Skip to content

Commit d1cbc14

Browse files
committed
---
yaml --- r: 348581 b: refs/heads/master c: 1fe9aa6 h: refs/heads/master i: 348579: 4ac5bd4
1 parent 8728465 commit d1cbc14

18 files changed

+1582
-231
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 1c96568685605c1bf0bf10e6d6f144a165630201
2+
refs/heads/master: 1fe9aa60dd7447ee6f1c111249bfb722eb5b4d09
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/Builtins.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ BUILTIN_BINARY_OPERATION(ExactUDiv, "udiv_exact", "n", IntegerOrVector)
7575
BUILTIN_BINARY_OPERATION(URem, "urem", "n", Integer)
7676
BUILTIN_BINARY_OPERATION(FRem, "frem", "n", FloatOrVector)
7777
BUILTIN_BINARY_OPERATION(Xor, "xor", "n", IntegerOrVector)
78+
// This builtin is an optimizer hint and always returns the first argument.
79+
BUILTIN_BINARY_OPERATION(Expect, "int_expect", "n", Integer)
7880
#undef BUILTIN_BINARY_OPERATION
7981

8082
/// These builtins are analogous the similarly named llvm intrinsics. The

trunk/include/swift/AST/DiagnosticsSIL.def

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -360,61 +360,75 @@ ERROR(pound_assert_failure,none,
360360
NOTE(constexpr_unknown_reason_default,none,
361361
"cannot evaluate expression as constant here", ())
362362
NOTE(constexpr_unevaluable_operation,none,
363-
"cannot constant evaluate operation", ())
363+
"cannot constant evaluate operation%select{| used by this call}0", (bool))
364364

365365
NOTE(constexpr_too_many_instructions,none,
366366
"exceeded instruction limit: %0 when evaluating the expression "
367367
"at compile time", (unsigned))
368-
NOTE(constexpr_limit_exceeding_instruction,none, "limit exceeded here", ())
368+
NOTE(constexpr_limit_exceeding_instruction,none, "limit exceeded "
369+
"%select{here|during this call}0", (bool))
369370

370371
NOTE(constexpr_loop_found_note,none,
371372
"control-flow loop found during evaluation ", ())
372-
NOTE(constexpr_loop_instruction,none, "found loop here", ())
373+
NOTE(constexpr_loop_instruction,none, "found loop "
374+
"%select{here|inside this call}0", (bool))
373375

374376
NOTE(constexpr_overflow,none, "integer overflow detected", ())
375-
NOTE(constexpr_overflow_operation,none, "operation overflows", ())
377+
NOTE(constexpr_overflow_operation,none, "operation"
378+
"%select{| performed during this call}0 overflows", (bool))
376379

377380
NOTE(constexpr_trap,none, "trap detected", ())
378-
NOTE(constexpr_trap_operation,none, "operation traps", ())
381+
NOTE(constexpr_trap_operation,none, "operation"
382+
"%select{| performed during this call}0 traps", (bool))
383+
384+
NOTE(constexpr_assertion_failed, none, "assertion failed with message: %0",
385+
(StringRef))
386+
NOTE(constexpr_assertion_failed_here, none, "assertion failed"
387+
"%select{ here| during this call}0 ", (bool))
379388

380389
NOTE(constexpr_invalid_operand_seen, none,
381390
"operation with invalid operands encountered during evaluation",())
382391
NOTE(constexpr_operand_invalid_here, none,
383-
"operation with invalid operands encountered here",())
392+
"operation with invalid operands encountered "
393+
"%select{here|during this call}0", (bool))
384394

385395
NOTE(constexpr_value_unknown_at_top_level,none,
386396
"cannot evaluate top-level value as constant here",())
387397
NOTE(constexpr_multiple_writers_found_at_top_level,none,
388398
"top-level value has multiple assignments",())
389399

390400
NOTE(constexpr_unsupported_instruction_found, none,
391-
"encountered operation not supported by the evaluator", ())
392-
NOTE(constexpr_unsupported_instruction_found_here,none,
393-
"operation not supported by the evaluator", ())
401+
"encountered operation not supported by the evaluator: %0", (StringRef))
402+
NOTE(constexpr_unsupported_instruction_found_here,none, "operation"
403+
"%select{| used by this call is}0 not supported by the evaluator", (bool))
394404

395405
NOTE(constexpr_unknown_function_called, none,
396-
"encountered call to a function whose body is not available", ())
406+
"encountered call to '%0' whose body is not available", (StringRef))
397407
NOTE(constexpr_unknown_function_called_here, none,
398-
"call to a function whose body is not available", ())
408+
"%select{|calls a }0function whose body is not available", (bool))
399409

