summaryrefslogtreecommitdiff
path: root/willow/lib
diff options
context:
space:
mode:
Diffstat (limited to 'willow/lib')
-rw-r--r--willow/lib/IR/Instruction.cpp37
-rw-r--r--willow/lib/IR/Verifier.cpp34
2 files changed, 57 insertions, 14 deletions
diff --git a/willow/lib/IR/Instruction.cpp b/willow/lib/IR/Instruction.cpp
index a61cd55..587736d 100644
--- a/willow/lib/IR/Instruction.cpp
+++ b/willow/lib/IR/Instruction.cpp
@@ -1,3 +1,38 @@
#include <willow/IR/Instruction.h>
-namespace willow {};
+namespace willow {
+
+bool Instruction::isTerminatorOp(Opcode op) {
+ using enum Opcode;
+ switch (op) {
+ case Jmp:
+ case Br:
+ case Call:
+ case Ret:
+ return true;
+ case Add:
+ case Mul:
+ case Sub:
+ case Div:
+ case Mod:
+ case Shl:
+ case Shr:
+ case Ashl:
+ case Ashr:
+ case Eq:
+ case Lt:
+ case Gt:
+ case Le:
+ case Ge:
+ case And:
+ case Or:
+ case Not:
+ case Phi:
+ case Alloca:
+ return false;
+ }
+}
+
+Successors Instruction::succs();
+
+}; // namespace willow
diff --git a/willow/lib/IR/Verifier.cpp b/willow/lib/IR/Verifier.cpp
index 459989a..f016bbb 100644
--- a/willow/lib/IR/Verifier.cpp
+++ b/willow/lib/IR/Verifier.cpp
@@ -9,9 +9,12 @@ namespace willow {
/// Verify that an instruction defines an SSA result
LogicalResult verifyResult(const Instruction &inst, DiagnosticEngine &diags);
+/// Verify that an instruction has the expected number of operands
LogicalResult verifyNumOperands(const Instruction &inst,
DiagnosticEngine &diags, std::size_t expected);
+LogicalResult verifyBinaryInst(const Instruction &, DiagnosticEngine &);
+
LogicalResult verifyModule(const Module &module, DiagnosticEngine &diags) {
bool any_failure = false;
@@ -43,23 +46,24 @@ LogicalResult verifyModule(const Module &module, DiagnosticEngine &diags) {
// }
LogicalResult verifyBasicBlock(const BasicBlock &BB, DiagnosticEngine &diags) {
- bool any_failure = false;
-
if (BB.empty())
return emit(diags, Severity::Error, BB.getLoc())
<< "Basic block '" << BB.getName() << "' has an empty body";
- auto *trailer = BB.trailer();
-
- if (!trailer->isTerminator()) {
- }
-
if (!BB.trailer()->isTerminator())
- // TODO: terminator check
+ return emit(diags, Severity::Error, BB.getLoc())
+ << "Basic block '" << BB.getName()
+ << "' does not end with a terminator";
- for (auto &inst : BB.getBody()) {
- // verify inst
- }
+ for (auto &inst : BB.getBody()) {
+ // verify inst
+ if (failed(verifyInst(inst, diags)))
+ return failure();
+
+ if (&inst != BB.trailer() && inst.isTerminator())
+ return emit(diags, Severity::Error, BB.getLoc())
+ << "Illegal terminator in the middle of a block";
+ }
}
// TODO: better instruction printing
@@ -149,6 +153,9 @@ LogicalResult verifyBinaryInst(const Instruction &inst,
<< "invalid instruction '" << inst << "': "
<< "expected an integral type, got '" << ty << "'";
+ if (failed(verifyNumOperands(inst, diags, 2)))
+ return failure();
+
auto *lhs = inst.getOperand(0);
auto *rhs = inst.getOperand(1);
@@ -177,8 +184,9 @@ LogicalResult verifyNumOperands(const Instruction &inst,
DiagnosticEngine &diags, std::size_t expected) {
std::size_t num_operands = inst.getNumOperands();
if (num_operands != expected)
- return emit(diags, Severity::Error, inst.getLoc()) << std::format(
- "expected {} operands, but got {}", expected, num_operands);
+ return emit(diags, Severity::Error, inst.getLoc())
+ << std::format("'{}':, expected {} operands, got {}", inst.opcode(),
+ expected, num_operands);
return success();
}