llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Yaxun (Sam) Liu (yxsamliu)

<details>
<summary>Changes</summary>

C++20 allows a class object to be used as a non-type template
parameter. For example, a template can take an object of a struct like
`{ char A; long long B; char C; char First[2]; char Second[2]; }`.

That struct has padding before `B`. The constant emitter can represent
the value with an ordinary LLVM struct and let LLVM provide that padding
implicitly. Normal record CodeGen instead uses the memory type for the
record, which may contain explicit padding fields so C++ fields have
stable LLVM field numbers.

The bytes are laid out the same, but the LLVM field numbers are not.
For the normal padded record type, `First` has one field index. For the
compact constant type, that same index names a later field. Clang was
computing the field index for the padded record type, then applying it
to the compact template parameter object type. As a result, reading
`First` could read from the bytes for `Second` instead.

Return the template parameter object address using the normal memory
type for the record. This makes the field index apply to the type it
was computed for, so field access uses the same layout as an ordinary
object. The constant data itself stays the same.

---
Full diff: https://github.com/llvm/llvm-project/pull/204174.diff


2 Files Affected:

- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+3-2) 
- (added) clang/test/CodeGenCXX/cxx20-nttp-object-layout.cpp (+44) 


``````````diff
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 627d2376f1288..40263a507d81b 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4347,9 +4347,10 @@ ConstantAddress 
CodeGenModule::GetAddrOfTemplateParamObject(
     const TemplateParamObjectDecl *TPO) {
   StringRef Name = getMangledName(TPO);
   CharUnits Alignment = getNaturalTypeAlignment(TPO->getType());
+  llvm::Type *Type = getTypes().ConvertTypeForMem(TPO->getType());
 
   if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name))
-    return ConstantAddress(GV, GV->getValueType(), Alignment);
+    return ConstantAddress(GV, Type, Alignment);
 
   ConstantEmitter Emitter(*this);
   llvm::Constant *Init = Emitter.emitForInitializer(
@@ -4371,7 +4372,7 @@ ConstantAddress 
CodeGenModule::GetAddrOfTemplateParamObject(
     GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);
 
-    return ConstantAddress(GV, GV->getValueType(), Alignment);
+  return ConstantAddress(GV, Type, Alignment);
 }
 
 ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
diff --git a/clang/test/CodeGenCXX/cxx20-nttp-object-layout.cpp 
b/clang/test/CodeGenCXX/cxx20-nttp-object-layout.cpp
new file mode 100644
index 0000000000000..600de2c999d56
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx20-nttp-object-layout.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -std=c++20 -O1 \
+// RUN:   -emit-llvm -o - %s | FileCheck %s
+
+using u8 = unsigned char;
+using u64 = unsigned long long;
+
+struct Padded {
+  u8 Head{};
+  u64 Middle{};
+  u8 Tail{};
+  u8 First[2]{};
+  u8 Second[2]{};
+  u8 Third[2]{};
+  constexpr bool operator==(const Padded &) const = default;
+};
+
+template <Padded P> __attribute__((noinline)) int readFirst() {
+  volatile int I = 0;
+  return P.First[I];
+}
+
+template <Padded P> __attribute__((noinline)) int readSecond() {
+  volatile int I = 0;
+  return P.Second[I];
+}
+
+constexpr Padded P = [] {
+  Padded Result{};
+  Result.First[0] = 5;
+  Result.Second[0] = 6;
+  Result.Third[0] = 7;
+  return Result;
+}();
+
+int use() { return readFirst<P>() + readSecond<P>(); }
+
+// `First` starts immediately after Head, Middle, and Tail, including the
+// padding before Middle: 1 + 7 + 8 + 1 == 17.
+// CHECK-LABEL: define {{.*}} @_Z9readFirst
+// CHECK: getelementptr {{.*}}(i8, ptr @_ZTAX{{.*}}, i64 17)
+
+// `Second` starts after `First`: 17 + 2 == 19.
+// CHECK-LABEL: define {{.*}} @_Z10readSecond
+// CHECK: getelementptr {{.*}}(i8, ptr @_ZTAX{{.*}}, i64 19)

``````````

</details>


https://github.com/llvm/llvm-project/pull/204174
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to