Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -1369,7 +1369,7 @@ 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); @@ -1390,11 +1390,10 @@ // 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, Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -785,6 +785,13 @@ 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, Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -3044,6 +3044,39 @@ 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 void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV) { @@ -4039,10 +4072,8 @@ 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 @@ -4104,7 +4135,9 @@ SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "", QualType()); - return ConstantAddress(GV, Alignment); + + return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), + Alignment); } /// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant @@ -4148,7 +4181,9 @@ GlobalName, Alignment); if (Entry) *Entry = GV; - return ConstantAddress(GV, Alignment); + + return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), + Alignment); } ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( Index: test/CodeGenCXX/amdgcn-string-literal.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/amdgcn-string-literal.cpp @@ -0,0 +1,28 @@ +// 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); +}