diff options
author | serge-sans-paille <sguelton@redhat.com> | 2021-10-02 23:17:30 +0200 |
---|---|---|
committer | serge-sans-paille <sguelton@redhat.com> | 2021-10-04 22:26:25 +0200 |
commit | 0f0e31cf511def3e92244e615b2646c1fd0df0cd (patch) | |
tree | d9b072d4f2d685eee978c3280cef181d5411b59d /clang/lib/CodeGen/CodeGenFunction.cpp | |
parent | a4bccf7afdd0c5d849cd640ad8be371c2a62da73 (diff) | |
download | llvm-0f0e31cf511def3e92244e615b2646c1fd0df0cd.zip llvm-0f0e31cf511def3e92244e615b2646c1fd0df0cd.tar.gz llvm-0f0e31cf511def3e92244e615b2646c1fd0df0cd.tar.bz2 |
Update inline builtin handling to honor gnu inline attribute
Per the GCC info page:
If the function is declared 'extern', then this definition of the
function is used only for inlining. In no case is the function
compiled as a standalone function, not even if you take its address
explicitly. Such an address becomes an external reference, as if
you had only declared the function, and had not defined it.
Respect that behavior for inline builtins: keep the original definition, and
generate a copy of the declaration suffixed by '.inline' that's only referenced
in direct call.
This fixes holes in c3717b6858d32d64514a187ede1a77be8ba4e542.
Differential Revision: https://reviews.llvm.org/D111009
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index da9a530..13bc366 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/CRC.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" + using namespace clang; using namespace CodeGen; @@ -1294,10 +1295,22 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, FunctionArgList Args; QualType ResTy = BuildFunctionArgList(GD, Args); - // Give a different name to inline builtin to avoid conflict with actual - // builtins. - if (FD->isInlineBuiltinDeclaration() && Fn) - Fn->setName(Fn->getName() + ".inline"); + // When generating code for a builtin with an inline declaration, use a + // mangled name to hold the actual body, while keeping an external definition + // in case the function pointer is referenced somewhere. + if (FD->isInlineBuiltinDeclaration() && Fn) { + std::string FDInlineName = (Fn->getName() + ".inline").str(); + llvm::Module *M = Fn->getParent(); + llvm::Function *Clone = M->getFunction(FDInlineName); + if (!Clone) { + Clone = llvm::Function::Create(Fn->getFunctionType(), + llvm::GlobalValue::InternalLinkage, + Fn->getAddressSpace(), FDInlineName, M); + Clone->addFnAttr(llvm::Attribute::AlwaysInline); + } + Fn->setLinkage(llvm::GlobalValue::ExternalLinkage); + Fn = Clone; + } // Check if we should generate debug info for this function. if (FD->hasAttr<NoDebugAttr>()) { |