Skip to content

Commit f2a7fd2

Browse files
tbaederryuxuanchen1997
authored andcommitted
[clang][Interp] Start computing APValue offsets
Summary: For array elements, arrays roots and fields. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251235
1 parent 1eefd13 commit f2a7fd2

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

clang/lib/AST/Interp/Pointer.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "MemberPointer.h"
1717
#include "PrimType.h"
1818
#include "Record.h"
19+
#include "clang/AST/RecordLayout.h"
1920

2021
using namespace clang;
2122
using namespace clang::interp;
@@ -141,25 +142,38 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
141142
else
142143
llvm_unreachable("Invalid allocation type");
143144

144-
if (isDummy() || isUnknownSizeArray() || Desc->asExpr())
145+
if (isUnknownSizeArray() || Desc->asExpr())
145146
return APValue(Base, CharUnits::Zero(), Path,
146147
/*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);
147148

148-
// TODO: compute the offset into the object.
149149
CharUnits Offset = CharUnits::Zero();
150150

151+
auto getFieldOffset = [&](const FieldDecl *FD) -> CharUnits {
152+
const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(FD->getParent());
153+
unsigned FieldIndex = FD->getFieldIndex();
154+
return ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex));
155+
};
156+
151157
// Build the path into the object.
152158
Pointer Ptr = *this;
153159
while (Ptr.isField() || Ptr.isArrayElement()) {
154160
if (Ptr.isArrayRoot()) {
155161
Path.push_back(APValue::LValuePathEntry(
156162
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
163+
164+
if (const auto *FD = dyn_cast<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
165+
Offset += getFieldOffset(FD);
166+
157167
Ptr = Ptr.getBase();
158168
} else if (Ptr.isArrayElement()) {
169+
unsigned Index;
159170
if (Ptr.isOnePastEnd())
160-
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getArray().getNumElems()));
171+
Index = Ptr.getArray().getNumElems();
161172
else
162-
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
173+
Index = Ptr.getIndex();
174+
175+
Offset += (Index * ASTCtx.getTypeSizeInChars(Ptr.getType()));
176+
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
163177
Ptr = Ptr.getArray();
164178
} else {
165179
// TODO: figure out if base is virtual
@@ -170,12 +184,21 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
170184
if (const auto *BaseOrMember = Desc->asDecl()) {
171185
Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
172186
Ptr = Ptr.getBase();
187+
188+
if (const auto *FD = dyn_cast<FieldDecl>(BaseOrMember))
189+
Offset += getFieldOffset(FD);
190+
173191
continue;
174192
}
175193
llvm_unreachable("Invalid field type");
176194
}
177195
}
178196

197+
// FIXME(perf): We compute the lvalue path above, but we can't supply it
198+
// for dummy pointers (that causes crashes later in CheckConstantExpression).
199+
if (isDummy())
200+
Path.clear();
201+
179202
// We assemble the LValuePath starting from the innermost pointer to the
180203
// outermost one. SO in a.b.c, the first element in Path will refer to
181204
// the field 'c', while later code expects it to refer to 'a'.

clang/test/AST/Interp/codegen.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
2+
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
3+
4+
5+
int arr[2];
6+
// CHECK: @pastEnd = constant ptr getelementptr (i8, ptr @arr, i64 8)
7+
int &pastEnd = arr[2];
8+
9+
// CHECK: @F = constant ptr @arr, align 8
10+
int &F = arr[0];
11+
12+
struct S {
13+
int a;
14+
float c[3];
15+
};
16+
17+
// CHECK: @s = global %struct.S zeroinitializer, align 4
18+
S s;
19+
// CHECK: @sp = constant ptr getelementptr (i8, ptr @s, i64 16), align 8
20+
float &sp = s.c[3];

0 commit comments

Comments
 (0)