Skip to content

Commit 0f56baa

Browse files
tbaederraokblast
authored andcommitted
[clang][bytecode] Move shared interp functions to InterpHelpers.h (llvm#164215)
This drastically reduces the preprocessed size of Context.cpp and InterpBuiltin.cpp.
1 parent 0dba5b3 commit 0f56baa

File tree

4 files changed

+148
-117
lines changed

4 files changed

+148
-117
lines changed

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "Context.h"
10+
#include "Boolean.h"
1011
#include "ByteCodeEmitter.h"
1112
#include "Compiler.h"
1213
#include "EvalEmitter.h"
13-
#include "Interp.h"
14+
#include "Integral.h"
1415
#include "InterpFrame.h"
16+
#include "InterpHelpers.h"
1517
#include "InterpStack.h"
18+
#include "Pointer.h"
1619
#include "PrimType.h"
1720
#include "Program.h"
1821
#include "clang/AST/ASTLambda.h"

clang/lib/AST/ByteCode/Interp.h

Lines changed: 1 addition & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "Function.h"
2323
#include "InterpBuiltinBitCast.h"
2424
#include "InterpFrame.h"
25+
#include "InterpHelpers.h"
2526
#include "InterpStack.h"
2627
#include "InterpState.h"
2728
#include "MemberPointer.h"
@@ -43,28 +44,10 @@ using FixedPointSemantics = llvm::FixedPointSemantics;
4344
/// Checks if the variable has externally defined storage.
4445
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
4546

46-
/// Checks if the array is offsetable.
47-
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
48-
49-
/// Checks if a pointer is live and accessible.
50-
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
51-
AccessKinds AK);
52-
53-
/// Checks if a pointer is a dummy pointer.
54-
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK);
55-
5647
/// Checks if a pointer is null.
5748
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
5849
CheckSubobjectKind CSK);
5950

60-
/// Checks if a pointer is in range.
61-
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
62-
AccessKinds AK);
63-
64-
/// Checks if a field from which a pointer is going to be derived is valid.
65-
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
66-
CheckSubobjectKind CSK);
67-
6851
/// Checks if Ptr is a one-past-the-end pointer.
6952
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
7053
CheckSubobjectKind CSK);
@@ -80,12 +63,6 @@ bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
8063
/// Checks if the Descriptor is of a constexpr or const global variable.
8164
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc);
8265

83-
/// Checks if a pointer points to a mutable field.
84-
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
85-
86-
/// Checks if a value can be loaded from a block.
87-
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
88-
AccessKinds AK = AK_Read);
8966
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
9067

9168
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
@@ -110,12 +87,6 @@ bool CheckThis(InterpState &S, CodePtr OpPC);
11087
/// language mode.
11188
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC);
11289

113-
/// Diagnose mismatched new[]/delete or new/delete[] pairs.
114-
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
115-
DynamicAllocator::Form AllocForm,
116-
DynamicAllocator::Form DeleteForm, const Descriptor *D,
117-
const Expr *NewExpr);
118-
11990
/// Check the source of the pointer passed to delete/delete[] has actually
12091
/// been heap allocated by us.
12192
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
@@ -129,9 +100,6 @@ bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
129100
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
130101
const Pointer &Ptr, const APSInt &IntValue);
131102

132-
/// Copy the contents of Src into Dest.
133-
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest);
134-
135103
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
136104
uint32_t VarArgSize);
137105
bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
@@ -149,19 +117,11 @@ bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
149117
bool CheckBCPResult(InterpState &S, const Pointer &Ptr);
150118
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
151119

152-
template <typename T>
153-
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
154-
const Expr *E = S.Current->getExpr(OpPC);
155-
S.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << E->getType();
156-
return S.noteUndefinedBehavior();
157-
}
158120
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
159121
const FixedPoint &FP);
160122

161123
bool isConstexprUnknown(const Pointer &P);
162124

163-
inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems);
164-
165125
enum class ShiftDir { Left, Right };
166126

167127
/// Checks if the shift operation is legal.
@@ -241,43 +201,6 @@ bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
241201
return true;
242202
}
243203

