diff options
Diffstat (limited to 'willow/lib')
| -rw-r--r-- | willow/lib/IR/IRBuilder.cpp | 210 | ||||
| -rw-r--r-- | willow/lib/IR/TypeContext.cpp | 31 | ||||
| -rw-r--r-- | willow/lib/IR/Value.cpp | 54 | ||||
| -rw-r--r-- | willow/lib/IR/Verifier.cpp | 29 |
4 files changed, 281 insertions, 43 deletions
diff --git a/willow/lib/IR/IRBuilder.cpp b/willow/lib/IR/IRBuilder.cpp new file mode 100644 index 0000000..62e7a98 --- /dev/null +++ b/willow/lib/IR/IRBuilder.cpp @@ -0,0 +1,210 @@ +#include <willow/IR/IRBuilder.h> + +namespace willow { + +AddInst *IRBuilder::BuildAdd(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new AddInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +MulInst *IRBuilder::BuildMul(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new MulInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +SubInst *IRBuilder::BuildSub(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new SubInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +DivInst *IRBuilder::BuildDiv(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new DivInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +ModInst *IRBuilder::BuildMod(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new ModInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +ShlInst *IRBuilder::BuildShl(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new ShlInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +ShrInst *IRBuilder::BuildShr(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new ShrInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +AshlInst *IRBuilder::BuildAshl(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new AshlInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +AshrInst *IRBuilder::BuildAshr(Type type, Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new AshrInst{type, lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +EqInst *IRBuilder::BuildEq(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new EqInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +LtInst *IRBuilder::BuildLt(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new LtInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +GtInst *IRBuilder::BuildGt(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new GtInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +LeInst *IRBuilder::BuildLe(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new LeInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +GeInst *IRBuilder::BuildGe(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new GeInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +AndInst *IRBuilder::BuildAnd(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new AndInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +OrInst *IRBuilder::BuildOr(Value *lhs, Value *rhs, + std::optional<Location> loc) { + auto *inst = new OrInst{ctx.types().IntType(1), lhs, rhs, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +NotInst *IRBuilder::BuildNot(Value *val, std::optional<Location> loc) { + auto *inst = new NotInst{ctx.types().IntType(1), val, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +JmpInst *IRBuilder::BuildJmp(BasicBlock *dst, std::optional<Location> loc) { + + auto *inst = new JmpInst{ctx.types().VoidType(), dst, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +BrInst *IRBuilder::BuildBr(Value *predicate, BasicBlock *truedst, + BasicBlock *falsedst, std::optional<Location> loc) { + auto *inst = + new BrInst{ctx.types().VoidType(), predicate, truedst, falsedst, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +RetInst *IRBuilder::BuildRet(Value *val, std::optional<Location> loc) { + auto *inst = new RetInst{ctx.types().VoidType(), val, loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} +RetInst *IRBuilder::BuildRet(std::optional<Location> loc) { + auto *inst = new RetInst{ctx.types().VoidType(), loc}; + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +PhiInst *IRBuilder::BuildPhi( + Type ty, std::initializer_list<std::pair<BasicBlock *, Value *>> args, + std::optional<Location> loc) { + auto *inst = new PhiInst(ty, args, loc); + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +AllocaInst *IRBuilder::BuildAlloca(Type ty, std::optional<Location> loc) { + Type pty = ctx.types().PtrType(ty); + auto *inst = new AllocaInst(pty, loc); + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + +}; // namespace willow diff --git a/willow/lib/IR/TypeContext.cpp b/willow/lib/IR/TypeContext.cpp index e69de29..21e5173 100644 --- a/willow/lib/IR/TypeContext.cpp +++ b/willow/lib/IR/TypeContext.cpp @@ -0,0 +1,31 @@ +#include <willow/IR/TypeContext.h> + +namespace willow { + +Type TypeContext::IntType(std::size_t width) { + auto [it, _] = icache.try_emplace(IntTypeImpl::Key{width}, + std::make_unique<IntTypeImpl>(width)); + + return Type(it->second.get()); +} + +Type TypeContext::PtrType(Type pointee) { + auto [it, _] = pcache.try_emplace( + PtrTypeImpl::Key{pointee}, std::make_unique<PtrTypeImpl>(pointee)); + + return Type(it->second.get()); +} + +Type TypeContext::VoidType() { return Type(voidty.get()); } + +Type TypeContext::BasicBlockType() { return Type{labelty.get()}; } + +Type TypeContext::FunctionType(Type ret, std::initializer_list<Type> params) { + auto [it, _] = + fncache.try_emplace(FunctionTypeImpl::Key{ret, params}, + std::make_unique<FunctionTypeImpl>(ret, params)); + + return Type(it->second.get()); +}; + +}; diff --git a/willow/lib/IR/Value.cpp b/willow/lib/IR/Value.cpp index 13e029f..0bd1079 100644 --- a/willow/lib/IR/Value.cpp +++ b/willow/lib/IR/Value.cpp @@ -1,27 +1,27 @@ -#include <willow/IR/Value.h> -#include <willow/IR/Constant.h> -#include <ostream> - -std::ostream &operator<<(std::ostream &os, const willow::Value &v) { - using willow::ValueKind; - auto ty = v.getType(); - if (!v.isVoid()) - os << ty << " "; - - switch (v.getValueKind()) { - case ValueKind::Parameter: - [[fallthrough]]; - case ValueKind::Instruction: { - return os << "%" << v.getName(); - } - case ValueKind::BasicBlock: { - return os << "^" << v.getName(); - } - case ValueKind::Function: { - return os << "@" << v.getName(); - } - case ValueKind::Constant: { - return os << *static_cast<const willow::Constant*>(&v); - } - } -} +// #include <willow/IR/Value.h> +// #include <willow/IR/Constant.h> +// #include <ostream> +// +// std::ostream &operator<<(std::ostream &os, const willow::Value &v) { +// using willow::ValueKind; +// auto ty = v.getType(); +// if (!v.isVoid()) +// os << ty << " "; +// +// switch (v.getValueKind()) { +// case ValueKind::Parameter: +// [[fallthrough]]; +// case ValueKind::Instruction: { +// return os << "%" << v.getName(); +// } +// case ValueKind::BasicBlock: { +// return os << "^" << v.getName(); +// } +// case ValueKind::Function: { +// return os << "@" << v.getName(); +// } +// case ValueKind::Constant: { +// return os << *static_cast<const willow::Constant*>(&v); +// } +// } +// } diff --git a/willow/lib/IR/Verifier.cpp b/willow/lib/IR/Verifier.cpp index d19bc83..b622f10 100644 --- a/willow/lib/IR/Verifier.cpp +++ b/willow/lib/IR/Verifier.cpp @@ -1,3 +1,4 @@ +#include <iostream> #include <willow/IR/BasicBlock.h> #include <willow/IR/Diagnostic.h> #include <willow/IR/DiagnosticEngine.h> @@ -75,20 +76,19 @@ LogicalResult verifyBasicBlock(WillowContext &ctx, const BasicBlock &BB, DiagnosticEngine &diags) { if (BB.empty()) return emit(diags, Severity::Error, BB.getLoc()) - << "Basic block '" << BB.getName() << "' has an empty body"; + << "Basic block has empty body"; - if (!BB.trailer()->isTerminator()) + if (!BB.trailer().isTerminator()) return emit(diags, Severity::Error, BB.getLoc()) - << "Basic block '" << BB.getName() - << "' does not end with a terminator"; + << "Basic block does not end with a terminator"; bool has_failed = false; - for (auto &inst : BB.getBody()) { + for (auto& inst : BB) { // verify inst if (failed(verifyInst(ctx, inst, diags))) has_failed = true; - if (&inst != BB.trailer() && inst.isTerminator()) + if (&inst != &BB.trailer() && inst.isTerminator()) return emit(diags, Severity::Error, BB.getLoc()) << "Illegal terminator in the middle of a block"; } @@ -219,11 +219,9 @@ LogicalResult verifyInst(WillowContext &ctx, const Instruction &inst, if (aty == pty) continue; - DiagnosticBuilder d(diags, Severity::Error, inst.getLoc()); - d << "invalid argument: expected '" << pty << "', got '" << aty << "'"; - if (param.hasName()) - d.note(Diagnostic{Severity::Remark, - std::format("param name: {}", param.getName())}); + return emit(diags, Severity::Error, inst.getLoc()) + << "invalid argument: expected '" << pty << "', got '" << aty + << "'"; return failure(); } @@ -266,8 +264,7 @@ LogicalResult verifyInst(WillowContext &ctx, const Instruction &inst, if (BB && fn && (pred->getParent() != fn)) return emit(diags, Severity::Error, inst.getLoc()) - << "basic block: '" << pred->getName() - << "' is not a child of function '" << fn->getName() << "'"; + << "invalid predecessor"; } return success(); @@ -344,14 +341,14 @@ LogicalResult verifyBinaryIntegerCmp(WillowContext &ctx, } LogicalResult verifyResult(const Instruction &inst, DiagnosticEngine &diags) { - if (inst.hasName()) - return success(); + if (!inst.getType().isVoid()) + return success(); return emit(diags, Severity::Error, inst.getLoc()) << "expected ssa result"; } LogicalResult verifyNoResult(const Instruction &inst, DiagnosticEngine &diags) { - if (!inst.hasName()) + if (inst.getType().isVoid()) return success(); return emit(diags, Severity::Error, inst.getLoc()) << "unexpected ssa result"; |