Skip to content

Commit 390daea

Browse files
author
Marc Rasi
committed
address comments
1 parent 44d7cdd commit 390daea

File tree

7 files changed

+101
-56
lines changed

7 files changed

+101
-56
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,15 @@ ERROR(pound_assert_condition_not_constant,none,
303303
ERROR(pound_assert_failure,none,
304304
"%0", (StringRef))
305305

306-
NOTE(constexpr_unknown_reason, none, "%0", (StringRef))
307-
NOTE(constexpr_called_from, none, "when called from here", ())
308-
NOTE(constexpr_not_evaluable, none,
306+
NOTE(constexpr_unknown_reason_default,none, "could not fold operation", ())
307+
NOTE(constexpr_too_many_instructions,none,
308+
"exceeded instruction limit: %0 when evaluating the expression at compile "
309+
"time", (unsigned))
310+
NOTE(constexpr_loop,none, "control flow loop found", ())
311+
NOTE(constexpr_overflow,none, "integer overflow detected", ())
312+
NOTE(constexpr_trap,none, "trap detected", ())
313+
NOTE(constexpr_called_from,none, "when called from here", ())
314+
NOTE(constexpr_not_evaluable,none,
309315
"expression not evaluable as constant here", ())
310316

311317
ERROR(non_physical_addressof,none,

include/swift/SIL/SILConstants.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,15 @@ class SymbolicValue {
121121

122122
union {
123123
/// This is the reason code for RK_Unknown values.
124-
UnknownReason unknown_reason : 32;
124+
UnknownReason unknownReason : 32;
125125

126126
/// This is the number of bits in an RK_Integer or RK_IntegerInline
127127
/// representation, which makes the number of entries in the list derivable.
128-
unsigned integer_bitwidth;
128+
unsigned integerBitwidth;
129129

130130
/// This is the number of elements for an RK_Aggregate representation.
131-
unsigned aggregate_numElements;
132-
} aux;
131+
unsigned aggregateNumElements;
132+
} auxInfo;
133133

134134
public:
135135
/// This enum is used to indicate the sort of value held by a SymbolicValue
@@ -238,7 +238,9 @@ class SymbolicValue {
238238
};
239239

240240
static_assert(sizeof(SymbolicValue) == 2 * sizeof(void *),
241-
"SymbolicValue should stay small and POD");
241+
"SymbolicValue should stay small");
242+
static_assert(std::is_pod<SymbolicValue>::value,
243+
"SymbolicValue should stay POD");
242244

243245
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, SymbolicValue val) {
244246
val.print(os);

lib/SIL/SILConstants.cpp

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ SymbolicValue SymbolicValue::getInteger(int64_t value, unsigned bitWidth) {
131131
SymbolicValue result;
132132
result.representationKind = RK_IntegerInline;
133133
result.value.integerInline = value;
134-
result.aux.integer_bitwidth = bitWidth;
134+
result.auxInfo.integerBitwidth = bitWidth;
135135
return result;
136136
}
137137

@@ -150,28 +150,29 @@ SymbolicValue SymbolicValue::getInteger(const APInt &value,
150150
SymbolicValue result;
151151
result.representationKind = RK_Integer;
152152
result.value.integer = words;
153-
result.aux.integer_bitwidth = value.getBitWidth();
153+
result.auxInfo.integerBitwidth = value.getBitWidth();
154154
return result;
155155
}
156156

157157
APInt SymbolicValue::getIntegerValue() const {
158158
assert(getKind() == Integer);
159159
if (representationKind == RK_IntegerInline) {
160-
auto numBits = aux.integer_bitwidth;
160+
auto numBits = auxInfo.integerBitwidth;
161161
return APInt(numBits, value.integerInline);
162162
}
163163

164164
assert(representationKind == RK_Integer);
165-
auto numBits = aux.integer_bitwidth;
166-
auto numWords = (numBits + 63) / 64;
165+
auto numBits = auxInfo.integerBitwidth;
166+
auto numWords =
167+
(numBits + APInt::APINT_BITS_PER_WORD - 1) / APInt::APINT_BITS_PER_WORD;
167168
return APInt(numBits, {value.integer, numWords});
168169
}
169170

170171
unsigned SymbolicValue::getIntegerValueBitWidth() const {
171172
assert(getKind() == Integer);
172173
assert (representationKind == RK_IntegerInline ||
173174
representationKind == RK_Integer);
174-
return aux.integer_bitwidth;
175+
return auxInfo.integerBitwidth;
175176
}
176177

177178
//===----------------------------------------------------------------------===//
@@ -190,13 +191,13 @@ SymbolicValue SymbolicValue::getAggregate(ArrayRef<SymbolicValue> elements,
190191
SymbolicValue result;
191192
result.representationKind = RK_Aggregate;
192193
result.value.aggregate = resultElts;
193-
result.aux.aggregate_numElements = elements.size();
194+
result.auxInfo.aggregateNumElements = elements.size();
194195
return result;
195196
}
196197

197198
ArrayRef<SymbolicValue> SymbolicValue::getAggregateValue() const {
198199
assert(getKind() == Aggregate);
199-
return ArrayRef<SymbolicValue>(value.aggregate, aux.aggregate_numElements);
200+
return ArrayRef<SymbolicValue>(value.aggregate, auxInfo.aggregateNumElements);
200201
}
201202

202203
//===----------------------------------------------------------------------===//
@@ -217,7 +218,7 @@ struct alignas(SourceLoc) UnknownSymbolicValue final
217218
UnknownReason reason;
218219

219220
/// The number of elements in the call stack.
220-
unsigned call_stack_size;
221+
unsigned callStackSize;
221222

222223
static UnknownSymbolicValue *create(SILNode *node, UnknownReason reason,
223224
ArrayRef<SourceLoc> elements,
@@ -235,20 +236,20 @@ struct alignas(SourceLoc) UnknownSymbolicValue final
235236
}
236237

237238
ArrayRef<SourceLoc> getCallStack() const {
238-
return {getTrailingObjects<SourceLoc>(), call_stack_size};
239+
return {getTrailingObjects<SourceLoc>(), callStackSize};
239240
}
240241

241242
// This is used by the llvm::TrailingObjects base class.
242243
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
243-
return call_stack_size;
244+
return callStackSize;
244245
}
245246

246247
private:
247248
UnknownSymbolicValue() = delete;
248249
UnknownSymbolicValue(const UnknownSymbolicValue &) = delete;
249250
UnknownSymbolicValue(SILNode *node, UnknownReason reason,
250-
unsigned call_stack_size)
251-
: node(node), reason(reason), call_stack_size(call_stack_size) {}
251+
unsigned callStackSize)
252+
: node(node), reason(reason), callStackSize(callStackSize) {}
252253
};
253254
} // namespace swift
254255