244-
template <typename SizeT>
245-
bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
246-
unsigned ElemSize, bool IsNoThrow) {
247-
// FIXME: Both the SizeT::from() as well as the
248-
// NumElements.toAPSInt() in this function are rather expensive.
249-
250-
// Can't be too many elements if the bitwidth of NumElements is lower than
251-
// that of Descriptor::MaxArrayElemBytes.
252-
if ((NumElements->bitWidth() - NumElements->isSigned()) <
253-
(sizeof(Descriptor::MaxArrayElemBytes) * 8))
254-
return true;
255-
256-
// FIXME: GH63562
257-
// APValue stores array extents as unsigned,
258-
// so anything that is greater that unsigned would overflow when
259-
// constructing the array, we catch this here.
260-
SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
261-
assert(MaxElements.isPositive());
262-
if (NumElements->toAPSInt().getActiveBits() >
263-
ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
264-
*NumElements > MaxElements) {
265-
if (!IsNoThrow) {
266-
const SourceInfo &Loc = S.Current->getSource(OpPC);
267-
268-
if (NumElements->isSigned() && NumElements->isNegative()) {
269-
S.FFDiag(Loc, diag::note_constexpr_new_negative)
270-
<< NumElements->toDiagnosticString(S.getASTContext());
271-
} else {
272-
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
273-
<< NumElements->toDiagnosticString(S.getASTContext());
274-
}
275-
}
276-
return false;
277-
}
278-
return true;
279-
}
280-
281204
/// Checks if the result of a floating-point operation is valid
282205
/// in the current context.
283206
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
@@ -286,19 +209,6 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
286209
/// Checks why the given DeclRefExpr is invalid.
287210
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR);
288211

289-
/// Interpreter entry point.
290-
bool Interpret(InterpState &S);
291-
292-
/// Interpret a builtin function.
293-
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
294-
uint32_t BuiltinID);
295-
296-
/// Interpret an offsetof operation.
297-
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
298-
ArrayRef<int64_t> ArrayIndices, int64_t &Result);
299-
300-
inline bool Invalid(InterpState &S, CodePtr OpPC);
301-
302212
enum class ArithOp { Add, Sub };
303213

304214
//===----------------------------------------------------------------------===//
@@ -403,13 +313,6 @@ bool Add(InterpState &S, CodePtr OpPC) {
403313
return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
404314
}
405315

406-
static inline llvm::RoundingMode getRoundingMode(FPOptions FPO) {
407-
auto RM = FPO.getRoundingMode();
408-
if (RM == llvm::RoundingMode::Dynamic)
409-
return llvm::RoundingMode::NearestTiesToEven;
410-
return RM;
411-
}
412-
413316
inline bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
414317
const Floating &RHS = S.Stk.pop<Floating>();
415318
const Floating &LHS = S.Stk.pop<Floating>();
@@ -3264,12 +3167,6 @@ inline bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
32643167

32653168
/// Just emit a diagnostic. The expression that caused emission of this
32663169
/// op is not valid in a constant context.
3267-
inline bool Invalid(InterpState &S, CodePtr OpPC) {
3268-
const SourceLocation &Loc = S.Current->getLocation(OpPC);
3269-
S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)
3270-
<< S.Current->getRange(OpPC);
3271-
return false;
3272-
}
32733170

