@@ -888,6 +888,15 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
888
888
// / DefinedNonLazyCategories - List of defined "non-lazy" categories.
889
889
SmallVector<llvm::GlobalValue*, 16 > DefinedNonLazyCategories;
890
890
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
+
891
900
// / GetNameForMethod - Return a name for the given method.
892
901
// / \param[out] NameOut - The return value.
893
902
void GetNameForMethod (const ObjCMethodDecl *OMD,
@@ -1054,6 +1063,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
1054
1063
}
1055
1064
1056
1065
ConstantAddress GenerateConstantString (const StringLiteral *SL) override ;
1066
+ ConstantAddress GenerateConstantNSString (const StringLiteral *SL);
1057
1067
1058
1068
llvm::Function *GenerateMethod (const ObjCMethodDecl *OMD,
1059
1069
const ObjCContainerDecl *CD=nullptr ) override ;
@@ -1070,6 +1080,9 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
1070
1080
// / forward references will be filled in with empty bodies if no
1071
1081
// / definition is seen. The return value has type ProtocolPtrTy.
1072
1082
virtual llvm::Constant *GetOrEmitProtocolRef (const ObjCProtocolDecl *PD)=0;
1083
+
1084
+ virtual llvm::Constant *getNSConstantStringClassRef () = 0;
1085
+
1073
1086
llvm::Constant *BuildGCBlockLayout (CodeGen::CodeGenModule &CGM,
1074
1087
const CGBlockInfo &blockInfo) override ;
1075
1088
llvm::Constant *BuildRCBlockLayout (CodeGen::CodeGenModule &CGM,
@@ -1266,6 +1279,8 @@ class CGObjCMac : public CGObjCCommonMac {
1266
1279
public:
1267
1280
CGObjCMac (CodeGen::CodeGenModule &cgm);
1268
1281
1282
+ llvm::Constant *getNSConstantStringClassRef () override ;
1283
+
1269
1284
llvm::Function *ModuleInitFunction () override ;
1270
1285
1271
1286
CodeGen::RValue GenerateMessageSend (CodeGen::CodeGenFunction &CGF,
@@ -1536,7 +1551,9 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
1536
1551
1537
1552
public:
1538
1553
CGObjCNonFragileABIMac (CodeGen::CodeGenModule &cgm);
1539
- // FIXME. All stubs for now!
1554
+
1555
+ llvm::Constant *getNSConstantStringClassRef () override ;
1556
+
1540
1557
llvm::Function *ModuleInitFunction () override ;
1541
1558
1542
1559
CodeGen::RValue GenerateMessageSend (CodeGen::CodeGenFunction &CGF,
@@ -1846,11 +1863,115 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) {
1846
1863
};
1847
1864
*/
1848
1865
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);
1854
1975
}
1855
1976
1856
1977
enum {
0 commit comments