@@ -330,7 +331,7 @@ SymbolicValue SymbolicValue::lookThroughSingleElementAggregates() const {
330331
/// is an interesting SourceLoc to point at.
331332
/// Returns true if a diagnostic was emitted.
332333
static bool emitNoteDiagnostic(SILInstruction *badInst, UnknownReason reason,
333-
SILLocation fallbackLoc, std::string error) {
334+
SILLocation fallbackLoc) {
334335
auto loc = skipInternalLocations(badInst->getDebugLocation()).getLocation();
335336
if (loc.isNull()) {
336337
// If we have important clarifying information, make sure to emit it.
@@ -339,63 +340,55 @@ static bool emitNoteDiagnostic(SILInstruction *badInst, UnknownReason reason,
339340
loc = fallbackLoc;
340341
}
341342

342-
auto &module = badInst->getModule();
343-
diagnose(module.getASTContext(), loc.getSourceLoc(),
344-
diag::constexpr_unknown_reason, error)
345-
.highlight(loc.getSourceRange());
346-
return true;
347-
}
348-
349-
/// Given that this is an 'Unknown' value, emit diagnostic notes providing
350-
/// context about what the problem is.
351-
void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
352-
auto badInst = dyn_cast<SILInstruction>(getUnknownNode());
353-
if (!badInst)
354-
return;
355-
356-
std::string error;
357-
switch (getUnknownReason()) {
343+
auto &ctx = badInst->getModule().getASTContext();
344+
auto sourceLoc = loc.getSourceLoc();
345+
switch (reason) {
358346
case UnknownReason::Default:
359-
error = "could not fold operation";
347+
diagnose(ctx, sourceLoc, diag::constexpr_unknown_reason_default)
348+
.highlight(loc.getSourceRange());
360349
break;
361350
case UnknownReason::TooManyInstructions:
362351
// TODO: Should pop up a level of the stack trace.
363-
error = "exceeded instruction limit: " + std::to_string(ConstExprLimit) +
364-
" when evaluating the expression at compile time";
352+
diagnose(ctx, sourceLoc, diag::constexpr_too_many_instructions,
353+
ConstExprLimit)
354+
.highlight(loc.getSourceRange());
365355
break;
366356
case UnknownReason::Loop:
367-
error = "control flow loop found";
357+
diagnose(ctx, sourceLoc, diag::constexpr_loop)
358+
.highlight(loc.getSourceRange());
368359
break;
369360
case UnknownReason::Overflow:
370-
error = "integer overflow detected";
361+
diagnose(ctx, sourceLoc, diag::constexpr_overflow)
362+
.highlight(loc.getSourceRange());
371363
break;
372364
case UnknownReason::Trap:
373-
error = "trap detected";
365+
diagnose(ctx, sourceLoc, diag::constexpr_trap)
366+
.highlight(loc.getSourceRange());
374367
break;
375368
}
369+
return true;
370+
}
371+
372+
/// Given that this is an 'Unknown' value, emit diagnostic notes providing
373+
/// context about what the problem is.
374+
void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
375+
auto badInst = dyn_cast<SILInstruction>(getUnknownNode());
376+
if (!badInst)
377+
return;
376378

377-
bool emittedFirstNote =
378-
emitNoteDiagnostic(badInst, getUnknownReason(), fallbackLoc, error);
379+
bool emittedFirstNote = emitNoteDiagnostic(badInst, getUnknownReason(),
380+
fallbackLoc);
379381

380382
auto sourceLoc = fallbackLoc.getSourceLoc();
381383
auto &module = badInst->getModule();
382384
if (sourceLoc.isInvalid()) {
383385
diagnose(module.getASTContext(), sourceLoc, diag::constexpr_not_evaluable);
384386
return;
385387
}
386-
auto &SM = module.getASTContext().SourceMgr;
387-
unsigned originalDiagnosticLineNumber =
388-
SM.getLineNumber(fallbackLoc.getSourceLoc());
389388
for (auto &sourceLoc : llvm::reverse(getUnknownCallStack())) {
390389
// Skip unknown sources.
391390
if (!sourceLoc.isValid())
392391
continue;
393-
// Also skip notes that point to the same line as the original error, for
394-
// example in:
395-
// #assert(foo(bar()))
396-
// it is not useful to get three diagnostics referring to the same line.
397-
if (SM.getLineNumber(sourceLoc) == originalDiagnosticLineNumber)
398-
continue;
399392

400393
auto diag = emittedFirstNote ? diag::constexpr_called_from
401394
: diag::constexpr_not_evaluable;

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class ConstExprFunctionState {
8080
numInstEvaluated(numInstEvaluated) {}
8181

8282
void setValue(SILValue value, SymbolicValue symVal) {
83+
// TODO(constexpr patch): Uncomment this assertion once Address kinds have
84+
// been added.
85+
// assert(symVal.getKind() != SymbolicValue::Address &&
86+
// "calculatedValues does not hold addresses");
8387
calculatedValues.insert({value, symVal});
8488
}
8589

test/SILOptimizer/pound_assert.sil

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-sil-opt -enable-experimental-static-assert -assume-parsing-unqualified-ownership-sil %s -dataflow-diagnostics -verify
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
8+
// Static assertion that "1 + 1 == 2".
9+
sil @test1 : $@convention(thin) () -> () {
10+
bb0:
11+
%0 = integer_literal $Builtin.Int32, 1
12+
%1 = builtin "add_Int32"(%0 : $Builtin.Int32, %0 : $Builtin.Int32) : $(Builtin.Int32)
13+
%2 = integer_literal $Builtin.Int32, 2
14+
%3 = builtin "cmp_eq_Int32"(%1 : $Builtin.Int32, %2 : $Builtin.Int32) : $(Builtin.Int1)
15+
%4 = string_literal utf8 ""
16+
%5 = builtin "poundAssert"(%3 : $Builtin.Int1, %4 : $Builtin.RawPointer) : $()
17+
return undef : $()
18+
}
19+
20+
// Static assertion that "2 + 2 == 5".
21+
sil @test2 : $@convention(thin) () -> () {
22+
bb0:
23+
%0 = integer_literal $Builtin.Int32, 2
24+
%1 = builtin "add_Int32"(%0 : $Builtin.Int32, %0 : $Builtin.Int32) : $(Builtin.Int32)
25+
%2 = integer_literal $Builtin.Int32, 5
26+
%3 = builtin "cmp_eq_Int32"(%1 : $Builtin.Int32, %2 : $Builtin.Int32) : $(Builtin.Int1)
27+
%4 = string_literal utf8 ""
28+
// expected-error @+1 {{assertion failed}}
29+
%5 = builtin "poundAssert"(%3 : $Builtin.Int1, %4 : $Builtin.RawPointer) : $()
30+
return undef : $()
31+
}

test/SILOptimizer/pound_assert.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ func infiniteLoop() -> Int {
3434
}
3535

3636
func test_infiniteLoop() {
37-
// expected-error @+1 {{#assert condition not constant}}
37+
// expected-error @+2 {{#assert condition not constant}}
38+
// expected-note @+1 {{when called from here}}
3839
#assert(infiniteLoop() == 1)
3940
}
4041

tools/sil-opt/SILOpt.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ static llvm::cl::opt<bool> DisableGuaranteedNormalArguments(
214214
llvm::cl::desc("Assume that the input module was compiled with "
215215
"-disable-guaranteed-normal-arguments enabled"));
216216

217+
static llvm::cl::opt<bool>
218+
EnableExperimentalStaticAssert(
219+
"enable-experimental-static-assert", llvm::cl::Hidden,
220+
llvm::cl::init(false), llvm::cl::desc("Enable experimental #assert"));
221+
217222
/// Regular expression corresponding to the value given in one of the
218223
/// -pass-remarks* command line flags. Passes whose name matches this regexp
219224
/// will emit a diagnostic.
@@ -325,6 +330,9 @@ int main(int argc, char **argv) {
325330
Invocation.getLangOptions().OptimizationRemarkMissedPattern =
326331
createOptRemarkRegex(PassRemarksMissed);
327332

333+
Invocation.getLangOptions().EnableExperimentalStaticAssert =
334+
EnableExperimentalStaticAssert;
335+
328336
// Setup the SIL Options.
329337
SILOptions &SILOpts = Invocation.getSILOptions();
330338
SILOpts.InlineThreshold = SILInlineThreshold;

0 commit comments

Comments
 (0)