32743171
inline bool Unsupported(InterpState &S, CodePtr OpPC) {
32753172
const SourceLocation &Loc = S.Current->getLocation(OpPC);
@@ -3701,17 +3598,6 @@ inline bool CheckDestruction(InterpState &S, CodePtr OpPC) {
37013598
return CheckDestructor(S, OpPC, Ptr);
37023599
}
37033600

3704-
inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {
3705-
uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
3706-
if (Limit != 0 && NumElems > Limit) {
3707-
S.FFDiag(S.Current->getSource(OpPC),
3708-
diag::note_constexpr_new_exceeds_limits)
3709-
<< NumElems << Limit;
3710-
return false;
3711-
}
3712-
return true;
3713-
}
3714-
37153601
//===----------------------------------------------------------------------===//
37163602
// Read opcode arguments
37173603
//===----------------------------------------------------------------------===//

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
#include "../ExprConstShared.h"
99
#include "Boolean.h"
1010
#include "EvalEmitter.h"
11-
#include "Interp.h"
1211
#include "InterpBuiltinBitCast.h"
12+
#include "InterpHelpers.h"
1313
#include "PrimType.h"
14+
#include "Program.h"
1415
#include "clang/AST/OSLog.h"
1516
#include "clang/AST/RecordLayout.h"
1617
#include "clang/Basic/Builtins.h"
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//===--- InterpHelpers.h - Interpreter Helper Functions --------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_AST_INTERP_INTERPHELPERS_H
10+
#define LLVM_CLANG_AST_INTERP_INTERPHELPERS_H
11+
12+
#include "DynamicAllocator.h"
13+
#include "InterpState.h"
14+
#include "Pointer.h"
15+
16+
namespace clang {
17+
class CallExpr;
18+
class OffsetOfExpr;
19+
20+
namespace interp {
21+
class Block;
22+
struct Descriptor;
23+
24+
/// Interpreter entry point.
25+
bool Interpret(InterpState &S);
26+
27+
/// Interpret a builtin function.
28+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
29+
uint32_t BuiltinID);
30+
31+
/// Interpret an offsetof operation.
32+
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
33+
ArrayRef<int64_t> ArrayIndices, int64_t &Result);
34+
35+
/// Checks if the array is offsetable.
36+
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
37+
38+
/// Checks if a pointer is live and accessible.
39+
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
40+
AccessKinds AK);
41+
42+
/// Checks if a pointer is a dummy pointer.
43+
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK);
44+
45+
/// Checks if a pointer is in range.
46+
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
47+
AccessKinds AK);
48+
49+
/// Checks if a field from which a pointer is going to be derived is valid.
50+
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
51+
CheckSubobjectKind CSK);
52+
53+
/// Checks if a pointer points to a mutable field.
54+
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
55+
56+
/// Checks if a value can be loaded from a block.
57+
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
58+
AccessKinds AK = AK_Read);
59+
60+
/// Diagnose mismatched new[]/delete or new/delete[] pairs.
61+
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
62+
DynamicAllocator::Form AllocForm,
63+
DynamicAllocator::Form DeleteForm, const Descriptor *D,
64+
const Expr *NewExpr);
65+
66+
/// Copy the contents of Src into Dest.
67+
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest);
68+
69+
template <typename T>
70+
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
71+
const Expr *E = S.Current->getExpr(OpPC);
72+
S.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << E->getType();
73+
return S.noteUndefinedBehavior();
74+
}
75+
76+
inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {
77+
uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
78+
if (Limit != 0 && NumElems > Limit) {
79+
S.FFDiag(S.Current->getSource(OpPC),
80+
diag::note_constexpr_new_exceeds_limits)
81+
<< NumElems << Limit;
82+
return false;
83+
}
84+
return true;
85+
}
86+
87+
static inline llvm::RoundingMode getRoundingMode(FPOptions FPO) {
88+
auto RM = FPO.getRoundingMode();
89+
if (RM == llvm::RoundingMode::Dynamic)
90+
return llvm::RoundingMode::NearestTiesToEven;
91+
return RM;
92+
}
93+
94+
inline bool Invalid(InterpState &S, CodePtr OpPC) {
95+
const SourceLocation &Loc = S.Current->getLocation(OpPC);
96+
S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)
97+
<< S.Current->getRange(OpPC);
98+
return false;
99+
}
100+
101+
template <typename SizeT>
102+
bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
103+
unsigned ElemSize, bool IsNoThrow) {
104+
// FIXME: Both the SizeT::from() as well as the
105+
// NumElements.toAPSInt() in this function are rather expensive.
106+
107+
// Can't be too many elements if the bitwidth of NumElements is lower than
108+
// that of Descriptor::MaxArrayElemBytes.
109+
if ((NumElements->bitWidth() - NumElements->isSigned()) <
110+
(sizeof(Descriptor::MaxArrayElemBytes) * 8))
111+
return true;
112+
113+
// FIXME: GH63562
114+
// APValue stores array extents as unsigned,
115+
// so anything that is greater that unsigned would overflow when
116+
// constructing the array, we catch this here.
117+
SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
118+
assert(MaxElements.isPositive());
119+
if (NumElements->toAPSInt().getActiveBits() >
120+
ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
121+
*NumElements > MaxElements) {
122+
if (!IsNoThrow) {
123+
const SourceInfo &Loc = S.Current->getSource(OpPC);
124+
125+
if (NumElements->isSigned() && NumElements->isNegative()) {
126+
S.FFDiag(Loc, diag::note_constexpr_new_negative)
127+
<< NumElements->toDiagnosticString(S.getASTContext());
128+
} else {
129+
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
130+
<< NumElements->toDiagnosticString(S.getASTContext());
131+
}
132+
}
133+
return false;
134+
}
135+
return true;
136+
}
137+
138+
} // namespace interp
139+
} // namespace clang
140+
141+
#endif // LLVM_CLANG_AST_INTERP_INTERPHELPERS_H

0 commit comments

Comments
 (0)