400410
NOTE(constexpr_untracked_sil_value_use_found, none,
401411
"encountered use of a variable not tracked by the evaluator", ())
402412
NOTE(constexpr_untracked_sil_value_used_here, none,
403-
"untracked variable used here", ())
404-
405-
NOTE(constexpr_witness_call_with_no_conformance_found, none,
406-
"cannot find concrete conformance for a witness method call", ())
407-
NOTE(constexpr_witness_call_with_no_target_found, none,
408-
"cannot resolve a witness method call to a concrete function", ())
409-
NOTE(constexpr_witness_call_found_here, none,
410-
"witness method call found here", ())
413+
"untracked variable used %select{here|by this call}0", (bool))
414+
415+
NOTE(constexpr_unresolvable_witness_call, none,
416+
"encountered unresolvable witness method call: '%0'", (StringRef))
417+
NOTE(constexpr_no_witness_table_entry, none, "cannot find witness table entry "
418+
"%select{for this call|for a witness-method invoked during this call}0",
419+
(bool))
420+
NOTE(constexpr_witness_call_with_no_conformance, none,
421+
"cannot find concrete conformance "
422+
"%select{for this call|for a witness-method invoked during this call}0",
423+
(bool))
411424

412425
NOTE(constexpr_unknown_control_flow_due_to_skip,none, "branch depends on "
413426
"non-constant value produced by an unevaluated instructions", ())
414427
NOTE(constexpr_returned_by_unevaluated_instruction,none,
415428
"return value of an unevaluated instruction is not a constant", ())
416429
NOTE(constexpr_mutated_by_unevaluated_instruction,none, "value mutable by an "
417430
"unevaluated instruction is not a constant", ())
431+
ERROR(not_constant_evaluable, none, "not constant evaluable", ())
418432

