[const evaluator] Expose the step-wise constant evaluation mode

(also referred to as flow-sensitive mode) so that the evaluator
can be used by clients to constant evaluate instructions in a
SILFunction body one by one following the flow of control.
This commit is contained in:
Ravi Kandhadai
2019-04-12 17:11:26 -07:00
parent 86e4467c52
commit 55e82004a2
6 changed files with 1073 additions and 4 deletions

View File

@@ -26,17 +26,18 @@
#include "swift/Basic/LLVM.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/SIL/SILBasicBlock.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace swift {
class ApplyInst;
class ASTContext;
class Operand;
class SILInstruction;
class SILFunction;
class SILModule;
class SILNode;
class SILValue;
class SymbolicValue;
class SymbolicValueAllocator;
class ConstExprFunctionState;
enum class UnknownReason;
/// This class is the main entrypoint for evaluating constant expressions. It
@@ -47,13 +48,14 @@ class ConstExprEvaluator {
/// The current call stack, used for providing accurate diagnostics.
llvm::SmallVector<SourceLoc, 4> callStack;
ConstExprEvaluator(const ConstExprEvaluator &) = delete;
void operator=(const ConstExprEvaluator &) = delete;
public:
explicit ConstExprEvaluator(SymbolicValueAllocator &alloc);
~ConstExprEvaluator();
explicit ConstExprEvaluator(const ConstExprEvaluator &other);
SymbolicValueAllocator &getAllocator() { return allocator; }
void pushCallStack(SourceLoc loc) { callStack.push_back(loc); }
@@ -81,5 +83,52 @@ public:
SmallVectorImpl<SymbolicValue> &results);
};
/// A constant-expression evaluator that can be used to step through a control
/// flow graph (SILFunction body) by evaluating one instruction at a time.
class ConstExprStepEvaluator {
private:
ConstExprEvaluator evaluator;
ConstExprFunctionState *internalState;
unsigned stepsEvaluated = 0;
/// Targets of branches that were visited. This is used to detect loops during
/// evaluation.
SmallPtrSet<SILBasicBlock *, 8> visitedBlocks;
Optional<SymbolicValue>
incrementStepsAndCheckLimit(SILInstruction *inst,
bool includeInInstructionLimit);
ConstExprStepEvaluator(const ConstExprEvaluator &) = delete;
void operator=(const ConstExprEvaluator &) = delete;
public:
/// Constructs a step evaluator given an allocator and a non-null pointer to a
/// SILFunction.
explicit ConstExprStepEvaluator(SymbolicValueAllocator &alloc,
SILFunction *fun);
~ConstExprStepEvaluator();
/// Evaluate an instruction in the current interpreter state.
/// \param instI instruction to be evaluated in the current interpreter state.
/// \returns a pair where the first and second elements are defined as
/// follows:
/// The first element is the iterator to the next instruction from where
/// the evaluation can continue, if the evaluation is successful.
/// Otherwise, it is None.
///
/// Second element is None, if the evaluation is successful.
/// Otherwise, is an unknown symbolic value that contains the error.
std::pair<Optional<SILBasicBlock::iterator>, Optional<SymbolicValue>>
evaluate(SILBasicBlock::iterator instI,
bool includeInInstructionLimit = true);
Optional<SymbolicValue> lookupConstValue(SILValue value);
bool isKnownFunction(SILFunction *fun);
};
} // end namespace swift
#endif