[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.
This commit is contained in:
parent
691bd184e6
commit
6bd3f2e898
@ -2837,10 +2837,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;
|
||||
@ -2850,10 +2849,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;
|
||||
|
||||
@ -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(ReturnTy, 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
|
||||
@ -4922,24 +4968,12 @@ 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
|
||||
// signature. This requires revising the API of CreateRuntimeFunction().
|
||||
// signature. The other overload of CreateRuntimeFunction does this; it
|
||||
// should be used for new code.
|
||||
markRegisterParameterAttributes(F);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1247,11 +1247,23 @@ public:
|
||||
/// Create or return a runtime function declaration with the specified type
|
||||
/// and name. If \p AssumeConvergent is true, the call will have the
|
||||
/// convergent attribute added.
|
||||
///
|
||||
/// For new code, please use the overload that takes a QualType; it sets
|
||||
/// function attributes more accurately.
|
||||
llvm::FunctionCallee
|
||||
CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name,
|
||||
llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
|
||||
bool Local = false, bool AssumeConvergent = false);
|
||||
|
||||
/// Create or return a runtime function declaration with the specified type
|
||||
/// and name. If \p AssumeConvergent is true, the call will have the
|
||||
/// convergent attribute added.
|
||||
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);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=CHECK --check-prefix=SIG_STR %s
|
||||
// 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
|
||||
// RUN: %clang_cc1 -triple s390x-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=SYSTEMZ %s
|
||||
|
||||
// SIG_STR: @[[STR:.*]] = private unnamed_addr constant [6 x i8] c"v4@?0\00", align 1
|
||||
// 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) {
|
||||
// CHECK-NEXT: call void @_Block_object_assign(ptr %[[V5]], ptr %[[BLOCKCOPY_SRC]], i32 8)
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
// SYSTEMZ: declare void @_Block_object_assign(ptr noundef, ptr noundef, i32 noundef signext)
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_4_20r(ptr noundef %0) unnamed_addr
|
||||
// CHECK: %[[_ADDR:.*]] = alloca ptr, align 4
|
||||
// CHECK-NEXT: store ptr %0, ptr %[[_ADDR]], align 4
|
||||
@ -59,6 +62,8 @@ void (^test1)(void) = ^(void) {
|
||||
// CHECK-NEXT: call void @_Block_object_dispose(ptr %[[V3]], i32 8)
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
// SYSTEMZ: declare void @_Block_object_dispose(ptr noundef, i32 noundef signext)
|
||||
|
||||
typedef double ftype(double);
|
||||
// It's not clear that we *should* support this syntax, but until that decision
|
||||
// is made, we should support it properly and not crash.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user