================
@@ -693,6 +696,101 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
   op.erase();
 }
 
+cir::FuncOp LoweringPreparePass::getOrCreateDtorFunc(CIRBaseBuilderTy &builder,
+                                                     cir::GlobalOp op,
+                                                     mlir::Region &dtorRegion,
+                                                     cir::CallOp &dtorCall) {
+  assert(!cir::MissingFeatures::astVarDeclInterface());
+  assert(!cir::MissingFeatures::opGlobalThreadLocal());
+
+  cir::VoidType voidTy = builder.getVoidTy();
+  auto voidPtrTy = cir::PointerType::get(voidTy);
+
+  // Look for operations in dtorBlock
+  mlir::Block &dtorBlock = dtorRegion.front();
+
+  // The first operation should be a get_global to retrieve the address
+  // of the global variable we're destroying.
+  auto opIt = dtorBlock.getOperations().begin();
+  cir::GetGlobalOp ggop = mlir::cast<cir::GetGlobalOp>(*opIt);
+
+  // The simple case is just a call to a destructor, like this:
+  //
+  //   %0 = cir.get_global %globalS : !cir.ptr<!rec_S>
+  //   cir.call %_ZN1SD1Ev(%0) : (!cir.ptr<!rec_S>) -> ()
+  //   (implicit cir.yield)
+  //
+  // That is, if the second operation is a call that takes the get_global 
result
+  // as its only operand, and the only other operation is a yield, then we can
+  // just return the called function.
+  if (dtorBlock.getOperations().size() == 3) {
+    auto callOp = mlir::dyn_cast<cir::CallOp>(&*(++opIt));
+    auto yieldOp = mlir::dyn_cast<cir::YieldOp>(&*(++opIt));
+    if (yieldOp && callOp && callOp.getNumOperands() == 1 &&
+        callOp.getArgOperand(0) == ggop) {
+      dtorCall = callOp;
+      return getCalledFunction(callOp);
+    }
+  }
+
+  // Otherwise, we need to create a helper function to replace the dtor region.
+  // This name is kind of arbitrary, but it matches the name that classic
+  // codegen uses, based on the expected case that gets us here.
+  builder.setInsertionPointAfter(op);
+  SmallString<256> fnName("__cxx_global_array_dtor");
+  uint32_t cnt = dynamicInitializerNames[fnName]++;
+  if (cnt)
+    fnName += "." + llvm::Twine(cnt).str();
+
+  // Create the helper function.
+  auto fnType = cir::FuncType::get({voidPtrTy}, voidTy);
+  cir::FuncOp dtorFunc =
+      buildRuntimeFunction(builder, fnName, op.getLoc(), fnType,
+                           cir::GlobalLinkageKind::InternalLinkage);
+  mlir::Block *entryBB = dtorFunc.addEntryBlock();
+
+  // Move everything from the dtor region into the helper function.
+  entryBB->getOperations().splice(entryBB->begin(), dtorBlock.getOperations(),
+                                  dtorBlock.begin(), dtorBlock.end());
+
+  // Before erasing this, clone it back into the dtor region
+  cir::GetGlobalOp dtorGGop =
+      mlir::cast<cir::GetGlobalOp>(entryBB->getOperations().front());
+  builder.setInsertionPointToStart(&dtorBlock);
+  builder.clone(*dtorGGop.getOperation());
----------------
erichkeane wrote:

Do you have to clone it? Could you just 'move' it instead?  Particularly since 
you're destroying this...

https://github.com/llvm/llvm-project/pull/169070
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to