@@ -1355,9 +1355,11 @@ mlir::LogicalResult cir::GlobalOp::verify() {
13551355  return  success ();
13561356}
13571357
1358- void  cir::GlobalOp::build (OpBuilder &odsBuilder, OperationState &odsState,
1359-                           llvm::StringRef sym_name, mlir::Type sym_type,
1360-                           bool  isConstant, cir::GlobalLinkageKind linkage) {
1358+ void  cir::GlobalOp::build (
1359+     OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
1360+     mlir::Type sym_type, bool  isConstant, cir::GlobalLinkageKind linkage,
1361+     function_ref<void (OpBuilder &, Location)> ctorBuilder,
1362+     function_ref<void(OpBuilder &, Location)> dtorBuilder) {
13611363  odsState.addAttribute (getSymNameAttrName (odsState.name ),
13621364                        odsBuilder.getStringAttr (sym_name));
13631365  odsState.addAttribute (getSymTypeAttrName (odsState.name ),
@@ -1370,43 +1372,127 @@ void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState,
13701372      cir::GlobalLinkageKindAttr::get (odsBuilder.getContext (), linkage);
13711373  odsState.addAttribute (getLinkageAttrName (odsState.name ), linkageAttr);
13721374
1375+   Region *ctorRegion = odsState.addRegion ();
1376+   if  (ctorBuilder) {
1377+     odsBuilder.createBlock (ctorRegion);
1378+     ctorBuilder (odsBuilder, odsState.location );
1379+   }
1380+ 
1381+   Region *dtorRegion = odsState.addRegion ();
1382+   if  (dtorBuilder) {
1383+     odsBuilder.createBlock (dtorRegion);
1384+     dtorBuilder (odsBuilder, odsState.location );
1385+   }
1386+ 
13731387  odsState.addAttribute (getGlobalVisibilityAttrName (odsState.name ),
13741388                        cir::VisibilityAttr::get (odsBuilder.getContext ()));
13751389}
13761390
1391+ // / Given the region at `index`, or the parent operation if `index` is None,
1392+ // / return the successor regions. These are the regions that may be selected
1393+ // / during the flow of control. `operands` is a set of optional attributes that
1394+ // / correspond to a constant value for each operand, or null if that operand is
1395+ // / not a constant.
1396+ void  cir::GlobalOp::getSuccessorRegions (
1397+     mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1398+   //  The `ctor` and `dtor` regions always branch back to the parent operation.
1399+   if  (!point.isParent ()) {
1400+     regions.push_back (RegionSuccessor ());
1401+     return ;
1402+   }
1403+ 
1404+   //  Don't consider the ctor region if it is empty.
1405+   Region *ctorRegion = &this ->getCtorRegion ();
1406+   if  (ctorRegion->empty ())
1407+     ctorRegion = nullptr ;
1408+ 
1409+   //  Don't consider the dtor region if it is empty.
1410+   Region *dtorRegion = &this ->getCtorRegion ();
1411+   if  (dtorRegion->empty ())
1412+     dtorRegion = nullptr ;
1413+ 
1414+   //  If the condition isn't constant, both regions may be executed.
1415+   if  (ctorRegion)
1416+     regions.push_back (RegionSuccessor (ctorRegion));
1417+   if  (dtorRegion)
1418+     regions.push_back (RegionSuccessor (dtorRegion));
1419+ }
1420+ 
13771421static  void  printGlobalOpTypeAndInitialValue (OpAsmPrinter &p, cir::GlobalOp op,
1378-                                              TypeAttr type,
1379-                                              Attribute initAttr) {
1422+                                              TypeAttr type, Attribute initAttr,
1423+                                              mlir::Region &ctorRegion,
1424+                                              mlir::Region &dtorRegion) {
1425+   auto  printType = [&]() { p << " : "   << type; };
13801426  if  (!op.isDeclaration ()) {
13811427    p << " = "  ;
1382-     //  This also prints the type...
1383-     if  (initAttr)
1384-       printConstant (p, initAttr);
1428+     if  (!ctorRegion.empty ()) {
1429+       p << " ctor "  ;
1430+       printType ();
1431+       p << "  "  ;
1432+       p.printRegion (ctorRegion,
1433+                     /* printEntryBlockArgs=*/ false ,
1434+                     /* printBlockTerminators=*/ false );
1435+     } else  {
1436+       //  This also prints the type...
1437+       if  (initAttr)
1438+         printConstant (p, initAttr);
1439+     }
1440+ 
1441+     if  (!dtorRegion.empty ()) {
1442+       p << "  dtor "  ;
1443+       p.printRegion (dtorRegion,
1444+                     /* printEntryBlockArgs=*/ false ,
1445+                     /* printBlockTerminators=*/ false );
1446+     }
13851447  } else  {
1386-     p <<  " :  "  << type ;
1448+     printType () ;
13871449  }
13881450}
13891451
1390- static  ParseResult
1391- parseGlobalOpTypeAndInitialValue (OpAsmParser &parser, TypeAttr &typeAttr,
1392-                                  Attribute &initialValueAttr) {
1452+ static  ParseResult parseGlobalOpTypeAndInitialValue (OpAsmParser &parser,
1453+                                                     TypeAttr &typeAttr,
1454+                                                     Attribute &initialValueAttr,
1455+                                                     mlir::Region &ctorRegion,
1456+                                                     mlir::Region &dtorRegion) {
13931457  mlir::Type opTy;
13941458  if  (parser.parseOptionalEqual ().failed ()) {
13951459    //  Absence of equal means a declaration, so we need to parse the type.
13961460    //   cir.global @a : !cir.int<s, 32>
13971461    if  (parser.parseColonType (opTy))
13981462      return  failure ();
13991463  } else  {
1400-     //  Parse constant with initializer, examples:
1401-     //   cir.global @y = #cir.fp<1.250000e+00> : !cir.double
1402-     //   cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
1403-     if  (parseConstantValue (parser, initialValueAttr).failed ())
1404-       return  failure ();
1464+     //  Parse contructor, example:
1465+     //   cir.global @rgb = ctor : type { ... }
1466+     if  (!parser.parseOptionalKeyword (" ctor"  )) {
1467+       if  (parser.parseColonType (opTy))
1468+         return  failure ();
1469+       auto  parseLoc = parser.getCurrentLocation ();
1470+       if  (parser.parseRegion (ctorRegion, /* arguments=*/  {}, /* argTypes=*/  {}))
1471+         return  failure ();
1472+       if  (ensureRegionTerm (parser, ctorRegion, parseLoc).failed ())
1473+         return  failure ();
1474+     } else  {
1475+       //  Parse constant with initializer, examples:
1476+       //   cir.global @y = 3.400000e+00 : f32
1477+       //   cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
1478+       if  (parseConstantValue (parser, initialValueAttr).failed ())
1479+         return  failure ();
1480+ 
1481+       assert (mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1482+              " Non-typed attrs shouldn't appear here."  );
1483+       auto  typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1484+       opTy = typedAttr.getType ();
1485+     }
14051486
1406-     assert (mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1407-            " Non-typed attrs shouldn't appear here."  );
1408-     auto  typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1409-     opTy = typedAttr.getType ();
1487+     //  Parse destructor, example:
1488+     //    dtor { ... }
1489+     if  (!parser.parseOptionalKeyword (" dtor"  )) {
1490+       auto  parseLoc = parser.getCurrentLocation ();
1491+       if  (parser.parseRegion (dtorRegion, /* arguments=*/  {}, /* argTypes=*/  {}))
1492+         return  failure ();
1493+       if  (ensureRegionTerm (parser, dtorRegion, parseLoc).failed ())
1494+         return  failure ();
1495+     }
14101496  }
14111497
14121498  typeAttr = TypeAttr::get (opTy);
0 commit comments