diff options
| author | Stefan Weigl-Bosker <stefan@s00.xyz> | 2026-02-19 18:45:44 -0500 |
|---|---|---|
| committer | Stefan Weigl-Bosker <stefan@s00.xyz> | 2026-02-19 18:45:44 -0500 |
| commit | af3d0ad1926eb825f64152cf217fc9a4777f0be3 (patch) | |
| tree | 8d7f73ce6c3c89863418382d8d553a06c668bbb3 /willow/include | |
| parent | d11fbc8268f5775ad783f8570478daad4a9e81cf (diff) | |
| download | compiler-more-tests.tar.gz | |
[willow]: more cleanup, testsmore-tests
Diffstat (limited to 'willow/include')
| -rw-r--r-- | willow/include/willow/IR/BasicBlock.h | 53 | ||||
| -rw-r--r-- | willow/include/willow/IR/Constant.h | 57 | ||||
| -rw-r--r-- | willow/include/willow/IR/ConstantPool.h | 35 | ||||
| -rw-r--r-- | willow/include/willow/IR/Diagnostic.h | 3 | ||||
| -rw-r--r-- | willow/include/willow/IR/DiagnosticEngine.h | 24 | ||||
| -rw-r--r-- | willow/include/willow/IR/Function.h | 35 | ||||
| -rw-r--r-- | willow/include/willow/IR/IRBuilder.h | 70 | ||||
| -rw-r--r-- | willow/include/willow/IR/Instruction.h | 13 | ||||
| -rw-r--r-- | willow/include/willow/IR/Instructions.h | 58 | ||||
| -rw-r--r-- | willow/include/willow/IR/Value.h | 34 |
10 files changed, 85 insertions, 297 deletions
diff --git a/willow/include/willow/IR/BasicBlock.h b/willow/include/willow/IR/BasicBlock.h index eb08c5d..7a3a947 100644 --- a/willow/include/willow/IR/BasicBlock.h +++ b/willow/include/willow/IR/BasicBlock.h @@ -54,38 +54,12 @@ public: Instruction *addInstruction(std::unique_ptr<Instruction> inst); - void push_back(Instruction &inst) { - assert(!inst.hasParent() && "Instruction is already parented"); - body.push_back(inst); - inst.setParent(this); - } - - void push_front(Instruction &inst) { - assert(!inst.hasParent() && "Instruction is already parented"); - body.push_front(inst); - inst.setParent(this); - } - - Iterator insert(Iterator pos, Instruction &inst) { - assert(!inst.hasParent() && "Instruction is already parented"); - auto it = body.insert(pos, inst); - inst.setParent(this); - return it; - } - - Iterator erase(Iterator pos) { - Instruction &I = *pos; - I.setParent(nullptr); - return body.erase(pos); - } + void push_back(Instruction &inst); + void push_front(Instruction &inst); + Iterator insert(Iterator pos, Instruction &inst); - Iterator eraseAndDelete(Iterator pos) { - Instruction &inst = *pos; - pos->setParent(nullptr); - auto it = body.erase(pos); - delete &inst; - return it; - } + Iterator erase(Iterator pos); + Iterator eraseAndDelete(Iterator pos); std::optional<Location> getLoc() const { return loc; } @@ -94,21 +68,8 @@ public: return predecessors; } - void addPred(BasicBlock *bb) { - auto [it, inserted] = predecessors.try_emplace(bb, 1); - - if (!inserted) - it->second += 1; - } - - void delPred(BasicBlock *bb) { - auto it = preds().find(bb); - - it->second -= 1; - - if (it->second <= 0) - preds().erase(it); - } + void addPred(BasicBlock *bb); + void delPred(BasicBlock *bb); }; } // namespace willow diff --git a/willow/include/willow/IR/Constant.h b/willow/include/willow/IR/Constant.h index 4e2a3d7..acdc75c 100644 --- a/willow/include/willow/IR/Constant.h +++ b/willow/include/willow/IR/Constant.h @@ -1,14 +1,12 @@ #ifndef WILLOW_INCLUDE_IR_CONSTANT_H #define WILLOW_INCLUDE_IR_CONSTANT_H -#include <utility> #include <willow/IR/Value.h> namespace willow { enum class ConstantKind { Int, //< Integer value with known bits - Undef, //< Known undef Poison, //< Known poison }; @@ -23,7 +21,6 @@ public: Constant(const Constant &) = delete; Constant &operator=(const Constant &) = delete; - bool isUndef() const { return kind == ConstantKind::Undef; } bool isPoison() const { return kind == ConstantKind::Poison; } bool isInt() const { return kind == ConstantKind::Int; } }; @@ -34,29 +31,9 @@ class ConstantInt final : public Constant { uint64_t bits = 0; public: - explicit ConstantInt(Type ty, uint64_t val) - : Constant(ty, ConstantKind::Int) { - const size_t w = ty.getNumBits(); - assert(w <= 64 && "Come back when im less lazy"); - // assert(!(val >> w) && "Truncated constant"); - - if (w == 64) - bits = val; - else { - const uint64_t m = (uint64_t{1} << w) - 1; - bits = val & m; - } - } - - int64_t getSExtVal() const { - const size_t w = getType().getNumBits(); - - if (w == 64) - return static_cast<int64_t>(bits); - - unsigned sh = 64 - w; - return (static_cast<int64_t>(bits << sh)) >> sh; - } + explicit ConstantInt(Type ty, uint64_t val); + + int64_t getSExtVal() const; uint64_t getZExtVal() const { return bits; } @@ -67,21 +44,10 @@ public: }; struct Hash { - size_t operator()(const ConstantInt::Key &k) const noexcept { - auto h1 = std::hash<TypeImpl *>{}(k.ty); - auto h2 = std::hash<uint64_t>{}(k.bits); - - return h1 ^ (h2 + 0x9e3779b97f4a7c15ULL + (h1 << 6) + (h1 >> 2)); - } + size_t operator()(const ConstantInt::Key &k) const noexcept; }; }; -/// Represents a constant value that is entirely undef. -class UndefVal final : public Constant { -public: - explicit UndefVal(Type ty) : Constant(ty, ConstantKind::Undef) {} -}; - /// Represents a constant value that is entirely poison. class PoisonVal final : public Constant { public: @@ -90,19 +56,6 @@ public: } // namespace willow -// TODO lol -inline std::ostream& operator<<(std::ostream &os, const willow::Constant& c) { - if (c.isPoison()) - return os << "poison"; - - if (c.isUndef()) - return os << "undef"; - - if (c.isInt()) { - return os << static_cast<const willow::ConstantInt*>(&c)->getSExtVal(); - } - - std::unreachable(); -} +std::ostream &operator<<(std::ostream &os, const willow::Constant &c); #endif // WILLOW_INCLUDE_IR_CONSTANT_H diff --git a/willow/include/willow/IR/ConstantPool.h b/willow/include/willow/IR/ConstantPool.h index 7d5347b..dd93997 100644 --- a/willow/include/willow/IR/ConstantPool.h +++ b/willow/include/willow/IR/ConstantPool.h @@ -1,8 +1,8 @@ #ifndef WILLOW_INCLUDE_IR_CONSTANT_POOL_H #define WILLOW_INCLUDE_IR_CONSTANT_POOL_H -#include <memory> #include <willow/IR/Constant.h> +#include <memory> namespace willow { @@ -14,8 +14,6 @@ public: /// Get a uniqued integer constant with the specified type and value. ConstantInt *getInt(Type ty, uint64_t val); - /// Get a uniqued undef value for the specified type \p ty. - UndefVal *getUndefVal(Type ty); /// Get a uniqued poison value for the specified type \p ty. PoisonVal *getPoisonVal(Type ty); @@ -25,41 +23,10 @@ private: ConstantInt::Hash> icache; - std::mutex undef_mutex; - std::unordered_map<TypeImpl *, std::unique_ptr<UndefVal>> ucache; - std::mutex poison_mutex; std::unordered_map<TypeImpl *, std::unique_ptr<PoisonVal>> pcache; }; -inline ConstantInt *ConstantPool::getInt(Type ty, uint64_t val) { - assert(ty.isInt() && "Expected integer type"); - ConstantInt::Key &&k{ty.getImpl(), ty.getNumBits()}; - std::lock_guard<std::mutex> lock(int_mutex); - - auto [it, _] = icache.try_emplace(k, std::make_unique<ConstantInt>(ty, val)); - - return it->second.get(); -} - -inline UndefVal *ConstantPool::getUndefVal(Type ty) { - std::lock_guard<std::mutex> lock(undef_mutex); - - auto [it, _] = - ucache.try_emplace(ty.getImpl(), std::make_unique<UndefVal>(ty)); - - return it->second.get(); -} - -inline PoisonVal *ConstantPool::getPoisonVal(Type ty) { - std::lock_guard<std::mutex> lock(poison_mutex); - - auto [it, _] = - pcache.try_emplace(ty.getImpl(), std::make_unique<PoisonVal>(ty)); - - return it->second.get(); -} - }; // namespace willow #endif // WILLOW_INCLUDE_IR_CONSTANT_POOL_H diff --git a/willow/include/willow/IR/Diagnostic.h b/willow/include/willow/IR/Diagnostic.h index 538704c..68483d9 100644 --- a/willow/include/willow/IR/Diagnostic.h +++ b/willow/include/willow/IR/Diagnostic.h @@ -5,6 +5,7 @@ #include <string> #include <vector> +#include <ostream> namespace willow { @@ -19,4 +20,6 @@ struct Diagnostic { } // namespace willow +std::ostream &operator<<(std::ostream &os, const willow::Diagnostic &diagnostic); + #endif // WILLOW_INCLUDE_IR_DIAGNOSTIC_H diff --git a/willow/include/willow/IR/DiagnosticEngine.h b/willow/include/willow/IR/DiagnosticEngine.h index a8735af..06dcc3c 100644 --- a/willow/include/willow/IR/DiagnosticEngine.h +++ b/willow/include/willow/IR/DiagnosticEngine.h @@ -21,11 +21,7 @@ public: explicit DiagnosticEngine(Handler h) : handler(std::move(h)) {} void setHandler(Handler h) { handler = std::move(h); } - - void report(Diagnostic d) { - if (handler) - handler(std::move(d)); - } + void report(Diagnostic d); private: Handler handler; @@ -42,23 +38,11 @@ public: DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; DiagnosticBuilder(DiagnosticEngine &eng, Severity severity, - std::optional<Location> loc) - : engine(&eng) { - diag.severity = severity; - diag.location = loc; - } + std::optional<Location> loc = std::nullopt); - DiagnosticBuilder(DiagnosticBuilder &&other) noexcept - : engine(std::exchange(other.engine, nullptr)), - diag(std::move(other.diag)), os(std::move(other.os)) {} + DiagnosticBuilder(DiagnosticBuilder &&other) noexcept; - ~DiagnosticBuilder() { - if (!engine) // was moved from - return; - - diag.message += os.str(); - engine->report(std::move(diag)); - } + ~DiagnosticBuilder(); template <typename T> DiagnosticBuilder &operator<<(T &&x) { diff --git a/willow/include/willow/IR/Function.h b/willow/include/willow/IR/Function.h index bd6ef3d..817abd2 100644 --- a/willow/include/willow/IR/Function.h +++ b/willow/include/willow/IR/Function.h @@ -8,7 +8,6 @@ #include <memory> #include <ranges> #include <string> -#include <string_view> #include <utility> #include <vector> @@ -83,32 +82,16 @@ public: std::size_t getNumParams() const { return params.size(); } - /// \return The SSA values that exist in this block. - auto getValues() { - return blocks | - std::views::transform([](auto &p) -> Value & { return *p; }); - } - auto getValues() const { - return blocks | - std::views::transform([](auto &p) -> const Value & { return *p; }); - } - /// Append an existing block, transferring ownership. /// \param block Basic block to append. /// \return Raw pointer to the appended block. - BasicBlock *addBlock(std::unique_ptr<BasicBlock> block) { - auto p = block.get(); - blocks.push_back(std::move(block)); - p->setParent(this); - return p; - } + BasicBlock *addBlock(std::unique_ptr<BasicBlock> block); /// Construct a new block in-place and append it. /// \return Raw pointer to the appended block. template <typename... Args> BasicBlock *createBlock(Args &&...args) { - blocks.push_back(std::make_unique<BasicBlock>(std::forward<Args>(args)...)); - return blocks.back().get(); + return addBlock(std::make_unique<BasicBlock>(std::forward<Args>(args)...)); } Type getReturnType() const { @@ -119,20 +102,6 @@ public: } }; -inline const BasicBlock *Function::entryBlock() const { - if (blocks.empty()) - return nullptr; - else - return blocks.front().get(); -} - -inline BasicBlock *Function::entryBlock() { - if (blocks.empty()) - return nullptr; - else - return blocks.front().get(); -} - } // namespace willow #endif // WILLOW_INCLUDE_IR_FUNCTION_H diff --git a/willow/include/willow/IR/IRBuilder.h b/willow/include/willow/IR/IRBuilder.h index f2f36f2..1c637a7 100644 --- a/willow/include/willow/IR/IRBuilder.h +++ b/willow/include/willow/IR/IRBuilder.h @@ -21,69 +21,75 @@ public: BasicBlock::Iterator insertion_point) : insert_point(insertion_point), ctx(ctx) {} - void SetInsertPoint(BasicBlock::Iterator point) { insert_point = point; } + void setInsertPoint(BasicBlock::Iterator point) { insert_point = point; } - AddInst *BuildAdd(Type type, Value *lhs, Value *rhs, + AddInst *buildAdd(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - MulInst *BuildMul(Type type, Value *lhs, Value *rhs, + MulInst *buildMul(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - SubInst *BuildSub(Type type, Value *lhs, Value *rhs, + SubInst *buildSub(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - DivInst *BuildDiv(Type type, Value *lhs, Value *rhs, + DivInst *buildDiv(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - ModInst *BuildMod(Type type, Value *lhs, Value *rhs, + ModInst *buildMod(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - ShlInst *BuildShl(Type type, Value *lhs, Value *rhs, + ShlInst *buildShl(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - ShrInst *BuildShr(Type type, Value *lhs, Value *rhs, + ShrInst *buildShr(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - AshlInst *BuildAshl(Type type, Value *lhs, Value *rhs, + AshlInst *buildAshl(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - AshrInst *BuildAshr(Type type, Value *lhs, Value *rhs, + AshrInst *buildAshr(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - EqInst *BuildEq(Value *lhs, Value *rhs, + EqInst *buildEq(Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - LtInst *BuildLt(Value *lhs, Value *rhs, + LtInst *buildLt(Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - GtInst *BuildGt(Value *lhs, Value *rhs, + GtInst *buildGt(Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - LeInst *BuildLe(Value *lhs, Value *rhs, + LeInst *buildLe(Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - GeInst *BuildGe(Value *lhs, Value *rhs, + GeInst *buildGe(Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - AndInst *BuildAnd(Value *lhs, Value *rhs, + AndInst *buildAnd(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - OrInst *BuildOr(Value *lhs, Value *rhs, + OrInst *buildOr(Type type, Value *lhs, Value *rhs, std::optional<Location> loc = std::nullopt); - NotInst *BuildNot(Value *val, std::optional<Location> loc = std::nullopt); + NotInst *buildNot(Type type, Value *val, + std::optional<Location> loc = std::nullopt); - JmpInst *BuildJmp(BasicBlock *dst, + JmpInst *buildJmp(BasicBlock *dst, std::optional<Location> loc = std::nullopt); - BrInst *BuildBr(Value *predicate, BasicBlock *truedst, BasicBlock *falsedst, + BrInst *buildBr(Value *predicate, BasicBlock *truedst, BasicBlock *falsedst, std::optional<Location> loc = std::nullopt); template <typename... Args> - CallInst *BuildCall(Type rty, Function *func, + CallInst *buildCall(Type rty, Function *func, std::optional<Location> loc = std::nullopt, - Args &&...args) { - auto *inst = new CallInst(rty, func, std::forward<Args>(args)...); - assert(inst); - insert_point->insertAfter(*inst); - insert_point++; + Args &&...args); - return inst; - } - RetInst *BuildRet(Value *val, std::optional<Location> loc = std::nullopt); - RetInst *BuildRet(std::optional<Location> loc = std::nullopt); + RetInst *buildRet(Value *val, std::optional<Location> loc = std::nullopt); + RetInst *buildRet(std::optional<Location> loc = std::nullopt); PhiInst * - BuildPhi(Type ty, + buildPhi(Type ty, std::initializer_list<std::pair<BasicBlock *, Value *>> args, std::optional<Location> loc = std::nullopt); - AllocaInst *BuildAlloca(Type ty, std::optional<Location> loc = std::nullopt); + AllocaInst *buildAlloca(Type ty, std::optional<Location> loc = std::nullopt); }; +template <typename... Args> +CallInst *IRBuilder::buildCall(Type rty, Function *func, + std::optional<Location> loc, Args &&...args) { + auto *inst = new CallInst(rty, func, std::forward<Args>(args)...); + assert(inst); + insert_point->insertAfter(*inst); + insert_point++; + + return inst; +} + } // namespace willow #endif // WILLOW_INCLUDE_IR_IR_BUILDER_H* diff --git a/willow/include/willow/IR/Instruction.h b/willow/include/willow/IR/Instruction.h index e02e308..34bf584 100644 --- a/willow/include/willow/IR/Instruction.h +++ b/willow/include/willow/IR/Instruction.h @@ -83,18 +83,7 @@ private: std::vector<Value *> operands; protected: - void setOperand(std::size_t index, Value *operand) { - assert(index < operands.size() && "Operand index out of bounds"); - assert(operand && "Operand cannot be null"); - Value *old = operands[index]; - if (old == operand) - return; - - old->delUse(this); - operands[index] = operand; - operand->addUse(this); - } - + void setOperand(std::size_t index, Value *operand); public: /// \param op Opcode for this instruction. /// \param type Type of the result of this instruction. diff --git a/willow/include/willow/IR/Instructions.h b/willow/include/willow/IR/Instructions.h index 753ea70..fd48b2c 100644 --- a/willow/include/willow/IR/Instructions.h +++ b/willow/include/willow/IR/Instructions.h @@ -11,10 +11,7 @@ namespace willow { class UnaryInst : public Instruction { public: UnaryInst(Opcode op, Type type, Value *value, - std::optional<Location> loc = std::nullopt) - : Instruction(op, type, loc) { - addOperand(value); - } + std::optional<Location> loc = std::nullopt); Value *getValue() { return getOperand(0); } const Value *getValue() const { return getOperand(0); } @@ -24,11 +21,7 @@ public: class BinaryInst : public Instruction { public: BinaryInst(Opcode op, Type type, Value *lhs, Value *rhs, - std::optional<Location> loc = std::nullopt) - : Instruction(op, type, loc) { - addOperand(lhs); - addOperand(rhs); - } + std::optional<Location> loc = std::nullopt); Value *getLHS() { return getOperand(0); } const Value *getLHS() const { return getOperand(0); } @@ -248,29 +241,14 @@ public: /// \p true_target. The basic block to jump to if the condition is true /// \p false_target. The basic block to jump to if the condition is false BrInst(Type type, Value *condition, BasicBlock *true_target, - BasicBlock *false_target, std::optional<Location> loc = std::nullopt) - : Instruction(Opcode::Br, type, loc) { - addOperand(condition); - addOperand(true_target); - addOperand(false_target); - } - - Value *getCondition() { return getOperand(0); } - const Value *getCondition() const { return getOperand(0); } - - BasicBlock *getTrueTarget() { - return static_cast<BasicBlock *>(getOperand(1)); - } - const BasicBlock *getTrueTarget() const { - return static_cast<const BasicBlock *>(getOperand(1)); - } - - BasicBlock *getFalseTarget() { - return static_cast<BasicBlock *>(getOperand(2)); - } - const BasicBlock *getFalseTarget() const { - return static_cast<const BasicBlock *>(getOperand(2)); - } + BasicBlock *false_target, std::optional<Location> loc = std::nullopt); + + Value *getCondition(); + const Value *getCondition() const; + BasicBlock *getTrueTarget(); + const BasicBlock *getTrueTarget() const; + BasicBlock *getFalseTarget(); + const BasicBlock *getFalseTarget() const; }; /// Call another function @@ -292,12 +270,8 @@ public: /// Return instruction class RetInst : public Instruction { public: - RetInst(Type voidty, std::optional<Location> loc) - : Instruction(Opcode::Ret, voidty, loc) {} - RetInst(Type voidty, Value *val, std::optional<Location> loc = std::nullopt) - : Instruction(Opcode::Ret, voidty, loc) { - addOperand(val); - } + RetInst(Type voidty, std::optional<Location> loc); + RetInst(Type voidty, Value *val, std::optional<Location> loc = std::nullopt); }; /// Select a control-flow variant value @@ -307,13 +281,7 @@ public: /// \p args List of (predecessor block, value to take) pairs PhiInst(Type type, std::initializer_list<std::pair<BasicBlock *, Value *>> args, - std::optional<Location> loc) - : Instruction(Opcode::Phi, type, loc) { - for (auto [bb, v] : args) { - addOperand(static_cast<Value *>(bb)); - addOperand(v); - } - } + std::optional<Location> loc = std::nullopt); auto incomings() { auto ops = std::span<Value *>{getOperands()}; diff --git a/willow/include/willow/IR/Value.h b/willow/include/willow/IR/Value.h index e252fa2..dc98373 100644 --- a/willow/include/willow/IR/Value.h +++ b/willow/include/willow/IR/Value.h @@ -3,9 +3,7 @@ #include <willow/IR/Types.h> -#include <cassert> #include <unordered_map> -#include <ostream> namespace willow { @@ -13,6 +11,8 @@ class Instruction; class BasicBlock; class Constant; +using UseList = std::unordered_map<Instruction *, std::size_t>; + enum class ValueKind { Instruction, ///< the identified result of an instruction Parameter, ///< the named parameter to a function @@ -43,27 +43,15 @@ public: /// Get the instructions that use this value, and the number of times they use /// it. - /// - /// \return map of Instruction* -> num uses - std::unordered_map<Instruction *, std::size_t> &getUses() { return uses; } - const std::unordered_map<Instruction *, std::size_t> &getUses() const { - return uses; - } - - void addUse(Instruction *i) { - auto [it, inserted] = uses.try_emplace(i, 1); - - if (!inserted) - it->second += 1; - } - - /// Remove a use of the instruction from te use list. - void delUse(Instruction *instruction) { - assert(uses.contains(instruction) && "No uses to remove"); - auto it = uses.find(instruction); - it->second -= 1; - if (it->second == 0) - uses.erase(it); + UseList &getUses() { return uses; } + const UseList &getUses() const { return uses; } + + /// Add the instruction \p i as a user of this value + void addUse(Instruction *instruction); + /// Remove the instruction \p i as a user of this value + void delUse(Instruction *instruction); + bool hasUse(Instruction *instruction) const { + return uses.contains(instruction); } }; |