Skip to content

Commit cd21d54

Browse files
committed
Fix some layering violations where CGObjCMac's NSString emission was
performed at the CodeGenModule level. Would be NFC except we now also use a different uniquing structure so that we don't get spurious conflicts if you ask for both an NSString and a CFString for the same content (which is possible with builtins). llvm-svn: 288287
1 parent 78a6953 commit cd21d54

File tree

3 files changed

+127
-135
lines changed

3 files changed

+127
-135
lines changed

clang/lib/CodeGen/CGObjCMac.cpp

Lines changed: 127 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,15 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
888888
/// DefinedNonLazyCategories - List of defined "non-lazy" categories.
889889
SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
890890

891+
/// Cached reference to the class for constant strings. This value has type
892+
/// int * but is actually an Obj-C class pointer.
893+
llvm::WeakVH ConstantStringClassRef;
894+
895+
/// \brief The LLVM type corresponding to NSConstantString.
896+
llvm::StructType *NSConstantStringType = nullptr;
897+
898+
llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
899+
891900
/// GetNameForMethod - Return a name for the given method.
892901
/// \param[out] NameOut - The return value.
893902
void GetNameForMethod(const ObjCMethodDecl *OMD,
@@ -1054,6 +1063,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
10541063
}
10551064

10561065
ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
1066+
ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
10571067

10581068
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
10591069
const ObjCContainerDecl *CD=nullptr) override;
@@ -1070,6 +1080,9 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
10701080
/// forward references will be filled in with empty bodies if no
10711081
/// definition is seen. The return value has type ProtocolPtrTy.
10721082
virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
1083+
1084+
virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1085+
10731086
llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
10741087
const CGBlockInfo &blockInfo) override;
10751088
llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
@@ -1266,6 +1279,8 @@ class CGObjCMac : public CGObjCCommonMac {
12661279
public:
12671280
CGObjCMac(CodeGen::CodeGenModule &cgm);
12681281

1282+
llvm::Constant *getNSConstantStringClassRef() override;
1283+
12691284
llvm::Function *ModuleInitFunction() override;
12701285

12711286
CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
@@ -1536,7 +1551,9 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
15361551

15371552
public:
15381553
CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1539-
// FIXME. All stubs for now!
1554+
1555+
llvm::Constant *getNSConstantStringClassRef() override;
1556+
15401557
llvm::Function *ModuleInitFunction() override;
15411558

15421559
CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
@@ -1846,11 +1863,115 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) {
18461863
};
18471864
*/
18481865

