Skip to content

Commit

Permalink
[clang codegen] Add CreateRuntimeFunction overload that takes a clang…
Browse files Browse the repository at this point in the history
… type.

Correctly computing the LLVM types/attributes is complicated in general,
so add a variant which does that for you.
  • Loading branch information
efriedma-quic committed Oct 23, 2024
1 parent e78f53d commit 852334c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 22 deletions.
14 changes: 6 additions & 8 deletions clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2839,10 +2839,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() {
if (BlockObjectDispose)
return BlockObjectDispose;

llvm::Type *args[] = { Int8PtrTy, Int32Ty };
llvm::FunctionType *fty
= llvm::FunctionType::get(VoidTy, args, false);
BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
QualType args[] = {Context.VoidPtrTy, Context.IntTy};
BlockObjectDispose =
CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_dispose");
configureBlocksRuntimeObject(
*this, cast<llvm::Constant>(BlockObjectDispose.getCallee()));
return BlockObjectDispose;
Expand All @@ -2852,10 +2851,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() {
if (BlockObjectAssign)
return BlockObjectAssign;

llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
llvm::FunctionType *fty
= llvm::FunctionType::get(VoidTy, args, false);
BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
QualType args[] = {Context.VoidPtrTy, Context.VoidPtrTy, Context.IntTy};
BlockObjectAssign =
CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_assign");
configureBlocksRuntimeObject(
*this, cast<llvm::Constant>(BlockObjectAssign.getCallee()));
return BlockObjectAssign;
Expand Down
61 changes: 47 additions & 14 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4903,6 +4903,52 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
return nullptr;
}

static void setWindowsItaniumDLLImport(CodeGenModule &CGM, bool Local,
llvm::Function *F, StringRef Name) {
// In Windows Itanium environments, try to mark runtime functions
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
// will link their standard library statically or dynamically. Marking
// functions imported when they are not imported can cause linker errors
// and warnings.
if (!Local && CGM.getTriple().isWindowsItaniumEnvironment() &&
!CGM.getCodeGenOpts().LTOVisibilityPublicStd) {
const FunctionDecl *FD = GetRuntimeFunctionDecl(CGM.getContext(), Name);
if (!FD || FD->hasAttr<DLLImportAttr>()) {
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
}

llvm::FunctionCallee CodeGenModule::CreateRuntimeFunction(
QualType ReturnTy, ArrayRef<QualType> ArgTys, StringRef Name,
llvm::AttributeList ExtraAttrs, bool Local, bool AssumeConvergent) {
if (AssumeConvergent) {
ExtraAttrs =
ExtraAttrs.addFnAttribute(VMContext, llvm::Attribute::Convergent);
}

QualType FTy = Context.getFunctionType(Context.VoidTy, ArgTys,
FunctionProtoType::ExtProtoInfo());
const CGFunctionInfo &Info = getTypes().arrangeFreeFunctionType(
Context.getCanonicalType(FTy).castAs<FunctionProtoType>());
auto *ConvTy = getTypes().GetFunctionType(Info);
llvm::Constant *C = GetOrCreateLLVMFunction(
Name, ConvTy, GlobalDecl(), /*ForVTable=*/false,
/*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);

if (auto *F = dyn_cast<llvm::Function>(C)) {
if (F->empty()) {
SetLLVMFunctionAttributes(GlobalDecl(), Info, F, /*IsThunk*/ false);
// FIXME: Set calling-conv properly in ExtProtoInfo
F->setCallingConv(getRuntimeCC());
setWindowsItaniumDLLImport(*this, Local, F, Name);
setDSOLocal(F);
}
}
return {ConvTy, C};
}

/// CreateRuntimeFunction - Create a new runtime function with the specified
/// type and name.
llvm::FunctionCallee
Expand All @@ -4922,20 +4968,7 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
if (auto *F = dyn_cast<llvm::Function>(C)) {
if (F->empty()) {
F->setCallingConv(getRuntimeCC());

// In Windows Itanium environments, try to mark runtime functions
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
// will link their standard library statically or dynamically. Marking
// functions imported when they are not imported can cause linker errors
// and warnings.
if (!Local && getTriple().isWindowsItaniumEnvironment() &&
!getCodeGenOpts().LTOVisibilityPublicStd) {
const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
if (!FD || FD->hasAttr<DLLImportAttr>()) {
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
}
setWindowsItaniumDLLImport(*this, Local, F, Name);
setDSOLocal(F);
// FIXME: We should use CodeGenModule::SetLLVMFunctionAttributes() instead
// of trying to approximate the attributes using the LLVM function
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,12 @@ class CodeGenModule : public CodeGenTypeCache {
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
bool Local = false, bool AssumeConvergent = false);

llvm::FunctionCallee
CreateRuntimeFunction(QualType ReturnTy, ArrayRef<QualType> ArgTys,
StringRef Name,
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
bool Local = false, bool AssumeConvergent = false);

/// Create a new runtime global variable with the specified type and name.
llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name);
Expand Down

0 comments on commit 852334c

Please sign in to comment.