Author: Timm Baeder Date: 2024-09-12T17:19:37+02:00 New Revision: 43fd2c401edd4f3ca0c687dd6937c2603fb15f71
URL: https://github.com/llvm/llvm-project/commit/43fd2c401edd4f3ca0c687dd6937c2603fb15f71 DIFF: https://github.com/llvm/llvm-project/commit/43fd2c401edd4f3ca0c687dd6937c2603fb15f71.diff LOG: [clang][bytecode] Implement base casts on integral pointers (#108340) Get the right offset to apply from the RecordLayout. Added: clang/test/AST/ByteCode/const-base-cast.cpp Modified: clang/lib/AST/ByteCode/Interp.h clang/lib/AST/ByteCode/Pointer.cpp clang/lib/AST/ByteCode/Pointer.h clang/test/CodeGenCXX/const-base-cast.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 7b7c7822e4a925..3d507e2e2ba764 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1611,6 +1611,12 @@ inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) { inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) { const Pointer &Ptr = S.Stk.peek<Pointer>(); + + if (!Ptr.isBlockPointer()) { + S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off)); + return true; + } + if (!CheckNull(S, OpPC, Ptr, CSK_Base)) return false; if (!CheckSubobject(S, OpPC, Ptr, CSK_Base)) @@ -1624,6 +1630,12 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) { inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) { const Pointer &Ptr = S.Stk.pop<Pointer>(); + + if (!Ptr.isBlockPointer()) { + S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off)); + return true; + } + if (!CheckNull(S, OpPC, Ptr, CSK_Base)) return false; if (!CheckSubobject(S, OpPC, Ptr, CSK_Base)) diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 9eaf0db45c7451..282953eb991a6b 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -667,3 +667,26 @@ IntPointer IntPointer::atOffset(const ASTContext &ASTCtx, .getQuantity(); return IntPointer{this->Desc, this->Value + FieldOffset}; } + +IntPointer IntPointer::baseCast(const ASTContext &ASTCtx, + unsigned BaseOffset) const { + const Record *R = Desc->ElemRecord; + const Descriptor *BaseDesc = nullptr; + + // This iterates over bases and checks for the proper offset. That's + // potentially slow but this case really shouldn't happen a lot. + for (const Record::Base &B : R->bases()) { + if (B.Offset == BaseOffset) { + BaseDesc = B.Desc; + break; + } + } + assert(BaseDesc); + + // Adjust the offset value based on the information from the record layout. + const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(R->getDecl()); + CharUnits BaseLayoutOffset = + Layout.getBaseClassOffset(cast<CXXRecordDecl>(BaseDesc->asDecl())); + + return {BaseDesc, Value + BaseLayoutOffset.getQuantity()}; +} diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index acbef437752388..ac9b9ed4091b66 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -46,6 +46,7 @@ struct IntPointer { uint64_t Value; IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const; + IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const; }; enum class Storage { Block, Int, Fn }; diff --git a/clang/test/AST/ByteCode/const-base-cast.cpp b/clang/test/AST/ByteCode/const-base-cast.cpp new file mode 100644 index 00000000000000..80226b973bf977 --- /dev/null +++ b/clang/test/AST/ByteCode/const-base-cast.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -fexperimental-new-constant-interpreter | FileCheck %s + + +/// Slightly adapted to the version from test/CodeGenCXX/. + +struct X { int x[12];}; +struct A : X { char x, y, z; }; +struct B { char y; }; +struct C : A,B {}; +unsigned char x = ((char*)(X*)(C*)0x1000) - (char*)0x1000; +// CHECK: @x = {{(dso_local )?}}global i8 0 + +unsigned char y = ((char*)(B*)(C*)0x1000) - (char*)0x1000; +// CHECK: @y = {{(dso_local )?}}global i8 51 + +unsigned char z = ((char*)(A*)(C*)0x1000) - (char*)0x1000; +// CHECK: @z = {{(dso_local )?}}global i8 0 + diff --git a/clang/test/CodeGenCXX/const-base-cast.cpp b/clang/test/CodeGenCXX/const-base-cast.cpp index bb08b9d21fcfce..7f2c66e6ca0886 100644 --- a/clang/test/CodeGenCXX/const-base-cast.cpp +++ b/clang/test/CodeGenCXX/const-base-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -fexperimental-new-constant-interpreter | FileCheck %s // Check that the following construct, which is similar to one which occurs // in Firefox, is folded correctly. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits