Skip to content

Commit 14cc50c

Browse files
author
Marc Rasi
committed
address comments
1 parent f8fc403 commit 14cc50c

File tree

6 files changed

+100
-71
lines changed

6 files changed

+100
-71
lines changed

include/swift/SIL/SILConstants.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
// This defines an interface to represent SIL level structured constants in an
13+
// This defines an interface to represent SIL level structured constants in a
1414
// memory efficient way.
1515
//
1616
//===----------------------------------------------------------------------===//
@@ -19,6 +19,8 @@
1919
#define SWIFT_SIL_CONSTANTS_H
2020

2121
#include "swift/SIL/SILValue.h"
22+
#include "llvm/Support/CommandLine.h"
23+
2224

2325
namespace swift {
2426
class SingleValueInstruction;
@@ -31,6 +33,8 @@ struct ArraySymbolicValue;
3133
struct EnumWithPayloadSymbolicValue;
3234
struct UnknownSymbolicValue;
3335

36+
extern llvm::cl::opt<unsigned> ConstExprLimit;
37+
3438
/// When we fail to constant fold a value, this captures a reason why,
3539
/// allowing the caller to produce a specific diagnostic. The "Unknown"
3640
/// SymbolicValue representation also includes a pointer to the SILNode in
@@ -85,8 +89,8 @@ class SymbolicValue {
8589
/// This value is represented with an inline integer representation.
8690
RK_IntegerInline,
8791

88-
/// This value is an array, struct, or tuple of constants. This is
89-
/// tracked by the "aggregate" member of the value union.
92+
/// This value is a struct or tuple of constants. This is tracked by the
93+
/// "aggregate" member of the value union.
9094
RK_Aggregate,
9195
};
9296

@@ -159,7 +163,7 @@ class SymbolicValue {
159163

160164
static SymbolicValue getUnknown(SILNode *node, UnknownReason reason,
161165
llvm::ArrayRef<SourceLoc> callStack,
162-
llvm::BumpPtrAllocator &allocator);
166+
ASTContext &astContext);
163167

164168
/// Return true if this represents an unknown result.
165169
bool isUnknown() const { return getKind() == Unknown; }
@@ -200,15 +204,15 @@ class SymbolicValue {
200204

201205
static SymbolicValue getInteger(int64_t value, unsigned bitWidth);
202206
static SymbolicValue getInteger(const APInt &value,
203-
llvm::BumpPtrAllocator &allocator);
207+
ASTContext &astContext);
204208

205209
APInt getIntegerValue() const;
206210
unsigned getIntegerValueBitWidth() const;
207211

208212
/// This returns an aggregate value with the specified elements in it. This
209-
/// copies the elements into the specified allocator.
213+
/// copies the elements into the specified ASTContext.
210214
static SymbolicValue getAggregate(ArrayRef<SymbolicValue> elements,
211-
llvm::BumpPtrAllocator &allocator);
215+
ASTContext &astContext);
212216

213217
ArrayRef<SymbolicValue> getAggregateValue() const;
214218

@@ -225,9 +229,9 @@ class SymbolicValue {
225229
/// reason, we fall back to using the specified location.
226230
void emitUnknownDiagnosticNotes(SILLocation fallbackLoc);
227231

228-
/// Clone this SymbolicValue into the specified allocator and return the new
232+
/// Clone this SymbolicValue into the specified ASTContext and return the new
229233
/// version. This only works for valid constants.
230-
SymbolicValue cloneInto(llvm::BumpPtrAllocator &allocator) const;
234+
SymbolicValue cloneInto(ASTContext &astContext) const;
231235

232236
void print(llvm::raw_ostream &os, unsigned indent = 0) const;
233237
void dump() const;

include/swift/SILOptimizer/Utils/ConstExpr.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
// with the goal of standardization in a future version of Swift.
1616
//
1717
// Constant expressions are functions without side effects that take constant
18-
// values and return constant values. These constants may be integer, floating
19-
// point, and string values, or arrays thereof (up to 1024 elements). We allow
20-
// abstractions to be built out of fragile structs and tuples.
18+
// values and return constant values. These constants may be integer, and
19+
// floating point values. We allow abstractions to be built out of fragile
20+
// structs and tuples.
2121
//
2222
//===----------------------------------------------------------------------===//
2323

@@ -30,6 +30,7 @@
3030

3131
namespace swift {
3232
class ApplyInst;
33+
class ASTContext;
3334
class Operand;
3435
class SILInstruction;
3536
class SILModule;
@@ -41,9 +42,10 @@ enum class UnknownReason;
4142
/// This class is the main entrypoint for evaluating constant expressions. It
4243
/// also handles caching of previously computed constexpr results.
4344
class ConstExprEvaluator {
44-
/// This is a long-lived bump pointer allocator that holds the arguments and
45-
/// result values for the cached constexpr calls we have already analyzed.
46-
llvm::BumpPtrAllocator &allocator;
45+
/// We store arguments and result values for the cached constexpr calls we
46+
/// have already analyzed in this ASTContext so that they are available even
47+
/// after this ConstExprEvaluator is gone.
48+
ASTContext &astContext;
4749

4850
/// The current call stack, used for providing accurate diagnostics.
4951
llvm::SmallVector<SourceLoc, 4> callStack;
@@ -55,7 +57,7 @@ class ConstExprEvaluator {
5557
explicit ConstExprEvaluator(SILModule &m);
5658
~ConstExprEvaluator();
5759

58-
llvm::BumpPtrAllocator &getAllocator() { return allocator; }
60+
ASTContext &getASTContext() { return astContext; }
5961

6062
void pushCallStack(SourceLoc loc) { callStack.push_back(loc); }
6163

lib/SIL/SILConstants.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
#include "llvm/Support/TrailingObjects.h"
1818
using namespace swift;
1919

20+
namespace swift {
21+
llvm::cl::opt<unsigned>
22+
ConstExprLimit("constexpr-limit", llvm::cl::init(512),
23+
llvm::cl::desc("Number of instructions interpreted in a"
24+
" constexpr function"));
25+
}
26+
2027
template <typename... T, typename... U>
2128
static InFlightDiagnostic diagnose(ASTContext &Context, SourceLoc loc,
2229
Diag<T...> diag, U &&... args) {
@@ -92,25 +99,26 @@ SymbolicValue::Kind SymbolicValue::getKind() const {
9299
}
93100
}
94101

95-
/// Clone this SymbolicValue into the specified allocator and return the new
102+
/// Clone this SymbolicValue into the specified ASTContext and return the new
96103
/// version. This only works for valid constants.
97104
SymbolicValue
98-
SymbolicValue::cloneInto(llvm::BumpPtrAllocator &allocator) const {
105+
SymbolicValue::cloneInto(ASTContext &astContext) const {
99106
auto thisRK = representationKind;
100107
switch (thisRK) {
101108
case RK_Unknown:
102109
case RK_Metatype:
103110
case RK_Function:
111+
assert(0 && "cloning this representation kind is not supported");
104112
case RK_IntegerInline:
105113
case RK_Integer:
106-
return SymbolicValue::getInteger(getIntegerValue(), allocator);
114+
return SymbolicValue::getInteger(getIntegerValue(), astContext);
107115
case RK_Aggregate: {
108116
auto elts = getAggregateValue();
109117
SmallVector<SymbolicValue, 4> results;
110118
results.reserve(elts.size());
111119
for (auto elt : elts)
112-
results.push_back(elt.cloneInto(allocator));
113-
return getAggregate(results, allocator);
120+
results.push_back(elt.cloneInto(astContext));
121+
return getAggregate(results, astContext);
114122
}
115123
}
116124
}
@@ -128,14 +136,14 @@ SymbolicValue SymbolicValue::getInteger(int64_t value, unsigned bitWidth) {
128136
}
129137

130138
SymbolicValue SymbolicValue::getInteger(const APInt &value,
131-
llvm::BumpPtrAllocator &allocator) {
139+
ASTContext &astContext) {
132140
// In the common case, we can form an inline representation.
133141
unsigned numWords = value.getNumWords();
134142
if (numWords == 1)
135143
return getInteger(value.getRawData()[0], value.getBitWidth());
136144

137145
// Copy the integers from the APInt into the bump pointer.
138-
auto *words = allocator.Allocate<uint64_t>(numWords);
146+
auto *words = astContext.Allocate<uint64_t>(numWords).data();
139147
std::uninitialized_copy(value.getRawData(), value.getRawData() + numWords,
140148
words);
141149

@@ -173,9 +181,10 @@ unsigned SymbolicValue::getIntegerValueBitWidth() const {
173181
/// This returns a constant Symbolic value with the specified elements in it.
174182
/// This assumes that the elements lifetime has been managed for this.
175183
SymbolicValue SymbolicValue::getAggregate(ArrayRef<SymbolicValue> elements,
176-
llvm::BumpPtrAllocator &allocator) {
177-
// Copy the integers from the APInt into the bump pointer.
178-
auto *resultElts = allocator.Allocate<SymbolicValue>(elements.size());
184+
ASTContext &astContext) {
185+
// Copy the elements into the bump pointer.
186+
auto *resultElts =
187+
astContext.Allocate<SymbolicValue>(elements.size()).data();
179188
std::uninitialized_copy(elements.begin(), elements.end(), resultElts);
180189

181190
SymbolicValue result;
@@ -212,10 +221,10 @@ struct alignas(SourceLoc) UnknownSymbolicValue final
212221

213222
static UnknownSymbolicValue *create(SILNode *node, UnknownReason reason,
214223
ArrayRef<SourceLoc> elements,
215-
llvm::BumpPtrAllocator &allocator) {
224+
ASTContext &astContext) {
216225
auto byteSize =
217226
UnknownSymbolicValue::totalSizeToAlloc<SourceLoc>(elements.size());
218-
auto rawMem = allocator.Allocate(byteSize, alignof(UnknownSymbolicValue));
227+
auto rawMem = astContext.Allocate(byteSize, alignof(UnknownSymbolicValue));
219228

220229
// Placement-new the value inside the memory we just allocated.
221230
auto value = ::new (rawMem) UnknownSymbolicValue(
@@ -245,12 +254,12 @@ struct alignas(SourceLoc) UnknownSymbolicValue final
245254

246255
SymbolicValue SymbolicValue::getUnknown(SILNode *node, UnknownReason reason,
247256
llvm::ArrayRef<SourceLoc> callStack,
248-
llvm::BumpPtrAllocator &allocator) {
257+
ASTContext &astContext) {
249258
assert(node && "node must be present");
250259
SymbolicValue result;
251260
result.representationKind = RK_Unknown;
252261
result.value.unknown =
253-
UnknownSymbolicValue::create(node, reason, callStack, allocator);
262+
UnknownSymbolicValue::create(node, reason, callStack, astContext);
254263
return result;
255264
}
256265

@@ -284,8 +293,8 @@ static SILDebugLocation skipInternalLocations(SILDebugLocation loc) {
284293
return loc;
285294

286295
// Zip through inlined call site information that came from the
287-
// implementation guts of the tensor library. We want to report the
288-
// message inside the user's code, not in the guts we inlined through.
296+
// implementation guts of the library. We want to report the message inside
297+
// the user's code, not in the guts we inlined through.
289298
for (; auto ics = ds->InlinedCallSite; ds = ics) {
290299
// If we found a valid inlined-into location, then we are good.
291300
if (ds->Loc.getSourceLoc().isValid())
@@ -351,7 +360,8 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
351360
break;
352361
case UnknownReason::TooManyInstructions:
353362
// TODO: Should pop up a level of the stack trace.
354-
error = "expression is too large to evaluate at compile-time";
363+
error = "exceeded instruction limit: " + std::to_string(ConstExprLimit) +
364+
" when evaluating the expression at compile time";
355365
break;
356366
case UnknownReason::Loop:
357367
error = "control flow loop found";
@@ -377,7 +387,7 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
377387
unsigned originalDiagnosticLineNumber =
378388
SM.getLineNumber(fallbackLoc.getSourceLoc());
379389
for (auto &sourceLoc : llvm::reverse(getUnknownCallStack())) {
380-
// Skip known sources.
390+
// Skip unknown sources.
381391
if (!sourceLoc.isValid())
382392
continue;
383393
// Also skip notes that point to the same line as the original error, for

lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,11 @@ static void diagnosePoundAssert(const SILInstruction *I,
148148
"sema prevents non-int1 #assert condition");
149149
if (intValue.isNullValue()) {
150150
auto *message = cast<StringLiteralInst>(builtinInst->getArguments()[1]);
151+
StringRef messageValue = message->getValue();
152+
if (messageValue.empty())
153+
messageValue = "assertion failed";
151154
diagnose(M.getASTContext(), I->getLoc().getSourceLoc(),
152-
diag::pound_assert_failure, message->getValue());
155+
diag::pound_assert_failure, messageValue);
153156
return;
154157
}
155158
}
@@ -165,13 +168,18 @@ class EmitDFDiagnostics : public SILFunctionTransform {
165168
return;
166169

167170
SILModule &M = getFunction()->getModule();
168-
ConstExprEvaluator constantEvaluator(M);
169171
for (auto &BB : *getFunction())
170172
for (auto &I : BB) {
171173
diagnoseUnreachable(&I, M.getASTContext());
172174
diagnoseStaticReports(&I, M);
173-
diagnosePoundAssert(&I, M, constantEvaluator);
174175
}
176+
177+
if (M.getASTContext().LangOpts.EnableExperimentalStaticAssert) {
178+
ConstExprEvaluator constantEvaluator(M);
179+
for (auto &BB : *getFunction())
180+
for (auto &I : BB)
181+
diagnosePoundAssert(&I, M, constantEvaluator);
182+
}
175183
}
176184
};
177185
} // end anonymous namespace

0 commit comments

Comments
 (0)