Skip to content

[clang][CodeGen] Handle template parameter objects with explicit address spaces #69266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 29, 2023
Merged
17 changes: 14 additions & 3 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3038,9 +3038,20 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
return MakeAddrLValue(CGM.GetAddrOfMSGuidDecl(GD), T,
AlignmentSource::Decl);

if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND))
return MakeAddrLValue(CGM.GetAddrOfTemplateParamObject(TPO), T,
AlignmentSource::Decl);
if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
auto ATPO = CGM.GetAddrOfTemplateParamObject(TPO);
auto AS = getLangASFromTargetAS(ATPO.getAddressSpace());

if (AS != T.getAddressSpace()) {
auto TargetAS = getContext().getTargetAddressSpace(T.getAddressSpace());
auto PtrTy = ATPO.getElementType()->getPointerTo(TargetAS);
auto ASC = getTargetHooks().performAddrSpaceCast(
CGM, ATPO.getPointer(), AS, T.getAddressSpace(), PtrTy);
ATPO = ConstantAddress(ASC, ATPO.getElementType(), ATPO.getAlignment());
}

return MakeAddrLValue(ATPO, T, AlignmentSource::Decl);
}

llvm_unreachable("Unhandled DeclRefExpr");
}
Expand Down
32 changes: 32 additions & 0 deletions clang/test/CodeGenCXX/template-param-objects-address-space.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -std=c++20 %s -emit-llvm -o - | FileCheck %s

struct S { char buf[32]; };
template<S s> constexpr const char *begin() { return s.buf; }
template<S s> constexpr const char *end() { return s.buf + __builtin_strlen(s.buf); }
template<S s> constexpr const void *retval() { return &s; }
extern const void *callee(const S*);
template<S s> constexpr const void* observable_addr() { return callee(&s); }

// CHECK: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]]
// CHECK-SAME: = linkonce_odr addrspace(1) constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat

// CHECK: @p
// CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr)
const char *p = begin<S{"hello world"}>();

// CHECK: @q
// CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) [[HELLO]], i64 11) to ptr)
const char *q = end<S{"hello world"}>();

const void *(*r)() = &retval<S{"hello world"}>;

// CHECK: @s
// CHECK-SAME: addrspace(1) global ptr null
const void *s = observable_addr<S{"hello world"}>();

// CHECK: define linkonce_odr noundef ptr @_Z6retvalIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv()
// CHECK: ret ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr)

// CHECK: define linkonce_odr noundef ptr @_Z15observable_addrIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv()
// CHECK: %call = call noundef ptr @_Z6calleePK1S(ptr noundef addrspacecast (ptr addrspace(1) [[HELLO]] to ptr))
// CHECK: declare noundef ptr @_Z6calleePK1S(ptr noundef)