1849-
ConstantAddress CGObjCCommonMac::GenerateConstantString(
1850-
const StringLiteral *SL) {
1851-
return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
1852-
CGM.GetAddrOfConstantCFString(SL) :
1853-
CGM.GetAddrOfConstantString(SL));
1866+
ConstantAddress
1867+
CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
1868+
return (!CGM.getLangOpts().NoConstantCFStrings
1869+
? CGM.GetAddrOfConstantCFString(SL)
1870+
: GenerateConstantNSString(SL));
1871+
}
1872+
1873+
static llvm::StringMapEntry<llvm::GlobalVariable *> &
1874+
GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
1875+
const StringLiteral *Literal, unsigned &StringLength) {
1876+
StringRef String = Literal->getString();
1877+
StringLength = String.size();
1878+
return *Map.insert(std::make_pair(String, nullptr)).first;
1879+
}
1880+
1881+
llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1882+
if (llvm::Value *V = ConstantStringClassRef)
1883+
return cast<llvm::Constant>(V);
1884+
1885+
auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1886+
std::string str =
1887+
StringClass.empty() ? "_NSConstantStringClassReference"
1888+
: "_" + StringClass + "ClassReference";
1889+
1890+
llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
1891+
auto GV = CGM.CreateRuntimeVariable(PTy, str);
1892+
auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1893+
ConstantStringClassRef = V;
1894+
return V;
1895+
}
1896+
1897+
llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1898+
if (llvm::Value *V = ConstantStringClassRef)
1899+
return cast<llvm::Constant>(V);
1900+
1901+
auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1902+
std::string str =
1903+
StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
1904+
: "OBJC_CLASS_$_" + StringClass;
1905+
auto GV = GetClassGlobal(str);
1906+
1907+
// Make sure the result is of the correct type.
1908+
auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1909+
1910+
ConstantStringClassRef = V;
1911+
return V;
1912+
}
1913+
1914+
ConstantAddress
1915+
CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
1916+
unsigned StringLength = 0;
1917+
llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1918+
GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
1919+
1920+
if (auto *C = Entry.second)
1921+
return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
1922+
1923+
// If we don't already have it, get _NSConstantStringClassReference.
1924+
llvm::Constant *Class = getNSConstantStringClassRef();
1925+
1926+
// If we don't already have it, construct the type for a constant NSString.
1927+
if (!NSConstantStringType) {
1928+
NSConstantStringType =
1929+
llvm::StructType::create({
1930+
CGM.Int32Ty->getPointerTo(),
1931+
CGM.Int8PtrTy,
1932+
CGM.IntTy
1933+
}, "struct.__builtin_NSString");
1934+
}
1935+
1936+
ConstantInitBuilder Builder(CGM);
1937+
auto Fields = Builder.beginStruct(NSConstantStringType);
1938+
1939+
// Class pointer.
1940+
Fields.add(Class);
1941+
1942+
// String pointer.
1943+
llvm::Constant *C =
1944+
llvm::ConstantDataArray::getString(VMContext, Entry.first());
1945+
1946+
llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
1947+
bool isConstant = !CGM.getLangOpts().WritableStrings;
1948+
1949+
auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
1950+
Linkage, C, ".str");
1951+
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1952+
// Don't enforce the target's minimum global alignment, since the only use
1953+
// of the string is via this class initializer.
1954+
GV->setAlignment(1);
1955+
Fields.addBitCast(GV, CGM.Int8PtrTy);
1956+
1957+
// String length.
1958+
Fields.addInt(CGM.IntTy, StringLength);
1959+
1960+
// The struct.
1961+
CharUnits Alignment = CGM.getPointerAlign();
1962+
GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
1963+
/*constant*/ true,
1964+
llvm::GlobalVariable::PrivateLinkage);
1965+
const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
1966+
const char *NSStringNonFragileABISection =
1967+
"__DATA,__objc_stringobj,regular,no_dead_strip";
1968+
// FIXME. Fix section.
1969+
GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
1970+
? NSStringNonFragileABISection
1971+
: NSStringSection);
1972+
Entry.second = GV;
1973+
1974+
return ConstantAddress(GV, Alignment);
18541975
}
18551976

18561977
enum {

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 0 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -3131,14 +3131,6 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
31313131
nullptr)).first;
31323132
}
31333133

3134-
static llvm::StringMapEntry<llvm::GlobalVariable *> &
3135-
GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
3136-
const StringLiteral *Literal, unsigned &StringLength) {
3137-
StringRef String = Literal->getString();
3138-
StringLength = String.size();
3139-
return *Map.insert(std::make_pair(String, nullptr)).first;
3140-
}
3141-
31423134
ConstantAddress
31433135
CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
31443136
unsigned StringLength = 0;
@@ -3265,120 +3257,6 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
32653257
return ConstantAddress(GV, Alignment);
32663258
}
32673259

