[clang] [CIR] Implement inline builtin functions (PR #163911)

Henrich Lauko via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 16 23:08:17 PDT 2025


================
@@ -551,6 +551,50 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
   const auto funcDecl = cast<FunctionDecl>(gd.getDecl());
   curGD = gd;
 
+  if (funcDecl->isInlineBuiltinDeclaration()) {
+    // When generating code for a builtin with an inline declaration, use a
+    // mangled name to hold the actual body, while keeping an external
+    // declaration in case the function pointer is referenced somewhere.
+    std::string fdInlineName = fn.getName().str() + ".inline";
+    cir::FuncOp clone =
+        mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
+    if (!clone) {
+      mlir::OpBuilder::InsertionGuard guard(builder);
+      builder.setInsertionPoint(fn);
+      clone = builder.create<cir::FuncOp>(fn.getLoc(), fdInlineName,
+                                          fn.getFunctionType());
+      clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
+          &cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
+      clone.setSymVisibility("private");
+      clone.setInlineKindAttr(cir::InlineAttr::get(
+          &cgm.getMLIRContext(), cir::InlineKind::AlwaysInline));
+    }
+    fn.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
+        &cgm.getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
+    fn.setSymVisibility("private");
+    fn = clone;
+  } else {
+    // Detect the unusual situation where an inline version is shadowed by a
+    // non-inline version. In that case we should pick the external one
+    // everywhere. That's GCC behavior too.
+    for (const FunctionDecl *pd = funcDecl->getPreviousDecl(); pd;
+         pd = pd->getPreviousDecl()) {
+      if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {
+        std::string inlineName = funcDecl->getName().str() + ".inline";
+        if (auto inlineFn = mlir::cast_or_null<cir::FuncOp>(
+                cgm.getGlobalValue(inlineName))) {
+          // Replace all uses of the .inline function with the regular function
+          if (inlineFn
+                  .replaceAllSymbolUses(fn.getSymNameAttr(), cgm.getModule())
+                  .failed())
----------------
xlauko wrote:

This is quite expensive operation that does linear walk of entire module. 
Might be worth to think about some precached symbol uses or at least leave a FIXME comment.

https://github.com/llvm/llvm-project/pull/163911


More information about the cfe-commits mailing list