419433
ERROR(non_physical_addressof,none,
420434
"addressof only works with purely physical lvalues; "

trunk/include/swift/SIL/SILConstants.h

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -41,63 +41,119 @@ extern llvm::cl::opt<unsigned> ConstExprLimit;
4141
/// allowing the caller to produce a specific diagnostic. The "Unknown"
4242
/// SymbolicValue representation also includes a pointer to the SILNode in
4343
/// question that was problematic.
44-
enum class UnknownReason {
45-
// TODO: Eliminate the default code, by making classifications for each
46-
// failure mode.
47-
Default,
44+
class UnknownReason {
45+
public:
46+
enum UnknownKind {
47+
// TODO: Eliminate the default kind, by making classifications for each
48+
// failure mode.
49+
Default,
50+
51+
/// The constant expression was too big. This is reported on a random
52+
/// instruction within the constexpr that triggered the issue.
53+
TooManyInstructions,
54+
55+
/// A control flow loop was found.
56+
Loop,
57+
58+
/// Integer overflow detected.
59+
Overflow,
60+
61+
/// Unspecified trap detected.
62+
Trap,
63+
64+
/// Assertion failure detected. These have an associated message unlike
65+
/// traps.
66+
AssertionFailure,
4867

49-
/// The constant expression was too big. This is reported on a random
50-
/// instruction within the constexpr that triggered the issue.
51-
TooManyInstructions,
68+
/// An operation was applied over operands whose symbolic values were
69+
/// constants but were not valid for the operation.
70+
InvalidOperandValue,
5271

53-
/// A control flow loop was found.
54-
Loop,
72+
/// Encountered an instruction not supported by the interpreter.
73+
UnsupportedInstruction,
5574

56-
/// Integer overflow detected.
57-
Overflow,
75+
/// Encountered a function call where the body of the called function is
76+
/// not available.
77+
CalleeImplementationUnknown,
5878

59-
/// Unspecified trap detected.
60-
Trap,
79+
/// Attempted to load from/store into a SIL value that was not tracked by
80+
/// the interpreter.
81+
UntrackedSILValue,
6182

62-
/// An operation was applied over operands whose symbolic values were
63-
/// constants but were not valid for the operation.
64-
InvalidOperandValue,
83+
/// Attempted to find a concrete protocol conformance for a witness method
84+
/// and failed.
85+
UnknownWitnessMethodConformance,
6586

66-
/// Encountered an instruction not supported by the interpreter.
67-
UnsupportedInstruction,
87+
/// Attempted to determine the SIL function of a witness method and failed.
88+
NoWitnesTableEntry,
6889

69-
/// Encountered a function call where the body of the called function is
70-
/// not available.
71-
CalleeImplementationUnknown,
90+
/// The value of a top-level variable cannot be determined to be a constant.
91+
/// This is only relevant in the backward evaluation mode, which is used by
92+
/// #assert.
93+
NotTopLevelConstant,
7294

73-
/// Attempted to load from/store into a SIL value that was not tracked by
74-
/// the interpreter.
75-
UntrackedSILValue,
95+
/// A top-level value has multiple writers. This is only relevant in the
96+
/// non-flow-sensitive evaluation mode, which is used by #assert.
97+
MutipleTopLevelWriters,
7698

77-
/// Attempted to find a concrete protocol conformance for a witness method
78-
/// and failed.
79-
UnknownWitnessMethodConformance,
99+
/// Indicates the return value of an instruction that was not evaluated
100+
/// during interpretation.
101+
ReturnedByUnevaluatedInstruction,
80102

81-
/// Attempted to determine the SIL function of a witness method (based on a
82-
/// concrete protocol conformance) and failed.
83-
UnresolvableWitnessMethod,
103+
/// Indicates that the value was possibly modified by an instruction
104+
/// that was not evaluated during the interpretation.
105+
MutatedByUnevaluatedInstruction,
106+
};
84107

85-
/// The value of a top-level variable cannot be determined to be a constant.
86-
/// This is only relevant in the backward evaluation mode, which is used by
87-
/// #assert.
88-
NotTopLevelConstant,
108+
private:
109+
UnknownKind kind;
89110

90-
/// A top-level value has multiple writers. This is only relevant in the
91-
/// non-flow-sensitive evaluation mode, which is used by #assert.
92-
MutipleTopLevelWriters,
111+
// Auxiliary information for different unknown kinds.
112+
union {
113+
SILFunction *function;
114+
const char *failedAssertMessage;
115+
} payload;
93116

94-
/// Indicates the return value of an instruction that was not evaluated during
95-
/// interpretation.
96-
ReturnedByUnevaluatedInstruction,
117+
public:
118+
UnknownKind getKind() { return kind; }
97119

98-
/// Indicates that the value was possibly modified by an instruction
99-
/// that was not evaluated during the interpretation.
100-
MutatedByUnevaluatedInstruction,
120+
static bool isUnknownKindWithPayload(UnknownKind kind) {
121+
return kind == UnknownKind::CalleeImplementationUnknown;
122+
}
123+
124+
static UnknownReason create(UnknownKind kind) {
125+
assert(!isUnknownKindWithPayload(kind));
126+
UnknownReason reason;
127+
reason.kind = kind;
128+
return reason;
129+
}
130+
131+
static UnknownReason createCalleeImplementationUnknown(SILFunction *callee) {
132+
assert(callee);
133+
UnknownReason reason;
134+
reason.kind = UnknownKind::CalleeImplementationUnknown;
135+
reason.payload.function = callee;
136+
return reason;
137+
}
138+
139+
SILFunction *getCalleeWithoutImplmentation() {
140+
assert(kind == UnknownKind::CalleeImplementationUnknown);
141+
return payload.function;
142+
}
143+
144+
static UnknownReason createAssertionFailure(const char *message,
145+
size_t size) {
146+
assert(message[size] == '\0' && "message must be null-terminated");
147+
UnknownReason reason;
148+
reason.kind = UnknownKind::AssertionFailure;
149+
reason.payload.failedAssertMessage = message;
150+
return reason;
151+
}
152+
153+
const char *getAssertionFailureMessage() {
154+
assert(kind == UnknownKind::AssertionFailure);
155+
return payload.failedAssertMessage;
156+
}
101157
};
102158

103159
/// An abstract class that exposes functions for allocating symbolic values.
@@ -241,9 +297,6 @@ class SymbolicValue {
241297
RepresentationKind representationKind : 8;
242298

243299
union {
244-
/// This is the reason code for RK_Unknown values.
245-
UnknownReason unknownReason : 32;
246-
247300
/// This is the number of bits in an RK_Integer or RK_IntegerInline
248301
/// representation, which makes the number of entries in the list derivable.
249302
unsigned integerBitwidth;

trunk/include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ PASS(ConditionForwarding, "condition-forwarding",
112112
"Conditional Branch Forwarding to Fold SIL switch_enum")
113113
PASS(ConstantEvaluatorTester, "test-constant-evaluator",
114114
"Test constant evaluator")
115+
PASS(ConstantEvaluableSubsetChecker, "test-constant-evaluable-subset",
116+
"Test Swift code snippets expected to be constant evaluable")
115117
PASS(CopyForwarding, "copy-forwarding",
116118
"Copy Forwarding to Remove Redundant Copies")
117119
PASS(CopyPropagation, "copy-propagation",

trunk/include/swift/SILOptimizer/Utils/ConstExpr.h

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class SILNode;
3838
class SymbolicValue;
3939
class SymbolicValueAllocator;
4040
class ConstExprFunctionState;
41-
enum class UnknownReason;
41+
class UnknownReason;
4242

4343
/// This class is the main entrypoint for evaluating constant expressions. It
4444
/// also handles caching of previously computed constexpr results.
@@ -48,10 +48,17 @@ class ConstExprEvaluator {
4848
/// The current call stack, used for providing accurate diagnostics.
4949
llvm::SmallVector<SourceLoc, 4> callStack;
5050

51+
/// When set to true, keep track of all functions called during an evaluation.
52+
bool trackCallees;
53+
/// Functions called during the evaluation. This is an auxiliary information
54+
/// provided to the clients.
55+
llvm::SmallPtrSet<SILFunction *, 2> calledFunctions;
56+
5157
void operator=(const ConstExprEvaluator &) = delete;
5258

5359
public:
54-
explicit ConstExprEvaluator(SymbolicValueAllocator &alloc);
60+
explicit ConstExprEvaluator(SymbolicValueAllocator &alloc,
61+
bool trackCallees = false);
5562
~ConstExprEvaluator();
5663

5764
explicit ConstExprEvaluator(const ConstExprEvaluator &other);
@@ -75,12 +82,23 @@ class ConstExprEvaluator {
7582
/// This is done in code that is not necessarily itself a constexpr
7683
/// function. The results are added to the results list which is a parallel
7784
/// structure to the input values.
78-
///
79-
/// TODO: Return information about which callees were found to be
80-
/// constexprs, which would allow the caller to delete dead calls to them
81-
/// that occur after after folding them.
8285
void computeConstantValues(ArrayRef<SILValue> values,
8386
SmallVectorImpl<SymbolicValue> &results);
87+
88+
void recordCalledFunctionIfEnabled(SILFunction *callee) {
89+
if (trackCallees) {
90+
calledFunctions.insert(callee);
91+
}
92+
}
93+
94+
/// If the evaluator was initialized with \c trackCallees enabled, return the
95+
/// SIL functions encountered during the evaluations performed with this
96+
/// evaluator. The returned functions include those that were called but
97+
/// failed to complete successfully.
98+
const SmallPtrSetImpl<SILFunction *> &getFuncsCalledDuringEvaluation() const {
99+
assert(trackCallees && "evaluator not configured to track callees");
100+
return calledFunctions;
101+
}
84102
};
85103

86104
/// A constant-expression evaluator that can be used to step through a control
@@ -106,7 +124,7 @@ class ConstExprStepEvaluator {
106124
/// Constructs a step evaluator given an allocator and a non-null pointer to a
107125
/// SILFunction.
108126
explicit ConstExprStepEvaluator(SymbolicValueAllocator &alloc,
109-
SILFunction *fun);
127+
SILFunction *fun, bool trackCallees = false);
110128
~ConstExprStepEvaluator();
111129

112130
/// Evaluate an instruction in the current interpreter state.
@@ -162,8 +180,6 @@ class ConstExprStepEvaluator {
162180

163181
Optional<SymbolicValue> lookupConstValue(SILValue value);
164182

165-
bool isKnownFunction(SILFunction *fun);
166-
167183
/// Returns true if and only if `errorVal` denotes an error that requires
168184
/// aborting interpretation and returning the error. Skipping an instruction
169185
/// that produces such errors is not a valid behavior.
@@ -175,7 +191,18 @@ class ConstExprStepEvaluator {
175191
/// Note that 'skipByMakingEffectsNonConstant' operation is not considered
176192
/// as an evaluation.
177193
unsigned instructionsEvaluatedByLastEvaluation() { return stepsEvaluated; }
194+
195+
/// If the evaluator was initialized with \c trackCallees enabled, return the
196+
/// SIL functions encountered during the evaluations performed with this
197+
/// evaluator. The returned functions include those that were called but
198+
/// failed to complete successfully. Targets of skipped apply instructions
199+
/// will not be included in the returned set.
200+
const SmallPtrSetImpl<SILFunction *> &getFuncsCalledDuringEvaluation() {
201+
return evaluator.getFuncsCalledDuringEvaluation();
202+
}
178203
};
179204

205+
bool isKnownConstantEvaluableFunction(SILFunction *fun);
206+
180207
} // end namespace swift
181208
#endif

trunk/lib/AST/Builtins.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1780,7 +1780,7 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
17801780
#define BUILTIN_BINARY_OPERATION(id, name, attrs, overload) case BuiltinValueKind::id:
17811781
#include "swift/AST/Builtins.def"
17821782
if (Types.size() != 1) return nullptr;
1783-
return getBinaryOperation(Id, Types[0]);
1783+
return getBinaryOperation(Id, Types[0]);
17841784

17851785
#define BUILTIN(id, name, Attrs)
17861786
#define BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(id, name, _, attrs, overload) case BuiltinValueKind::id:

0 commit comments

Comments
 (0)