зеркало из https://github.com/microsoft/clang.git
Treat the weak export of block runtime symbols as a deployment-target
feature akin to the ARC runtime checks. Removes a terrible hack where IR gen needed to find the declarations of those symbols in the translation unit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139404 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
88914801a4
Коммит
13db5cfc4e
|
@ -139,6 +139,7 @@ public:
|
|||
|
||||
unsigned MRTD : 1; // -mrtd calling convention
|
||||
unsigned DelayedTemplateParsing : 1; // Delayed template parsing
|
||||
unsigned BlocksRuntimeOptional : 1; // The blocks runtime is not guaranteed
|
||||
|
||||
private:
|
||||
// We declare multibit enums as unsigned because MSVC insists on making enums
|
||||
|
@ -198,7 +199,7 @@ public:
|
|||
|
||||
ThreadsafeStatics = 1;
|
||||
POSIXThreads = 0;
|
||||
Blocks = 0;
|
||||
Blocks = BlocksRuntimeOptional = 0;
|
||||
EmitAllDecls = 0;
|
||||
MathErrno = 1;
|
||||
SignedOverflowBehavior = SOB_Undefined;
|
||||
|
|
|
@ -450,7 +450,9 @@ def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">,
|
|||
def femit_all_decls : Flag<"-femit-all-decls">,
|
||||
HelpText<"Emit all declarations, even if unused">;
|
||||
def fblocks : Flag<"-fblocks">,
|
||||
HelpText<"enable the 'blocks' language feature">;
|
||||
HelpText<"Enable the 'blocks' language feature">;
|
||||
def fblocks_runtime_optional : Flag<"-fblocks-runtime-optional">,
|
||||
HelpText<"Weakly link in the blocks runtime">;
|
||||
def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
|
||||
def fexceptions : Flag<"-fexceptions">,
|
||||
HelpText<"Enable support for exception handling">;
|
||||
|
|
|
@ -183,9 +183,16 @@ public:
|
|||
/// configureObjCRuntime - Configure the known properties of the
|
||||
/// Objective-C runtime for this platform.
|
||||
///
|
||||
/// FIXME: this doesn't really belong here.
|
||||
/// FIXME: this really belongs on some sort of DeploymentTarget abstraction
|
||||
virtual void configureObjCRuntime(ObjCRuntime &runtime) const;
|
||||
|
||||
/// hasBlocksRuntime - Given that the user is compiling with
|
||||
/// -fblocks, does this tool chain guarantee the existence of a
|
||||
/// blocks runtime?
|
||||
///
|
||||
/// FIXME: this really belongs on some sort of DeploymentTarget abstraction
|
||||
virtual bool hasBlocksRuntime() const { return true; }
|
||||
|
||||
// GetCXXStdlibType - Determine the C++ standard library type to use with the
|
||||
// given compilation arguments.
|
||||
virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
|
||||
|
|
|
@ -1809,3 +1809,58 @@ void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
|
|||
|
||||
EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
|
||||
}
|
||||
|
||||
/// Adjust the declaration of something from the blocks API.
|
||||
static void configureBlocksRuntimeObject(CodeGenModule &CGM,
|
||||
llvm::Constant *C) {
|
||||
if (!CGM.getLangOptions().BlocksRuntimeOptional) return;
|
||||
|
||||
llvm::GlobalValue *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
|
||||
if (GV->isDeclaration() &&
|
||||
GV->getLinkage() == llvm::GlobalValue::ExternalLinkage)
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
|
||||
}
|
||||
|
||||
llvm::Constant *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");
|
||||
configureBlocksRuntimeObject(*this, BlockObjectDispose);
|
||||
return BlockObjectDispose;
|
||||
}
|
||||
|
||||
llvm::Constant *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");
|
||||
configureBlocksRuntimeObject(*this, BlockObjectAssign);
|
||||
return BlockObjectAssign;
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
|
||||
if (NSConcreteGlobalBlock)
|
||||
return NSConcreteGlobalBlock;
|
||||
|
||||
NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock",
|
||||
Int8PtrTy->getPointerTo(), 0);
|
||||
configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
|
||||
return NSConcreteGlobalBlock;
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
|
||||
if (NSConcreteStackBlock)
|
||||
return NSConcreteStackBlock;
|
||||
|
||||
NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock",
|
||||
Int8PtrTy->getPointerTo(), 0);
|
||||
configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
|
||||
return NSConcreteStackBlock;
|
||||
}
|
||||
|
|
|
@ -2396,93 +2396,3 @@ void CodeGenModule::EmitCoverageFile() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
///@name Custom Runtime Function Interfaces
|
||||
///@{
|
||||
//
|
||||
// FIXME: These can be eliminated once we can have clients just get the required
|
||||
// AST nodes from the builtin tables.
|
||||
|
||||
llvm::Constant *CodeGenModule::getBlockObjectDispose() {
|
||||
if (BlockObjectDispose)
|
||||
return BlockObjectDispose;
|
||||
|
||||
DeclarationName DName(&Context.Idents.get("_Block_object_dispose"));
|
||||
DeclContext::lookup_result
|
||||
Lookup = Context.getTranslationUnitDecl()->lookup(DName);
|
||||
|
||||
// If there is an explicit decl, use that.
|
||||
if (Lookup.first != Lookup.second)
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*Lookup.first))
|
||||
return BlockObjectDispose =
|
||||
GetAddrOfFunction(FD, getTypes().GetFunctionType(FD));
|
||||
|
||||
// Otherwise construct the function by hand.
|
||||
llvm::Type *args[] = { Int8PtrTy, Int32Ty };
|
||||
llvm::FunctionType *fty
|
||||
= llvm::FunctionType::get(VoidTy, args, false);
|
||||
return BlockObjectDispose =
|
||||
CreateRuntimeFunction(fty, "_Block_object_dispose");
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::getBlockObjectAssign() {
|
||||
if (BlockObjectAssign)
|
||||
return BlockObjectAssign;
|
||||
|
||||
DeclarationName DName(&Context.Idents.get("_Block_object_assign"));
|
||||
DeclContext::lookup_result
|
||||
Lookup = Context.getTranslationUnitDecl()->lookup(DName);
|
||||
|
||||
// If there is an explicit decl, use that.
|
||||
if (Lookup.first != Lookup.second)
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*Lookup.first))
|
||||
return BlockObjectAssign =
|
||||
GetAddrOfFunction(FD, getTypes().GetFunctionType(FD));
|
||||
|
||||
// Otherwise construct the function by hand.
|
||||
llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
|
||||
llvm::FunctionType *fty
|
||||
= llvm::FunctionType::get(VoidTy, args, false);
|
||||
return BlockObjectAssign =
|
||||
CreateRuntimeFunction(fty, "_Block_object_assign");
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
|
||||
if (NSConcreteGlobalBlock)
|
||||
return NSConcreteGlobalBlock;
|
||||
|
||||
DeclarationName DName(&Context.Idents.get("_NSConcreteGlobalBlock"));
|
||||
DeclContext::lookup_result
|
||||
Lookup = Context.getTranslationUnitDecl()->lookup(DName);
|
||||
|
||||
// If there is an explicit decl, use that.
|
||||
if (Lookup.first != Lookup.second)
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(*Lookup.first))
|
||||
return NSConcreteGlobalBlock =
|
||||
GetAddrOfGlobalVar(VD, getTypes().ConvertType(VD->getType()));
|
||||
|
||||
// Otherwise construct the variable by hand.
|
||||
return NSConcreteGlobalBlock =
|
||||
CreateRuntimeVariable(Int8PtrTy, "_NSConcreteGlobalBlock");
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
|
||||
if (NSConcreteStackBlock)
|
||||
return NSConcreteStackBlock;
|
||||
|
||||
DeclarationName DName(&Context.Idents.get("_NSConcreteStackBlock"));
|
||||
DeclContext::lookup_result
|
||||
Lookup = Context.getTranslationUnitDecl()->lookup(DName);
|
||||
|
||||
// If there is an explicit decl, use that.
|
||||
if (Lookup.first != Lookup.second)
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(*Lookup.first))
|
||||
return NSConcreteStackBlock =
|
||||
GetAddrOfGlobalVar(VD, getTypes().ConvertType(VD->getType()));
|
||||
|
||||
// Otherwise construct the variable by hand.
|
||||
return NSConcreteStackBlock =
|
||||
CreateRuntimeVariable(Int8PtrTy, "_NSConcreteStackBlock");
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
@ -109,6 +109,14 @@ void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const {
|
|||
runtime.HasTerminate = false;
|
||||
}
|
||||
|
||||
/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
|
||||
bool Darwin::hasBlocksRuntime() const {
|
||||
if (isTargetIPhoneOS())
|
||||
return !isIPhoneOSVersionLT(3, 2);
|
||||
else
|
||||
return !isMacosxVersionLT(10, 6);
|
||||
}
|
||||
|
||||
// FIXME: Can we tablegen this?
|
||||
static const char *GetArmArchForMArch(StringRef Value) {
|
||||
if (Value == "armv6k")
|
||||
|
|
|
@ -187,6 +187,7 @@ public:
|
|||
virtual bool HasNativeLLVMSupport() const;
|
||||
|
||||
virtual void configureObjCRuntime(ObjCRuntime &runtime) const;
|
||||
virtual bool hasBlocksRuntime() const;
|
||||
|
||||
virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
|
||||
const char *BoundArch) const;
|
||||
|
|
|
@ -1718,6 +1718,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
|
||||
!Args.hasArg(options::OPT_fno_blocks))) {
|
||||
CmdArgs.push_back("-fblocks");
|
||||
|
||||
if (!Args.hasArg(options::OPT_fgnu_runtime) &&
|
||||
!getToolChain().hasBlocksRuntime())
|
||||
CmdArgs.push_back("-fblocks-runtime-optional");
|
||||
}
|
||||
|
||||
// -faccess-control is default.
|
||||
|
|
|
@ -665,6 +665,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
|
|||
Res.push_back("-pthread");
|
||||
if (Opts.Blocks)
|
||||
Res.push_back("-fblocks");
|
||||
if (Opts.BlocksRuntimeOptional)
|
||||
Res.push_back("-fblocks-runtime-optional");
|
||||
if (Opts.EmitAllDecls)
|
||||
Res.push_back("-femit-all-decls");
|
||||
if (Opts.MathErrno)
|
||||
|
@ -1667,6 +1669,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
|||
|
||||
Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
|
||||
Opts.Blocks = Args.hasArg(OPT_fblocks);
|
||||
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
|
||||
Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
|
||||
Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
|
||||
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -emit-llvm -o - %s | \
|
||||
// RUN: FileCheck %s
|
||||
|
||||
// CHECK: @_NSConcreteGlobalBlock = extern_weak global
|
||||
extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
|
||||
// CHECK: @_NSConcreteStackBlock = extern_weak global
|
||||
extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
|
||||
extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
|
||||
// CHECK: declare extern_weak void @_Block_object_assign
|
||||
extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
|
||||
// CHECK: declare extern_weak void @_Block_object_dispose
|
||||
|
||||
void *x = ^(){};
|
||||
|
||||
void f1(void (^a0)(void));
|
||||
|
||||
void f0() {
|
||||
__block int x;
|
||||
f1(^(void){ x = 1; });
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -emit-pch -o %t
|
||||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -include-pch %t -emit-llvm -o - | \
|
||||
// RUN: FileCheck %s
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
// CHECK: @_NSConcreteGlobalBlock = extern_weak global
|
||||
extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
|
||||
// CHECK: @_NSConcreteStackBlock = extern_weak global
|
||||
extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
|
||||
extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
|
||||
// CHECK: declare extern_weak void @_Block_object_assign
|
||||
extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
|
||||
// CHECK: declare extern_weak void @_Block_object_dispose
|
||||
|
||||
#else
|
||||
|
||||
void *x = ^(){};
|
||||
|
||||
void f1(void (^a0)(void));
|
||||
|
||||
void f0() {
|
||||
__block int x;
|
||||
f1(^(void){ x = 1; });
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,30 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -emit-pch -o %t
|
||||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks %s -include-pch %t -emit-llvm -o - | \
|
||||
// RUN: FileCheck %s
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
extern "C" {
|
||||
// CHECK: @_NSConcreteGlobalBlock = extern_weak global
|
||||
extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
|
||||
// CHECK: @_NSConcreteStackBlock = extern_weak global
|
||||
extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
|
||||
extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
|
||||
// CHECK: declare extern_weak void @_Block_object_assign
|
||||
extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
|
||||
// CHECK: declare extern_weak void @_Block_object_dispose
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void *x = ^(){};
|
||||
|
||||
void f1(void (^a0)(void));
|
||||
|
||||
void f0() {
|
||||
__block int x;
|
||||
f1(^(void){ x = 1; });
|
||||
}
|
||||
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче