llvm::ConstantInt::get(IntPtrTy,
getContext().getTypeSizeInChars(type).getQuantity());
- llvm::Type *BP = AllocaInt8PtrTy;
+ llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace());
if (Loc.getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP);
// Otherwise, create a temporary global with the initializer then
// memcpy from the global to the alloca.
std::string Name = getStaticDeclName(CGM, D);
- unsigned AS = 0;
- if (getLangOpts().OpenCL) {
- AS = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
- BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS);
- }
+ unsigned AS = CGM.getContext().getTargetAddressSpace(
+ CGM.getStringLiteralAddressSpace());
+ BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS);
+
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true,
llvm::GlobalValue::PrivateLinkage,
return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D);
}
+LangAS CodeGenModule::getStringLiteralAddressSpace() const {
+ // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
+ if (LangOpts.OpenCL)
+ return LangAS::opencl_constant;
+ if (auto AS = getTarget().getConstantAddressSpace())
+ return AS.getValue();
+ return LangAS::Default;
+}
+
+// In address space agnostic languages, string literals are in default address
+// space in AST. However, certain targets (e.g. amdgcn) request them to be
+// emitted in constant address space in LLVM IR. To be consistent with other
+// parts of AST, string literal global variables in constant address space
+// need to be casted to default address space before being put into address
+// map and referenced by other part of CodeGen.
+// In OpenCL, string literals are in constant address space in AST, therefore
+// they should not be casted to default address space.
+static llvm::Constant *
+castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM,
+ llvm::GlobalVariable *GV) {
+ llvm::Constant *Cast = GV;
+ if (!CGM.getLangOpts().OpenCL) {
+ if (auto AS = CGM.getTarget().getConstantAddressSpace()) {
+ if (AS != LangAS::Default)
+ Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
+ CGM, GV, AS.getValue(), LangAS::Default,
+ GV->getValueType()->getPointerTo(
+ CGM.getContext().getTargetAddressSpace(LangAS::Default)));
+ }
+ }
+ return Cast;
+}
+
template<typename SomeDecl>
void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
llvm::GlobalValue *GV) {
GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
CodeGenModule &CGM, StringRef GlobalName,
CharUnits Alignment) {
- // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
- unsigned AddrSpace = 0;
- if (CGM.getLangOpts().OpenCL)
- AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
+ unsigned AddrSpace = CGM.getContext().getTargetAddressSpace(
+ CGM.getStringLiteralAddressSpace());
llvm::Module &M = CGM.getModule();
// Create a global variable for this string
SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>",
QualType());
- return ConstantAddress(GV, Alignment);
+
+ return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
+ Alignment);
}
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
GlobalName, Alignment);
if (Entry)
*Entry = GV;
- return ConstantAddress(GV, Alignment);
+
+ return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
+ Alignment);
}
ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
ForDefinition_t IsForDefinition
= NotForDefinition);
+ /// Return the AST address space of string literal, which is used to emit
+ /// the string literal as global variable in LLVM IR.
+ /// Note: This is not necessarily the address space of the string literal
+ /// in AST. For address space agnostic language, e.g. C++, string literal
+ /// in AST is always in default address space.
+ LangAS getStringLiteralAddressSpace() const;
+
/// Return the address of the given function. If Ty is non-null, then this
/// function will use the specified type if it has to create it.
llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr,
--- /dev/null
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @.str = private unnamed_addr addrspace(4) constant [6 x i8] c"g_str\00", align 1
+// CHECK: @g_str = addrspace(1) global i8* addrspacecast (i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0) to i8*), align 8
+// CHECK: @g_array = addrspace(1) global [8 x i8] c"g_array\00", align 1
+// CHECK: @.str.1 = private unnamed_addr addrspace(4) constant [6 x i8] c"l_str\00", align 1
+// CHECK: @_ZZ1fvE7l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1
+
+const char* g_str = "g_str";
+char g_array[] = "g_array";
+
+void g(const char* p);
+
+// CHECK-LABEL: define void @_Z1fv()
+void f() {
+ const char* l_str = "l_str";
+
+ // CHECK: call void @llvm.memcpy.p0i8.p4i8.i64
+ char l_array[] = "l_array";
+
+ g(g_str);
+ g(g_array);
+ g(l_str);
+ g(l_array);
+
+ const char* p = g_str;
+ g(p);
+}