3268-
ConstantAddress
3269-
CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
3270-
unsigned StringLength = 0;
3271-
llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
3272-
GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
3273-
3274-
if (auto *C = Entry.second)
3275-
return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
3276-
3277-
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
3278-
llvm::Constant *Zeros[] = { Zero, Zero };
3279-
llvm::Value *V;
3280-
// If we don't already have it, get _NSConstantStringClassReference.
3281-
if (!ConstantStringClassRef) {
3282-
std::string StringClass(getLangOpts().ObjCConstantStringClass);
3283-
llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
3284-
llvm::Constant *GV;
3285-
if (LangOpts.ObjCRuntime.isNonFragile()) {
3286-
std::string str =
3287-
StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
3288-
: "OBJC_CLASS_$_" + StringClass;
3289-
GV = getObjCRuntime().GetClassGlobal(str);
3290-
// Make sure the result is of the correct type.
3291-
llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
3292-
V = llvm::ConstantExpr::getBitCast(GV, PTy);
3293-
ConstantStringClassRef = V;
3294-
} else {
3295-
std::string str =
3296-
StringClass.empty() ? "_NSConstantStringClassReference"
3297-
: "_" + StringClass + "ClassReference";
3298-
llvm::Type *PTy = llvm::ArrayType::get(Ty, 0);
3299-
GV = CreateRuntimeVariable(PTy, str);
3300-
// Decay array -> ptr
3301-
V = llvm::ConstantExpr::getGetElementPtr(PTy, GV, Zeros);
3302-
ConstantStringClassRef = V;
3303-
}
3304-
} else
3305-
V = ConstantStringClassRef;
3306-
3307-
if (!NSConstantStringType) {
3308-
// Construct the type for a constant NSString.
3309-
RecordDecl *D = Context.buildImplicitRecord("__builtin_NSString");
3310-
D->startDefinition();
3311-
3312-
QualType FieldTypes[3];
3313-
3314-
// const int *isa;
3315-
FieldTypes[0] = Context.getPointerType(Context.IntTy.withConst());
3316-
// const char *str;
3317-
FieldTypes[1] = Context.getPointerType(Context.CharTy.withConst());
3318-
// unsigned int length;
3319-
FieldTypes[2] = Context.UnsignedIntTy;
3320-
3321-
// Create fields
3322-
for (unsigned i = 0; i < 3; ++i) {
3323-
FieldDecl *Field = FieldDecl::Create(Context, D,
3324-
SourceLocation(),
3325-
SourceLocation(), nullptr,
3326-
FieldTypes[i], /*TInfo=*/nullptr,
3327-
/*BitWidth=*/nullptr,
3328-
/*Mutable=*/false,
3329-
ICIS_NoInit);
3330-
Field->setAccess(AS_public);
3331-
D->addDecl(Field);
3332-
}
3333-
3334-
D->completeDefinition();
3335-
QualType NSTy = Context.getTagDeclType(D);
3336-
NSConstantStringType = cast<llvm::StructType>(getTypes().ConvertType(NSTy));
3337-
}
3338-
3339-
ConstantInitBuilder Builder(*this);
3340-
auto Fields = Builder.beginStruct(NSConstantStringType);
3341-
3342-
// Class pointer.
3343-
Fields.add(cast<llvm::ConstantExpr>(V));
3344-
3345-
// String pointer.
3346-
llvm::Constant *C =
3347-
llvm::ConstantDataArray::getString(VMContext, Entry.first());
3348-
3349-
llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
3350-
bool isConstant = !LangOpts.WritableStrings;
3351-
3352-
auto *GV = new llvm::GlobalVariable(getModule(), C->getType(), isConstant,
3353-
Linkage, C, ".str");
3354-
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
3355-
// Don't enforce the target's minimum global alignment, since the only use
3356-
// of the string is via this class initializer.
3357-
CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
3358-
GV->setAlignment(Align.getQuantity());
3359-
Fields.add(
3360-
llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros));
3361-
3362-
// String length.
3363-
Fields.addInt(IntTy, StringLength);
3364-
3365-
// The struct.
3366-
CharUnits Alignment = getPointerAlign();
3367-
GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
3368-
/*constant*/ true,
3369-
llvm::GlobalVariable::PrivateLinkage);
3370-
const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
3371-
const char *NSStringNonFragileABISection =
3372-
"__DATA,__objc_stringobj,regular,no_dead_strip";
3373-
// FIXME. Fix section.
3374-
GV->setSection(LangOpts.ObjCRuntime.isNonFragile()
3375-
? NSStringNonFragileABISection
3376-
: NSStringSection);
3377-
Entry.second = GV;
3378-
3379-
return ConstantAddress(GV, Alignment);
3380-
}
3381-
33823260
QualType CodeGenModule::getObjCFastEnumerationStateType() {
33833261
if (ObjCFastEnumerationStateType.isNull()) {
33843262
RecordDecl *D = Context.buildImplicitRecord("__objcFastEnumerationState");

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -434,13 +434,6 @@ class CodeGenModule : public CodeGenTypeCache {
434434
/// int * but is actually an Obj-C class pointer.
435435
llvm::WeakVH CFConstantStringClassRef;
436436

437-
/// Cached reference to the class for constant strings. This value has type
438-
/// int * but is actually an Obj-C class pointer.
439-
llvm::WeakVH ConstantStringClassRef;
440-
441-
/// \brief The LLVM type corresponding to NSConstantString.
442-
llvm::StructType *NSConstantStringType = nullptr;
443-
444437
/// \brief The type used to describe the state of a fast enumeration in
445438
/// Objective-C's for..in loop.
446439
QualType ObjCFastEnumerationStateType;

0 commit comments

Comments
 (0)