summaryrefslogtreecommitdiff
path: root/willow/unittest/IR/VerifierTest.cpp
diff options
context:
space:
mode:
authorStefan Weigl-Bosker <stefan@s00.xyz>2026-02-19 13:13:41 -0500
committerGitHub <noreply@github.com>2026-02-19 13:13:41 -0500
commit1fd2d6d88f5f78d879bf38bb3fba7fa2e749d3b0 (patch)
treeeb5a0740956812678131970687377339fad5a541 /willow/unittest/IR/VerifierTest.cpp
parentadd95b14f74e6dbe04a6efe98ff0f20424930b73 (diff)
downloadcompiler-1fd2d6d88f5f78d879bf38bb3fba7fa2e749d3b0.tar.gz
[willow]: initial IRBuilder API (#9)
- add IRBuilder api - remove `name` field from `Value` - fix some bugs in IList interface - more verifier tests
Diffstat (limited to 'willow/unittest/IR/VerifierTest.cpp')
-rw-r--r--willow/unittest/IR/VerifierTest.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/willow/unittest/IR/VerifierTest.cpp b/willow/unittest/IR/VerifierTest.cpp
new file mode 100644
index 0000000..efe34db
--- /dev/null
+++ b/willow/unittest/IR/VerifierTest.cpp
@@ -0,0 +1,82 @@
+#include <catch2/catch_test_macros.hpp>
+
+#include <willow/IR/Context.h>
+#include <willow/IR/Diagnostic.h>
+#include <willow/IR/DiagnosticEngine.h>
+#include <willow/IR/Function.h>
+#include <willow/IR/IRBuilder.h>
+#include <willow/IR/Module.h>
+#include <willow/IR/Verifier.h>
+
+using namespace willow;
+
+TEST_CASE("valid modules", "[verifier]") {
+ WillowContext ctx;
+ std::vector<Diagnostic> diags;
+ DiagnosticEngine eng([&](Diagnostic d) { diags.push_back(std::move(d)); });
+
+ auto &m = *ctx.addModule("test");
+ SECTION("empty module") {
+ REQUIRE(succeeded(verifyModule(ctx, m, eng)));
+ REQUIRE(diags.empty());
+ }
+}
+
+TEST_CASE("valid function", "[verifier]") {
+ WillowContext ctx;
+ std::vector<Diagnostic> diags;
+ DiagnosticEngine eng([&](Diagnostic d) { diags.push_back(std::move(d)); });
+
+ auto &m = *ctx.addModule("test");
+
+ Type fty = ctx.types().FunctionType(ctx.types().VoidType(), {});
+ auto &fn = *m.emplaceFunction("fn", &m, fty);
+
+ REQUIRE(succeeded(verifyFunction(ctx, fn, eng)));
+ REQUIRE(diags.empty());
+}
+
+TEST_CASE("invalid basic block", "[verifier]") {
+ WillowContext ctx;
+ std::vector<Diagnostic> diags;
+ DiagnosticEngine eng([&](Diagnostic d) { diags.push_back(std::move(d)); });
+
+ Type i64Ty = ctx.types().IntType(64);
+ Type voidTy = ctx.types().VoidType();
+ auto *one = ctx.constants().getInt(i64Ty, 1);
+
+ auto &m = *ctx.addModule("test");
+ Type fty = ctx.types().FunctionType(ctx.types().VoidType(), {});
+ Type ifty = ctx.types().FunctionType(i64Ty, {});
+ auto &fn = *m.emplaceFunction("fn", &m, fty);
+ auto &fn2 = *m.emplaceFunction("fn2", &m, ifty);
+ auto *bb = fn.addBlock(
+ std::make_unique<BasicBlock>(&fn, ctx.types().BasicBlockType()));
+ IRBuilder builder{ctx, *bb, bb->end()};
+
+ SECTION("Empty basic block") {
+ REQUIRE(bb->empty());
+ REQUIRE(failed(verifyBasicBlock(ctx, *bb, eng)));
+ }
+
+ SECTION("Basic block with no terminator") {
+ builder.BuildAdd(i64Ty, one, one);
+ REQUIRE(failed(verifyBasicBlock(ctx, *bb, eng)));
+ }
+
+ SECTION("Teminator must be the last instruction in a basic block") {
+ builder.BuildCall(i64Ty, &fn2);
+ builder.BuildAdd(i64Ty, one, one);
+ REQUIRE(failed(verifyBasicBlock(ctx, *bb, eng)));
+ }
+
+ SECTION("Basic block with invalid instruction") {
+ auto *bb2 = fn.addBlock(
+ std::make_unique<BasicBlock>(&fn, ctx.types().BasicBlockType()));
+ builder.SetInsertPoint(bb2->end());
+ builder.BuildAdd(voidTy, one, one);
+ builder.BuildRet();
+
+ REQUIRE(failed(verifyBasicBlock(ctx, *bb, eng)));
+ }
+}