Skip to content

Commit 43fd2c4

Browse files
authored
[clang][bytecode] Implement base casts on integral pointers (#108340)
Get the right offset to apply from the RecordLayout.
1 parent 2e30f8d commit 43fd2c4

File tree

5 files changed

+56
-1
lines changed

5 files changed

+56
-1
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,12 @@ inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
16111611

16121612
inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
16131613
const Pointer &Ptr = S.Stk.peek<Pointer>();
1614+
1615+
if (!Ptr.isBlockPointer()) {
1616+
S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
1617+
return true;
1618+
}
1619+
16141620
if (!CheckNull(S, OpPC, Ptr, CSK_Base))
16151621
return false;
16161622
if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
@@ -1624,6 +1630,12 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
16241630

16251631
inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) {
16261632
const Pointer &Ptr = S.Stk.pop<Pointer>();
1633+
1634+
if (!Ptr.isBlockPointer()) {
1635+
S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
1636+
return true;
1637+
}
1638+
16271639
if (!CheckNull(S, OpPC, Ptr, CSK_Base))
16281640
return false;
16291641
if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))

clang/lib/AST/ByteCode/Pointer.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,26 @@ IntPointer IntPointer::atOffset(const ASTContext &ASTCtx,
667667
.getQuantity();
668668
return IntPointer{this->Desc, this->Value + FieldOffset};
669669
}
670+
671+
IntPointer IntPointer::baseCast(const ASTContext &ASTCtx,
672+
unsigned BaseOffset) const {
673+
const Record *R = Desc->ElemRecord;
674+
const Descriptor *BaseDesc = nullptr;
675+
676+
// This iterates over bases and checks for the proper offset. That's
677+
// potentially slow but this case really shouldn't happen a lot.
678+
for (const Record::Base &B : R->bases()) {
679+
if (B.Offset == BaseOffset) {
680+
BaseDesc = B.Desc;
681+
break;
682+
}
683+
}
684+
assert(BaseDesc);
685+
686+
// Adjust the offset value based on the information from the record layout.
687+
const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(R->getDecl());
688+
CharUnits BaseLayoutOffset =
689+
Layout.getBaseClassOffset(cast<CXXRecordDecl>(BaseDesc->asDecl()));
690+
691+
return {BaseDesc, Value + BaseLayoutOffset.getQuantity()};
692+
}

clang/lib/AST/ByteCode/Pointer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct IntPointer {
4646
uint64_t Value;
4747

4848
IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const;
49+
IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const;
4950
};
5051

5152
enum class Storage { Block, Int, Fn };
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
2+
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -fexperimental-new-constant-interpreter | FileCheck %s
3+
4+
5+
/// Slightly adapted to the version from test/CodeGenCXX/.
6+
7+
struct X { int x[12];};
8+
struct A : X { char x, y, z; };
9+
struct B { char y; };
10+
struct C : A,B {};
11+
unsigned char x = ((char*)(X*)(C*)0x1000) - (char*)0x1000;
12+
// CHECK: @x = {{(dso_local )?}}global i8 0
13+
14+
unsigned char y = ((char*)(B*)(C*)0x1000) - (char*)0x1000;
15+
// CHECK: @y = {{(dso_local )?}}global i8 51
16+
17+
unsigned char z = ((char*)(A*)(C*)0x1000) - (char*)0x1000;
18+
// CHECK: @z = {{(dso_local )?}}global i8 0
19+

clang/test/CodeGenCXX/const-base-cast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -fexperimental-new-constant-interpreter | FileCheck %s
22

33
// Check that the following construct, which is similar to one which occurs
44
// in Firefox, is folded correctly.

0 commit comments

Comments
 (0)