Skip to content

Commit 6bd3f2e

Browse files
[clang codegen] Add CreateRuntimeFunction overload that takes a clang type. (#113506)
Correctly computing the LLVM types/attributes is complicated in general, so add a variant which does that for you.
1 parent 691bd18 commit 6bd3f2e

File tree

4 files changed

+72
-23
lines changed

4 files changed

+72
-23
lines changed

clang/lib/CodeGen/CGBlocks.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2837,10 +2837,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() {
28372837
if (BlockObjectDispose)
28382838
return BlockObjectDispose;
28392839

2840-
llvm::Type *args[] = { Int8PtrTy, Int32Ty };
2841-
llvm::FunctionType *fty
2842-
= llvm::FunctionType::get(VoidTy, args, false);
2843-
BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
2840+
QualType args[] = {Context.VoidPtrTy, Context.IntTy};
2841+
BlockObjectDispose =
2842+
CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_dispose");
28442843
configureBlocksRuntimeObject(
28452844
*this, cast<llvm::Constant>(BlockObjectDispose.getCallee()));
28462845
return BlockObjectDispose;
@@ -2850,10 +2849,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() {
28502849
if (BlockObjectAssign)
28512850
return BlockObjectAssign;
28522851

2853-
llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
2854-
llvm::FunctionType *fty
2855-
= llvm::FunctionType::get(VoidTy, args, false);
2856-
BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
2852+
QualType args[] = {Context.VoidPtrTy, Context.VoidPtrTy, Context.IntTy};
2853+
BlockObjectAssign =
2854+
CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_assign");
28572855
configureBlocksRuntimeObject(
28582856
*this, cast<llvm::Constant>(BlockObjectAssign.getCallee()));
28592857
return BlockObjectAssign;

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4903,6 +4903,52 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
49034903
return nullptr;
49044904
}
49054905

4906+
static void setWindowsItaniumDLLImport(CodeGenModule &CGM, bool Local,
4907+
llvm::Function *F, StringRef Name) {
4908+
// In Windows Itanium environments, try to mark runtime functions
4909+
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
4910+
// will link their standard library statically or dynamically. Marking
4911+
// functions imported when they are not imported can cause linker errors
4912+
// and warnings.
4913+
if (!Local && CGM.getTriple().isWindowsItaniumEnvironment() &&
4914+
!CGM.getCodeGenOpts().LTOVisibilityPublicStd) {
4915+
const FunctionDecl *FD = GetRuntimeFunctionDecl(CGM.getContext(), Name);
4916+
if (!FD || FD->hasAttr<DLLImportAttr>()) {
4917+
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
4918+
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
4919+
}
4920+
}
4921+
}
4922+
4923+
llvm::FunctionCallee CodeGenModule::CreateRuntimeFunction(
4924+
QualType ReturnTy, ArrayRef<QualType> ArgTys, StringRef Name,
4925+
llvm::AttributeList ExtraAttrs, bool Local, bool AssumeConvergent) {
4926+
if (AssumeConvergent) {
4927+
ExtraAttrs =
4928+
ExtraAttrs.addFnAttribute(VMContext, llvm::Attribute::Convergent);
4929+
}
4930+
4931+
QualType FTy = Context.getFunctionType(ReturnTy, ArgTys,
4932+
FunctionProtoType::ExtProtoInfo());
4933+
const CGFunctionInfo &Info = getTypes().arrangeFreeFunctionType(
4934+
Context.getCanonicalType(FTy).castAs<FunctionProtoType>());
4935+
auto *ConvTy = getTypes().GetFunctionType(Info);
4936+
llvm::Constant *C = GetOrCreateLLVMFunction(
4937+
Name, ConvTy, GlobalDecl(), /*ForVTable=*/false,
4938+
/*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);
4939+
4940+
if (auto *F = dyn_cast<llvm::Function>(C)) {
4941+
if (F->empty()) {
4942+
SetLLVMFunctionAttributes(GlobalDecl(), Info, F, /*IsThunk*/ false);
4943+
// FIXME: Set calling-conv properly in ExtProtoInfo
4944+
F->setCallingConv(getRuntimeCC());
4945+
setWindowsItaniumDLLImport(*this, Local, F, Name);
4946+
setDSOLocal(F);
4947+
}
4948+
}
4949+
return {ConvTy, C};
4950+
}
4951+
49064952
/// CreateRuntimeFunction - Create a new runtime function with the specified
49074953
/// type and name.
49084954
llvm::FunctionCallee
@@ -4922,24 +4968,12 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
49224968
if (auto *F = dyn_cast<llvm::Function>(C)) {
49234969
if (F->empty()) {
49244970
F->setCallingConv(getRuntimeCC());
4925-
4926-
// In Windows Itanium environments, try to mark runtime functions
4927-
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
4928-
// will link their standard library statically or dynamically. Marking
4929-
// functions imported when they are not imported can cause linker errors
4930-
// and warnings.
4931-
if (!Local && getTriple().isWindowsItaniumEnvironment() &&
4932-
!getCodeGenOpts().LTOVisibilityPublicStd) {
4933-
const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
4934-
if (!FD || FD->hasAttr<DLLImportAttr>()) {
4935-
F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
4936-
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
4937-
}
4938-
}
4971+
setWindowsItaniumDLLImport(*this, Local, F, Name);
49394972
setDSOLocal(F);
49404973
// FIXME: We should use CodeGenModule::SetLLVMFunctionAttributes() instead
49414974
// of trying to approximate the attributes using the LLVM function
4942-
// signature. This requires revising the API of CreateRuntimeFunction().
4975+
// signature. The other overload of CreateRuntimeFunction does this; it
4976+
// should be used for new code.
49434977
markRegisterParameterAttributes(F);
49444978
}
49454979
}

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,11 +1247,23 @@ class CodeGenModule : public CodeGenTypeCache {
12471247
/// Create or return a runtime function declaration with the specified type
12481248
/// and name. If \p AssumeConvergent is true, the call will have the
12491249
/// convergent attribute added.
1250+
///
1251+
/// For new code, please use the overload that takes a QualType; it sets
1252+
/// function attributes more accurately.
12501253
llvm::FunctionCallee
12511254
CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name,
12521255
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
12531256
bool Local = false, bool AssumeConvergent = false);
12541257

