[clang] 5303ca1 - [clang][Interp] Start computing APValue offsets
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 20 08:40:58 PDT 2024
Author: Timm Bäder
Date: 2024-07-20T17:29:31+02:00
New Revision: 5303ca1496fc5f604f37c071d37821597788e83e
URL: https://github.com/llvm/llvm-project/commit/5303ca1496fc5f604f37c071d37821597788e83e
DIFF: https://github.com/llvm/llvm-project/commit/5303ca1496fc5f604f37c071d37821597788e83e.diff
LOG: [clang][Interp] Start computing APValue offsets
For array elements, arrays roots and fields.
Added:
clang/test/AST/Interp/codegen.cpp
Modified:
clang/lib/AST/Interp/Pointer.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index f7bd76b260584..229007c6d720a 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -16,6 +16,7 @@
#include "MemberPointer.h"
#include "PrimType.h"
#include "Record.h"
+#include "clang/AST/RecordLayout.h"
using namespace clang;
using namespace clang::interp;
@@ -141,25 +142,38 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
else
llvm_unreachable("Invalid allocation type");
- if (isDummy() || isUnknownSizeArray() || Desc->asExpr())
+ if (isUnknownSizeArray() || Desc->asExpr())
return APValue(Base, CharUnits::Zero(), Path,
/*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);
- // TODO: compute the offset into the object.
CharUnits Offset = CharUnits::Zero();
+ auto getFieldOffset = [&](const FieldDecl *FD) -> CharUnits {
+ const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(FD->getParent());
+ unsigned FieldIndex = FD->getFieldIndex();
+ return ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex));
+ };
+
// Build the path into the object.
Pointer Ptr = *this;
while (Ptr.isField() || Ptr.isArrayElement()) {
if (Ptr.isArrayRoot()) {
Path.push_back(APValue::LValuePathEntry(
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
+
+ if (const auto *FD = dyn_cast<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
+ Offset += getFieldOffset(FD);
+
Ptr = Ptr.getBase();
} else if (Ptr.isArrayElement()) {
+ unsigned Index;
if (Ptr.isOnePastEnd())
- Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getArray().getNumElems()));
+ Index = Ptr.getArray().getNumElems();
else
- Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
+ Index = Ptr.getIndex();
+
+ Offset += (Index * ASTCtx.getTypeSizeInChars(Ptr.getType()));
+ Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
Ptr = Ptr.getArray();
} else {
// TODO: figure out if base is virtual
@@ -170,12 +184,21 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
if (const auto *BaseOrMember = Desc->asDecl()) {
Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
Ptr = Ptr.getBase();
+
+ if (const auto *FD = dyn_cast<FieldDecl>(BaseOrMember))
+ Offset += getFieldOffset(FD);
+
continue;
}
llvm_unreachable("Invalid field type");
}
}
+ // FIXME(perf): We compute the lvalue path above, but we can't supply it
+ // for dummy pointers (that causes crashes later in CheckConstantExpression).
+ if (isDummy())
+ Path.clear();
+
// We assemble the LValuePath starting from the innermost pointer to the
// outermost one. SO in a.b.c, the first element in Path will refer to
// the field 'c', while later code expects it to refer to 'a'.
diff --git a/clang/test/AST/Interp/codegen.cpp b/clang/test/AST/Interp/codegen.cpp
new file mode 100644
index 0000000000000..8a0d070d19da3
--- /dev/null
+++ b/clang/test/AST/Interp/codegen.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
+
+
+int arr[2];
+// CHECK: @pastEnd = constant ptr getelementptr (i8, ptr @arr, i64 8)
+int &pastEnd = arr[2];
+
+// CHECK: @F = constant ptr @arr, align 8
+int &F = arr[0];
+
+struct S {
+ int a;
+ float c[3];
+};
+
+// CHECK: @s = global %struct.S zeroinitializer, align 4
+S s;
+// CHECK: @sp = constant ptr getelementptr (i8, ptr @s, i64 16), align 8
+float &sp = s.c[3];
More information about the cfe-commits
mailing list