forked from OSchip/llvm-project
[Clang][CodeGen][ObjC]: Fix CoreFoundation on ELF with `-fconstant-cfstrings`.
[Clang][CodeGen][ObjC]: Fix non-bridged CoreFoundation builds on ELF targets that use `-fconstant-cfstrings`. The original changes from differential for a similar patch to PE/COFF (https://reviews.llvm.org/D44491) did not check for an edge case where the global could be a constant which surfaced as an issue when building for ELF because of different linkage semantics. This patch addresses several issues with crashes related to CF builds on ELF as well as improves data layout by ensuring string literals that back the actual CFConstStrings end up in .rodata in line with Mach-O. Change itself tested with CoreFoundation on Linux x86_64 but should be valid for BSD-like systems as well that use ELF as the native object format. Differential Revision: https://reviews.llvm.org/D52344 llvm-svn: 342883
This commit is contained in:
parent
edefda48d2
commit
7c142a52e2
|
@ -4109,37 +4109,48 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
|
|||
|
||||
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
|
||||
llvm::Constant *Zeros[] = { Zero, Zero };
|
||||
|
||||
|
||||
// If we don't already have it, get __CFConstantStringClassReference.
|
||||
if (!CFConstantStringClassRef) {
|
||||
llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
|
||||
Ty = llvm::ArrayType::get(Ty, 0);
|
||||
llvm::GlobalValue *GV = cast<llvm::GlobalValue>(
|
||||
CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"));
|
||||
llvm::Constant *C =
|
||||
CreateRuntimeVariable(Ty, "__CFConstantStringClassReference");
|
||||
|
||||
if (getTriple().isOSBinFormatELF() || getTriple().isOSBinFormatCOFF()) {
|
||||
llvm::GlobalValue *GV = nullptr;
|
||||
|
||||
if ((GV = dyn_cast<llvm::GlobalValue>(C))) {
|
||||
IdentifierInfo &II = getContext().Idents.get(GV->getName());
|
||||
TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl();
|
||||
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
|
||||
|
||||
if (getTriple().isOSBinFormatCOFF()) {
|
||||
IdentifierInfo &II = getContext().Idents.get(GV->getName());
|
||||
TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl();
|
||||
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
|
||||
|
||||
const VarDecl *VD = nullptr;
|
||||
for (const auto &Result : DC->lookup(&II))
|
||||
if ((VD = dyn_cast<VarDecl>(Result)))
|
||||
break;
|
||||
|
||||
if (!VD || !VD->hasAttr<DLLExportAttr>()) {
|
||||
GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
} else {
|
||||
GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
const VarDecl *VD = nullptr;
|
||||
for (const auto &Result : DC->lookup(&II))
|
||||
if ((VD = dyn_cast<VarDecl>(Result)))
|
||||
break;
|
||||
|
||||
if (getTriple().isOSBinFormatELF()) {
|
||||
if (!VD)
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
}
|
||||
else {
|
||||
if (!VD || !VD->hasAttr<DLLExportAttr>()) {
|
||||
GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
} else {
|
||||
GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
}
|
||||
}
|
||||
|
||||
setDSOLocal(GV);
|
||||
}
|
||||
}
|
||||
setDSOLocal(GV);
|
||||
|
||||
|
||||
// Decay array -> ptr
|
||||
CFConstantStringClassRef =
|
||||
llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros);
|
||||
llvm::ConstantExpr::getGetElementPtr(Ty, C, Zeros);
|
||||
}
|
||||
|
||||
QualType CFTy = getContext().getCFConstantStringType();
|
||||
|
@ -4185,7 +4196,11 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
|
|||
if (getTriple().isOSBinFormatMachO())
|
||||
GV->setSection(isUTF16 ? "__TEXT,__ustring"
|
||||
: "__TEXT,__cstring,cstring_literals");
|
||||
|
||||
// Make sure the literal ends up in .rodata to allow for safe ICF and for
|
||||
// the static linker to adjust permissions to read-only later on.
|
||||
else if (getTriple().isOSBinFormatELF())
|
||||
GV->setSection(".rodata");
|
||||
|
||||
// String.
|
||||
llvm::Constant *Str =
|
||||
llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-elf -DCF_BUILDING_CF -DDECL -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DECL
|
||||
// RUN: %clang_cc1 -triple x86_64-elf -DCF_BUILDING_CF -DDEFN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DEFN
|
||||
// RUN: %clang_cc1 -triple x86_64-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF
|
||||
// RUN: %clang_cc1 -triple x86_64-elf -DEXTERN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-EXTERN
|
||||
|
||||
// RUN: %clang_cc1 -Os -triple x86_64-elf -DCF_BUILDING_CF -DDECL -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DECL
|
||||
// RUN: %clang_cc1 -Os -triple x86_64-elf -DCF_BUILDING_CF -DDEFN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-IN-CF-DEFN
|
||||
// RUN: %clang_cc1 -Os -triple x86_64-elf -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF
|
||||
// RUN: %clang_cc1 -Os -triple x86_64-elf -DEXTERN -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-CF-EXTERN
|
||||
|
||||
|
||||
#if defined(CF_BUILDING_CF)
|
||||
#if defined(DECL)
|
||||
extern long __CFConstantStringClassReference[];
|
||||
#elif defined(DEFN)
|
||||
long __CFConstantStringClassReference[32];
|
||||
#endif
|
||||
#else
|
||||
#if defined(EXTERN)
|
||||
extern long __CFConstantStringClassReference[];
|
||||
#else
|
||||
long __CFConstantStringClassReference[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct __CFString *CFStringRef;
|
||||
const CFStringRef string = (CFStringRef)__builtin___CFStringMakeConstantString("string");
|
||||
|
||||
|
||||
// CHECK-CF-IN-CF-DECL: @__CFConstantStringClassReference = external global [0 x i32]
|
||||
// CHECK-CF-IN-CF-DEFN: @__CFConstantStringClassReference = common global [32 x i64] zeroinitializer, align 16
|
||||
// CHECK-CF: @__CFConstantStringClassReference = common global [1 x i64] zeroinitializer, align 8
|
||||
// CHECK-CF-EXTERN: @__CFConstantStringClassReference = external global [0 x i32]
|
||||
// CHECK-CF-EXTERN: @.str = private unnamed_addr constant [7 x i8] c"string\00", section ".rodata", align 1
|
Loading…
Reference in New Issue