1258+
/// Create or return a runtime function declaration with the specified type
1259+
/// and name. If \p AssumeConvergent is true, the call will have the
1260+
/// convergent attribute added.
1261+
llvm::FunctionCallee
1262+
CreateRuntimeFunction(QualType ReturnTy, ArrayRef<QualType> ArgTys,
1263+
StringRef Name,
1264+
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
1265+
bool Local = false, bool AssumeConvergent = false);
1266+
12551267
/// Create a new runtime global variable with the specified type and name.
12561268
llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty,
12571269
StringRef Name);

clang/test/CodeGen/blocks.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=CHECK --check-prefix=SIG_STR %s
22
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks -fdisable-block-signature-string | FileCheck --check-prefix=CHECK --check-prefix=NO_SIG_STR %s
3+
// RUN: %clang_cc1 -triple s390x-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=SYSTEMZ %s
34

45
// SIG_STR: @[[STR:.*]] = private unnamed_addr constant [6 x i8] c"v4@?0\00", align 1
56
// SIG_STR: @{{.*}} = internal constant { ptr, i32, i32, ptr, ptr } { ptr @_NSConcreteGlobalBlock, i32 1342177280, i32 0, ptr @f_block_invoke, ptr @{{.*}} }, align 4
@@ -50,6 +51,8 @@ void (^test1)(void) = ^(void) {
5051
// CHECK-NEXT: call void @_Block_object_assign(ptr %[[V5]], ptr %[[BLOCKCOPY_SRC]], i32 8)
5152
// CHECK-NEXT: ret void
5253

54+
// SYSTEMZ: declare void @_Block_object_assign(ptr noundef, ptr noundef, i32 noundef signext)
55+
5356
// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_4_20r(ptr noundef %0) unnamed_addr
5457
// CHECK: %[[_ADDR:.*]] = alloca ptr, align 4
5558
// CHECK-NEXT: store ptr %0, ptr %[[_ADDR]], align 4
@@ -59,6 +62,8 @@ void (^test1)(void) = ^(void) {
5962
// CHECK-NEXT: call void @_Block_object_dispose(ptr %[[V3]], i32 8)
6063
// CHECK-NEXT: ret void
6164

65+
// SYSTEMZ: declare void @_Block_object_dispose(ptr noundef, i32 noundef signext)
66+
6267
typedef double ftype(double);
6368
// It's not clear that we *should* support this syntax, but until that decision
6469
// is made, we should support it properly and not crash.

0 commit comments

Comments
 (0)