|
27 | 27 | #include "swift/AST/TypeMemberVisitor.h"
|
28 | 28 | #include "swift/AST/Types.h"
|
29 | 29 | #include "swift/ClangImporter/ClangModule.h"
|
| 30 | +#include "swift/Demangling/ManglingMacros.h" |
30 | 31 | #include "swift/IRGen/Linking.h"
|
| 32 | +#include "swift/Runtime/HeapObject.h" |
31 | 33 | #include "swift/SIL/FormalLinkage.h"
|
32 | 34 | #include "swift/SIL/SILDebugScope.h"
|
33 | 35 | #include "swift/SIL/SILModule.h"
|
@@ -3079,6 +3081,169 @@ llvm::Constant *IRGenModule::getAddrOfGlobalUTF16String(StringRef utf8) {
|
3079 | 3081 | return address;
|
3080 | 3082 | }
|
3081 | 3083 |
|
| 3084 | +static llvm::Constant *getMetatypeDeclarationFor(IRGenModule &IGM, |
| 3085 | + StringRef name) { |
| 3086 | + auto *storageType = IGM.ObjCClassStructTy; |
| 3087 | + |
| 3088 | + // We may have defined the variable already. |
| 3089 | + if (auto existing = IGM.Module.getNamedGlobal(name)) |
| 3090 | + return getElementBitCast(existing, storageType); |
| 3091 | + |
| 3092 | + auto linkage = llvm::GlobalValue::ExternalLinkage; |
| 3093 | + auto visibility = llvm::GlobalValue::DefaultVisibility; |
| 3094 | + auto storageClass = llvm::GlobalValue::DefaultStorageClass; |
| 3095 | + |
| 3096 | + auto var = new llvm::GlobalVariable(IGM.Module, storageType, |
| 3097 | + /*constant*/ false, linkage, |
| 3098 | + /*initializer*/ nullptr, name); |
| 3099 | + var->setVisibility(visibility); |
| 3100 | + var->setDLLStorageClass(storageClass); |
| 3101 | + var->setAlignment(IGM.getPointerAlignment().getValue()); |
| 3102 | + |
| 3103 | + return var; |
| 3104 | +} |
| 3105 | +#define STRINGIFY_IMPL(x) #x |
| 3106 | +#define REALLY_STRINGIFY( x) STRINGIFY_IMPL(x) |
| 3107 | + |
| 3108 | +llvm::Constant * |
| 3109 | +IRGenModule::getAddrOfGlobalConstantString(StringRef utf8) { |
| 3110 | + auto &entry = GlobalConstantStrings[utf8]; |
| 3111 | + if (entry) |
| 3112 | + return entry; |
| 3113 | + |
| 3114 | + // If not, create it. This implicitly adds a trailing null. |
| 3115 | + auto data = llvm::ConstantDataArray::getString(LLVMContext, utf8); |
| 3116 | + auto *dataTy = data->getType(); |
| 3117 | + |
| 3118 | + llvm::Type *constantStringTy[] = { |
| 3119 | + RefCountedStructTy, |
| 3120 | + Int32Ty, |
| 3121 | + Int32Ty, |
| 3122 | + Int8Ty, |
| 3123 | + dataTy |
| 3124 | + }; |
| 3125 | + auto *ConstantStringTy = |
| 3126 | + llvm::StructType::get(getLLVMContext(), constantStringTy, |
| 3127 | + /*packed*/ false); |
| 3128 | + |
| 3129 | + auto metaclass = getMetatypeDeclarationFor( |
| 3130 | + *this, REALLY_STRINGIFY(CLASS_METADATA_SYM(s20_Latin1StringStorage))); |
| 3131 | + |
| 3132 | + metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy); |
| 3133 | + |
| 3134 | + // Get a reference count of two. |
| 3135 | + auto *strongRefCountInit = llvm::ConstantInt::get( |
| 3136 | + Int32Ty, |
| 3137 | + InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/) |
| 3138 | + .getBitsValue()); |
| 3139 | + auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0); |
| 3140 | + |
| 3141 | + auto *count = llvm::ConstantInt::get(Int32Ty, utf8.size()); |
| 3142 | + // Capacitity is length plus one because of the implicitly added '\0' |
| 3143 | + // character. |
| 3144 | + auto *capacity = llvm::ConstantInt::get(Int32Ty, utf8.size() + 1); |
| 3145 | + auto *flags = llvm::ConstantInt::get(Int8Ty, 0); |
| 3146 | + |
| 3147 | + // FIXME: Big endian-ness. |
| 3148 | + llvm::Constant *heapObjectHeaderFields[] = { |
| 3149 | + metaclass, strongRefCountInit, unownedRefCountInit |
| 3150 | + }; |
| 3151 | + |
| 3152 | + auto *initRefCountStruct = llvm::ConstantStruct::get( |
| 3153 | + RefCountedStructTy, makeArrayRef(heapObjectHeaderFields)); |
| 3154 | + |
| 3155 | + llvm::Constant *fields[] = { |
| 3156 | + initRefCountStruct, count, capacity, flags, data}; |
| 3157 | + auto *init = |
| 3158 | + llvm::ConstantStruct::get(ConstantStringTy, makeArrayRef(fields)); |
| 3159 | + |
| 3160 | + auto global = new llvm::GlobalVariable(Module, init->getType(), true, |
| 3161 | + llvm::GlobalValue::PrivateLinkage, |
| 3162 | + init); |
| 3163 | + global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
| 3164 | + |
| 3165 | + // Cache string entry. |
| 3166 | + entry = global; |
| 3167 | + |
| 3168 | + return global; |
| 3169 | +} |
| 3170 | + |
| 3171 | +llvm::Constant * |
| 3172 | +IRGenModule::getAddrOfGlobalUTF16ConstantString(StringRef utf8) { |
| 3173 | + auto &entry = GlobalConstantUTF16Strings[utf8]; |
| 3174 | + if (entry) |
| 3175 | + return entry; |
| 3176 | + |
| 3177 | + // If not, first transcode it to UTF16. |
| 3178 | + SmallVector<llvm::UTF16, 128> buffer(utf8.size() + 1); // +1 for ending nulls. |
| 3179 | + const llvm::UTF8 *fromPtr = (const llvm::UTF8 *) utf8.data(); |
| 3180 | + llvm::UTF16 *toPtr = &buffer[0]; |
| 3181 | + (void) ConvertUTF8toUTF16(&fromPtr, fromPtr + utf8.size(), |
| 3182 | + &toPtr, toPtr + utf8.size(), |
| 3183 | + llvm::strictConversion); |
| 3184 | + |
| 3185 | + // The length of the transcoded string in UTF-8 code points. |
| 3186 | + size_t utf16Length = toPtr - &buffer[0]; |
| 3187 | + |
| 3188 | + // Null-terminate the UTF-16 string. |
| 3189 | + *toPtr = 0; |
| 3190 | + ArrayRef<llvm::UTF16> utf16(&buffer[0], utf16Length + 1); |
| 3191 | + |
| 3192 | + auto *data = llvm::ConstantDataArray::get(LLVMContext, utf16); |
| 3193 | + auto *dataTy = data->getType(); |
| 3194 | + |
| 3195 | + llvm::Type *constantUTFStringTy[] = { |
| 3196 | + RefCountedStructTy, |
| 3197 | + Int32Ty, |
| 3198 | + Int32Ty, |
| 3199 | + Int8Ty, |
| 3200 | + Int8Ty, // For 16-byte alignment. |
| 3201 | + dataTy |
| 3202 | + }; |
| 3203 | + auto *ConstantUTFStringTy = |
| 3204 | + llvm::StructType::get(getLLVMContext(), constantUTFStringTy, |
| 3205 | + /*packed*/ false); |
| 3206 | + |
| 3207 | + auto metaclass = getMetatypeDeclarationFor( |
| 3208 | + *this, REALLY_STRINGIFY(CLASS_METADATA_SYM(s19_UTF16StringStorage))); |
| 3209 | + |
| 3210 | + metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy); |
| 3211 | + |
| 3212 | + // Get a reference count of two. |
| 3213 | + auto *strongRefCountInit = llvm::ConstantInt::get( |
| 3214 | + Int32Ty, |
| 3215 | + InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/) |
| 3216 | + .getBitsValue()); |
| 3217 | + auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0); |
| 3218 | + |
| 3219 | + auto *count = llvm::ConstantInt::get(Int32Ty, utf16Length); |
| 3220 | + auto *capacity = llvm::ConstantInt::get(Int32Ty, utf16Length + 1); |
| 3221 | + auto *flags = llvm::ConstantInt::get(Int8Ty, 0); |
| 3222 | + auto *padding = llvm::ConstantInt::get(Int8Ty, 0); |
| 3223 | + |
| 3224 | + llvm::Constant *heapObjectHeaderFields[] = { |
| 3225 | + metaclass, strongRefCountInit, unownedRefCountInit |
| 3226 | + }; |
| 3227 | + |
| 3228 | + auto *initRefCountStruct = llvm::ConstantStruct::get( |
| 3229 | + RefCountedStructTy, makeArrayRef(heapObjectHeaderFields)); |
| 3230 | + |
| 3231 | + llvm::Constant *fields[] = { |
| 3232 | + initRefCountStruct, count, capacity, flags, padding, data}; |
| 3233 | + auto *init = |
| 3234 | + llvm::ConstantStruct::get(ConstantUTFStringTy, makeArrayRef(fields)); |
| 3235 | + |
| 3236 | + auto global = new llvm::GlobalVariable(Module, init->getType(), true, |
| 3237 | + llvm::GlobalValue::PrivateLinkage, |
| 3238 | + init); |
| 3239 | + global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); |
| 3240 | + |
| 3241 | + // Cache string entry. |
| 3242 | + entry = global; |
| 3243 | + |
| 3244 | + return global; |
| 3245 | +} |
| 3246 | + |
3082 | 3247 | /// Do we have to use resilient access patterns when working with this
|
3083 | 3248 | /// declaration?
|
3084 | 3249 | ///
|
|
0 commit comments