From 88fd18adb7d11e9806851fe3627dbacc6aba2482 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Wed, 20 May 2026 19:09:55 -0500 Subject: [PATCH 01/12] rewrite the easy stuff in middleend --- src/middleend/mir/instruction.cpp | 45 ++++++++++++++-------------- src/middleend/mir/instruction.h | 28 ++++++++--------- src/middleend/mir/mir.cpp | 14 +++++---- src/middleend/mir/mir.h | 18 ++++++----- src/middleend/mir/operator.cpp | 35 ++++++++++++++++++++-- src/middleend/mir/operator.h | 27 ++++------------- src/middleend/mir/type.cpp | 21 +++++++++++-- src/middleend/mir/type.h | 14 ++------- src/middleend/mir/value.cpp | 2 ++ src/middleend/mir/value.h | 7 +++-- src/middleend/pass.cpp | 2 ++ src/middleend/pass.h | 2 ++ src/middleend/pass_manager.cpp | 8 +++-- src/middleend/pass_manager.h | 2 ++ src/middleend/utils/erase_uses.cpp | 9 ++++-- src/middleend/utils/erase_uses.h | 5 ++-- src/middleend/utils/replace_uses.cpp | 10 ++++--- src/middleend/utils/replace_uses.h | 5 ++-- src/middleend/utils/traversal.cpp | 17 ++++++----- src/middleend/utils/traversal.h | 2 ++ 20 files changed, 161 insertions(+), 112 deletions(-) diff --git a/src/middleend/mir/instruction.cpp b/src/middleend/mir/instruction.cpp index 388a415b..b69c0b94 100644 --- a/src/middleend/mir/instruction.cpp +++ b/src/middleend/mir/instruction.cpp @@ -3,6 +3,7 @@ #include "middleend/mir/value.h" namespace middleend::mir { + void Instruction::addUse(Value *def) { def->getUses()[this]++; } void Instruction::delUse(Value *def) { @@ -40,8 +41,8 @@ void InstructionBinaryOp::accept(InstructionVisitor *v) { v->visit(this); } InstructionCall::InstructionCall(Type type, Function *callee, std::vector arguments) - : Value(type), callee(callee), arguments(arguments) { - for (auto val : arguments) + : Value(type), callee(callee), args(arguments) { + for (auto *val : arguments) addUse(val); } @@ -49,14 +50,14 @@ Function *InstructionCall::getCallee() { return callee; } void InstructionCall::setCallee(Function *new_val) { callee = new_val; } -std::vector &InstructionCall::getArguments() { return arguments; } +std::vector &InstructionCall::getArguments() { return args; } void InstructionCall::accept(InstructionVisitor *v) { v->visit(this); } InstructionAlloca::InstructionAlloca(Type allocType) - : Value(Type::PTR), allocType(allocType) {} + : Value(Type::PTR), alloc_type(allocType) {} -Type InstructionAlloca::getAllocType() { return allocType; } +Type InstructionAlloca::getAllocType() { return alloc_type; } void InstructionAlloca::accept(InstructionVisitor *v) { v->visit(this); } @@ -76,19 +77,19 @@ void InstructionLoad::setPtr(Value *new_val) { void InstructionLoad::accept(InstructionVisitor *v) { v->visit(this); } InstructionStore::InstructionStore(Value *value, Value *ptr) - : value(value), ptr(ptr) { + : val(value), ptr(ptr) { addUse(value); addUse(ptr); } -Value *InstructionStore::getValue() { return value; } +Value *InstructionStore::getValue() { return val; } Value *InstructionStore::getPtr() { return ptr; } void InstructionStore::setValue(Value *new_val) { - delUse(value); + delUse(val); addUse(new_val); - value = new_val; + val = new_val; } void InstructionStore::setPtr(Value *new_val) { @@ -131,16 +132,14 @@ void InstructionParallelCopy::setCopy(InstructionPhi *phi_val, void InstructionParallelCopy::accept(InstructionVisitor *v) { v->visit(this); } -TerminatorReturn::TerminatorReturn(Value *value) : value(value) { - addUse(value); -} +TerminatorReturn::TerminatorReturn(Value *value) : val(value) { addUse(value); } -Value *TerminatorReturn::getValue() { return value; } +Value *TerminatorReturn::getValue() { return val; } void TerminatorReturn::setValue(Value *new_val) { - delUse(value); + delUse(val); addUse(new_val); - value = new_val; + val = new_val; } void TerminatorReturn::accept(InstructionVisitor *v) { v->visit(this); } @@ -150,16 +149,15 @@ TerminatorBranch::TerminatorBranch(BasicBlock *successor) BasicBlock *TerminatorBranch::getSuccessor() { return successor; } -void TerminatorBranch::setSuccessor(BasicBlock *successor) { - this->successor = successor; +void TerminatorBranch::setSuccessor(BasicBlock *new_succ) { + successor = new_succ; } void TerminatorBranch::accept(InstructionVisitor *v) { v->visit(this); } TerminatorCondBranch::TerminatorCondBranch(Value *cond, BasicBlock *t_successor, BasicBlock *f_successor) - : t_successor(t_successor), f_successor(f_successor) { - this->cond = cond; + : t_successor(t_successor), f_successor(f_successor), cond(cond) { addUse(cond); } @@ -175,13 +173,14 @@ void TerminatorCondBranch::setCond(Value *new_val) { this->cond = new_val; } -void TerminatorCondBranch::setTSuccessor(BasicBlock *t_successor) { - this->t_successor = t_successor; +void TerminatorCondBranch::setTSuccessor(BasicBlock *new_succ) { + t_successor = new_succ; } -void TerminatorCondBranch::setFSuccessor(BasicBlock *f_successor) { - this->f_successor = f_successor; +void TerminatorCondBranch::setFSuccessor(BasicBlock *new_succ) { + f_successor = new_succ; } void TerminatorCondBranch::accept(InstructionVisitor *v) { v->visit(this); } + } // namespace middleend::mir diff --git a/src/middleend/mir/instruction.h b/src/middleend/mir/instruction.h index 755b1905..f7c1964d 100644 --- a/src/middleend/mir/instruction.h +++ b/src/middleend/mir/instruction.h @@ -1,10 +1,10 @@ #pragma once -#include - #include "middleend/mir/operator.h" #include "middleend/mir/value.h" +#include + namespace middleend::mir { class InstructionVisitor; @@ -37,8 +37,7 @@ class InstructionBinaryOp : public Instruction, public Value { class InstructionCall : public Instruction, public Value { public: - InstructionCall(Type type, Function *callee, - std::vector arguments); + InstructionCall(Type type, Function *callee, std::vector args); Function *getCallee(); void setCallee(Function *new_val); std::vector &getArguments(); @@ -46,17 +45,17 @@ class InstructionCall : public Instruction, public Value { private: Function *callee; - std::vector arguments; + std::vector args; }; class InstructionAlloca : public Instruction, public Value { public: - InstructionAlloca(Type allocType); + InstructionAlloca(Type alloc_type); Type getAllocType(); void accept(InstructionVisitor *v) override; private: - Type allocType; + Type alloc_type; }; class InstructionLoad : public Instruction, public Value { @@ -72,7 +71,7 @@ class InstructionLoad : public Instruction, public Value { class InstructionStore : public Instruction { public: - InstructionStore(Value *value, Value *ptr); + InstructionStore(Value *val, Value *ptr); Value *getValue(); Value *getPtr(); void setValue(Value *new_val); @@ -80,7 +79,7 @@ class InstructionStore : public Instruction { void accept(InstructionVisitor *v) override; private: - Value *value; + Value *val; Value *ptr; }; @@ -113,20 +112,20 @@ class Terminator : public Instruction { class TerminatorReturn : public Terminator { public: - TerminatorReturn(Value *value); + TerminatorReturn(Value *val); Value *getValue(); void setValue(Value *new_val); void accept(InstructionVisitor *v) override; private: - Value *value; + Value *val; }; class TerminatorBranch : public Terminator { public: TerminatorBranch(BasicBlock *successor); BasicBlock *getSuccessor(); - void setSuccessor(BasicBlock *successor); + void setSuccessor(BasicBlock *new_succ); void accept(InstructionVisitor *v) override; private: @@ -141,8 +140,8 @@ class TerminatorCondBranch : public Terminator { BasicBlock *getTSuccessor(); BasicBlock *getFSuccessor(); void setCond(Value *new_val); - void setTSuccessor(BasicBlock *t_successor); - void setFSuccessor(BasicBlock *f_successor); + void setTSuccessor(BasicBlock *new_succ); + void setFSuccessor(BasicBlock *new_succ); void accept(InstructionVisitor *v) override; private: @@ -165,4 +164,5 @@ class InstructionVisitor { virtual void visit(TerminatorBranch *t) = 0; virtual void visit(TerminatorCondBranch *t) = 0; }; + } // namespace middleend::mir diff --git a/src/middleend/mir/mir.cpp b/src/middleend/mir/mir.cpp index e3418659..9e08d454 100644 --- a/src/middleend/mir/mir.cpp +++ b/src/middleend/mir/mir.cpp @@ -1,12 +1,13 @@ -#include - +#include "middleend/mir/mir.h" #include "middleend/analysis/number_ir.h" #include "middleend/mir/instruction.h" -#include "middleend/mir/mir.h" #include "middleend/mir/type.h" #include "middleend/mir/value.h" +#include + namespace middleend::mir { + BasicBlockEdges::BasicBlockEdges() : size(0) {} const std::vector BasicBlockEdges::getEdges() { @@ -46,7 +47,7 @@ std::list> &BasicBlock::getInstructions() { return body; } -std::unique_ptr &BasicBlock::getTerminator() { return terminator; } +Terminator *BasicBlock::getTerminator() { return terminator.get(); } BasicBlockEdges &BasicBlock::getPredecessors() { return predecessors; } @@ -160,7 +161,7 @@ Literal *Program::getLiteral(Type type, uint64_t value) { return typed_map.at(value).get(); auto literal = std::make_unique(type, value); - auto literal_ptr = literal.get(); + auto *literal_ptr = literal.get(); typed_map[value] = std::move(literal); return literal_ptr; @@ -268,7 +269,7 @@ void ToStringVisitor::visit(InstructionParallelCopy *i) { return nir->getNumber(a) < nir->getNumber(b); }; - auto pairs = i->getCopies(); + auto &pairs = i->getCopies(); std::map ordered(pairs.begin(), pairs.end(), comp); @@ -299,4 +300,5 @@ void ToStringVisitor::visit(TerminatorCondBranch *t) { std::string bb_false = std::to_string(nir->getNumber(t->getFSuccessor())); result = "br " + cond + ", label " + bb_true + ", label " + bb_false; } + } // namespace middleend::mir diff --git a/src/middleend/mir/mir.h b/src/middleend/mir/mir.h index 724c5447..651c90c1 100644 --- a/src/middleend/mir/mir.h +++ b/src/middleend/mir/mir.h @@ -1,18 +1,19 @@ #pragma once +#include "middleend/mir/instruction.h" +#include "middleend/mir/type.h" + #include #include #include #include -#include "middleend/mir/instruction.h" -#include "middleend/mir/type.h" - namespace middleend { + class NumberIR; -} -namespace middleend::mir { +namespace mir { + using LiteralMap = std::unordered_map>>; @@ -36,7 +37,7 @@ class BasicBlock { BasicBlock(std::list> body, std::unique_ptr terminator); std::list> &getInstructions(); - std::unique_ptr &getTerminator(); + Terminator *getTerminator(); BasicBlockEdges &getPredecessors(); BasicBlockEdges &getSuccessors(); std::string toString(NumberIR *nir); @@ -130,4 +131,7 @@ class ToStringVisitor : public InstructionVisitor { std::string result; NumberIR *nir; }; -} // namespace middleend::mir + +} // namespace mir + +} // namespace middleend diff --git a/src/middleend/mir/operator.cpp b/src/middleend/mir/operator.cpp index c012e9f9..bc3231ea 100644 --- a/src/middleend/mir/operator.cpp +++ b/src/middleend/mir/operator.cpp @@ -1,8 +1,28 @@ -#include - #include "middleend/mir/operator.h" +#include +#include + namespace middleend::mir { + +BinaryOp strToBinaryOp(std::string str) { + static const std::unordered_map fromStr = { + // clang-format off + {"add", BinaryOp::ADD}, + {"sub", BinaryOp::SUB}, + {"mul", BinaryOp::MUL}, + {"sdiv", BinaryOp::SDIV}, + {"and", BinaryOp::AND}, + {"or", BinaryOp::OR}, + {"xor", BinaryOp::XOR}, + {"shl", BinaryOp::SHL}, + {"ashr", BinaryOp::ASHR}, + // clang-format on + }; + + return fromStr.at(str); +} + std::string toString(BinaryOp op) { switch (op) { case BinaryOp::ADD: @@ -27,6 +47,16 @@ std::string toString(BinaryOp op) { std::unreachable(); } +CmpOp strToCmpOp(std::string str) { + static const std::unordered_map fromStr = { + // clang-format off + {"sgt", CmpOp::SGT}, + // clang-format on + }; + + return fromStr.at(str); +} + std::string toString(CmpOp op) { switch (op) { case CmpOp::SGT: @@ -34,4 +64,5 @@ std::string toString(CmpOp op) { } std::unreachable(); } + } // namespace middleend::mir diff --git a/src/middleend/mir/operator.h b/src/middleend/mir/operator.h index 68e1a16c..08c16288 100644 --- a/src/middleend/mir/operator.h +++ b/src/middleend/mir/operator.h @@ -1,9 +1,9 @@ #pragma once #include -#include namespace middleend::mir { + enum class BinaryOp { ADD, SUB, @@ -16,29 +16,14 @@ enum class BinaryOp { ASHR, }; +BinaryOp strToBinaryOp(std::string str); +std::string toString(BinaryOp op); + enum class CmpOp { SGT, }; -// clang-format off - const std::unordered_map strToBinaryOp = { - {"add", BinaryOp::ADD}, - {"sub", BinaryOp::SUB}, - {"mul", BinaryOp::MUL}, - {"sdiv", BinaryOp::SDIV}, - {"and", BinaryOp::AND}, - {"or", BinaryOp::OR}, - {"xor", BinaryOp::XOR}, - {"shl", BinaryOp::SHL}, - {"ashr", BinaryOp::ASHR}, - }; -// clang-format on - -const std::unordered_map strToCmpOp = { - {"sgt", CmpOp::SGT}, -}; - -std::string toString(BinaryOp op); - +CmpOp strToCmpOp(std::string str); std::string toString(CmpOp op); + } // namespace middleend::mir diff --git a/src/middleend/mir/type.cpp b/src/middleend/mir/type.cpp index a74e501b..d64a0bfa 100644 --- a/src/middleend/mir/type.cpp +++ b/src/middleend/mir/type.cpp @@ -1,8 +1,24 @@ -#include - #include "middleend/mir/type.h" +#include +#include + namespace middleend::mir { + +Type strToType(std::string str) { + static const std::unordered_map fromStr = { + // clang-format off + {"i1", Type::I1}, + {"i16", Type::I16}, + {"i32", Type::I32}, + {"i64", Type::I64}, + {"ptr", Type::PTR}, + // clang-format on + }; + + return fromStr.at(str); +} + std::string toString(Type type) { switch (type) { case Type::I1: @@ -18,4 +34,5 @@ std::string toString(Type type) { } std::unreachable(); } + } // namespace middleend::mir diff --git a/src/middleend/mir/type.h b/src/middleend/mir/type.h index 123f9b7a..5a57e852 100644 --- a/src/middleend/mir/type.h +++ b/src/middleend/mir/type.h @@ -1,9 +1,9 @@ #pragma once #include -#include namespace middleend::mir { + enum class Type { I1, I16, @@ -12,15 +12,7 @@ enum class Type { PTR, }; -// clang-format off - const std::unordered_map strToType = { - {"i1", Type::I1}, - {"i16", Type::I16}, - {"i32", Type::I32}, - {"i64", Type::I64}, - {"ptr", Type::PTR}, - }; -// clang-format on - +Type strToType(std::string str); std::string toString(Type type); + } // namespace middleend::mir diff --git a/src/middleend/mir/value.cpp b/src/middleend/mir/value.cpp index fb87e06e..bb8a8506 100644 --- a/src/middleend/mir/value.cpp +++ b/src/middleend/mir/value.cpp @@ -2,6 +2,7 @@ #include "middleend/mir/type.h" namespace middleend::mir { + Value::Value(Type type) : type(type) {} Type Value::getType() { return type; } @@ -11,4 +12,5 @@ std::unordered_map &Value::getUses() { return uses; } Literal::Literal(Type type, int64_t value) : Value(type), value(value) {} int64_t Literal::getValue() { return value; } + } // namespace middleend::mir diff --git a/src/middleend/mir/value.h b/src/middleend/mir/value.h index 37c874f2..56694556 100644 --- a/src/middleend/mir/value.h +++ b/src/middleend/mir/value.h @@ -1,10 +1,12 @@ #pragma once -#include - #include "middleend/mir/type.h" +#include +#include + namespace middleend::mir { + class Instruction; // TODO: function params @@ -28,4 +30,5 @@ class Literal : public Value { private: int64_t value; }; + } // namespace middleend::mir diff --git a/src/middleend/pass.cpp b/src/middleend/pass.cpp index 7ab33a9a..7863748f 100644 --- a/src/middleend/pass.cpp +++ b/src/middleend/pass.cpp @@ -1,6 +1,7 @@ #include "middleend/pass.h" namespace middleend { + void AnalysisPass::invalidate() { valid = false; } void AnalysisPass::rerunIfInvalid(mir::Program &p) { @@ -15,4 +16,5 @@ void TransformPass::registerAnalyses( const std::vector &TransformPass::getAnalyses() { return required_analyses; } + } // namespace middleend diff --git a/src/middleend/pass.h b/src/middleend/pass.h index 4303355e..91b3dece 100644 --- a/src/middleend/pass.h +++ b/src/middleend/pass.h @@ -3,6 +3,7 @@ #include "middleend/mir/mir.h" namespace middleend { + class Pass { public: virtual void run(mir::Program &p) = 0; @@ -31,4 +32,5 @@ class TransformPass : public Pass { protected: std::vector required_analyses; }; + } // namespace middleend diff --git a/src/middleend/pass_manager.cpp b/src/middleend/pass_manager.cpp index f089ae6e..ae050dee 100644 --- a/src/middleend/pass_manager.cpp +++ b/src/middleend/pass_manager.cpp @@ -1,5 +1,3 @@ -#include - #include "middleend/pass_manager.h" #include "middleend/transform/insert_parallel_copies.h" #include "middleend/transform/inst_combine.h" @@ -7,7 +5,10 @@ #include "middleend/transform/simplify_cfg.h" #include "middleend/transform/split_critical.h" +#include + namespace middleend { + void PassManager::addPass(std::unique_ptr p) { p->registerAnalyses(analyses); passes.push_back(std::move(p)); @@ -41,10 +42,11 @@ std::unique_ptr initializeO0() { } std::unique_ptr initializeO1() { - auto pm = std::make_unique(); + auto pm = initializeO0(); pm->addPass(std::make_unique()); pm->addPass(std::make_unique()); pm->addPass(std::make_unique()); return pm; } + } // namespace middleend diff --git a/src/middleend/pass_manager.h b/src/middleend/pass_manager.h index 79b6af6f..5038aacc 100644 --- a/src/middleend/pass_manager.h +++ b/src/middleend/pass_manager.h @@ -4,6 +4,7 @@ #include "middleend/pass.h" namespace middleend { + class PassManager { public: void addPass(std::unique_ptr p); @@ -17,4 +18,5 @@ class PassManager { std::unique_ptr initializeO0(); std::unique_ptr initializeO1(); + } // namespace middleend diff --git a/src/middleend/utils/erase_uses.cpp b/src/middleend/utils/erase_uses.cpp index f1192ffd..c153030d 100644 --- a/src/middleend/utils/erase_uses.cpp +++ b/src/middleend/utils/erase_uses.cpp @@ -1,13 +1,14 @@ #include "middleend/utils/erase_uses.h" namespace middleend { + void EraseUsesVisitor::visit(mir::InstructionBinaryOp *i) { i->delUse(i->getLeft()); i->delUse(i->getRight()); } void EraseUsesVisitor::visit(mir::InstructionCall *i) { - for (auto val : i->getArguments()) + for (auto *val : i->getArguments()) i->delUse(val); } @@ -23,12 +24,12 @@ void EraseUsesVisitor::visit(mir::InstructionStore *i) { } void EraseUsesVisitor::visit(mir::InstructionPhi *i) { - for (auto [_, val] : i->getPredecessors()) + for (auto &[_, val] : i->getPredecessors()) i->delUse(val); } void EraseUsesVisitor::visit(mir::InstructionParallelCopy *i) { - for (auto [phi_val, copy_val] : i->getCopies()) { + for (auto &[phi_val, copy_val] : i->getCopies()) { i->delUse(phi_val); i->delUse(copy_val); } @@ -39,7 +40,9 @@ void EraseUsesVisitor::visit(mir::TerminatorReturn *t) { } void EraseUsesVisitor::visit(mir::TerminatorBranch *t) {} + void EraseUsesVisitor::visit(mir::TerminatorCondBranch *t) { t->delUse(t->getCond()); } + } // namespace middleend diff --git a/src/middleend/utils/erase_uses.h b/src/middleend/utils/erase_uses.h index 7f81d060..43432705 100644 --- a/src/middleend/utils/erase_uses.h +++ b/src/middleend/utils/erase_uses.h @@ -3,9 +3,7 @@ #include "middleend/mir/instruction.h" namespace middleend { -// -// Erase visited instruction from the uses lists of its uses -// + class EraseUsesVisitor : public mir::InstructionVisitor { public: EraseUsesVisitor() = default; @@ -22,4 +20,5 @@ class EraseUsesVisitor : public mir::InstructionVisitor { void visit(mir::TerminatorBranch *t) override; void visit(mir::TerminatorCondBranch *t) override; }; + } // namespace middleend diff --git a/src/middleend/utils/replace_uses.cpp b/src/middleend/utils/replace_uses.cpp index 195bd591..b282805f 100644 --- a/src/middleend/utils/replace_uses.cpp +++ b/src/middleend/utils/replace_uses.cpp @@ -1,8 +1,9 @@ -#include - #include "middleend/utils/replace_uses.h" +#include + namespace middleend { + ReplaceUsesVisitor::ReplaceUsesVisitor(mir::Value *old_value, mir::Value *new_value) : old_value(old_value), new_value(new_value) {} @@ -17,7 +18,7 @@ void ReplaceUsesVisitor::visit(mir::InstructionBinaryOp *i) { void ReplaceUsesVisitor::visit(mir::InstructionCall *i) { auto &args = i->getArguments(); for (auto iter = args.begin(); iter != args.end(); iter++) { - auto val = *iter; + auto *val = *iter; if (val == old_value) { i->delUse(val); i->addUse(new_value); @@ -49,7 +50,7 @@ void ReplaceUsesVisitor::visit(mir::InstructionPhi *i) { } void ReplaceUsesVisitor::visit(mir::InstructionParallelCopy *i) { - for (auto [phi_val, copy_val] : i->getCopies()) { + for (auto &[phi_val, copy_val] : i->getCopies()) { if (phi_val == old_value) { // TODO: do this in a way that doesnt invalidate the iterator std::unreachable(); @@ -71,4 +72,5 @@ void ReplaceUsesVisitor::visit(mir::TerminatorCondBranch *t) { if (t->getCond() == old_value) t->setCond(new_value); } + } // namespace middleend diff --git a/src/middleend/utils/replace_uses.h b/src/middleend/utils/replace_uses.h index 4eebfac5..e6db773d 100644 --- a/src/middleend/utils/replace_uses.h +++ b/src/middleend/utils/replace_uses.h @@ -3,9 +3,7 @@ #include "middleend/mir/instruction.h" namespace middleend { -// -// Replace all uses of old_value with new_value in visited instruction -// + class ReplaceUsesVisitor : public mir::InstructionVisitor { public: ReplaceUsesVisitor(mir::Value *old_value, mir::Value *new_value); @@ -26,4 +24,5 @@ class ReplaceUsesVisitor : public mir::InstructionVisitor { mir::Value *old_value; mir::Value *new_value; }; + } // namespace middleend diff --git a/src/middleend/utils/traversal.cpp b/src/middleend/utils/traversal.cpp index 7d81a3d8..05f0ca62 100644 --- a/src/middleend/utils/traversal.cpp +++ b/src/middleend/utils/traversal.cpp @@ -1,12 +1,13 @@ +#include "middleend/utils/traversal.h" +#include "middleend/analysis/number_ir.h" +#include "middleend/mir/mir.h" + #include #include #include -#include "middleend/analysis/number_ir.h" -#include "middleend/mir/mir.h" -#include "middleend/utils/traversal.h" - namespace middleend { + std::list traversePreorder(mir::FunctionDefinition *f) { // TODO: implement std::list traversal_order; @@ -16,7 +17,7 @@ std::list traversePreorder(mir::FunctionDefinition *f) { void recursePostorder(mir::BasicBlock *bb, std::list &to, TraversalOrderMap &tn, uint64_t &counter) { tn[bb]; // Prevent loops - for (auto succ : bb->getSuccessors().getUniqueEdges()) + for (auto *succ : bb->getSuccessors().getUniqueEdges()) if (!tn.contains(succ)) recursePostorder(succ, to, tn, counter); tn[bb] = counter++; @@ -51,12 +52,12 @@ std::list traverseTraces(mir::FunctionDefinition *f) { std::list traversal_order; - auto entry = f->getEntryBlock(); + auto *entry = f->getEntryBlock(); std::unordered_set visited = {}; std::deque worklist = {entry}; while (!worklist.empty()) { - auto cur = worklist.front(); + auto *cur = worklist.front(); worklist.pop_front(); if (visited.contains(cur)) @@ -75,7 +76,7 @@ std::list traverseTraces(mir::FunctionDefinition *f) { }; std::ranges::sort(successors, cmp); std::ranges::reverse_view reverse_edges{successors}; - for (auto succ : reverse_edges) { + for (auto &succ : reverse_edges) { if (visited.contains(succ)) continue; diff --git a/src/middleend/utils/traversal.h b/src/middleend/utils/traversal.h index e777e2f4..743c0525 100644 --- a/src/middleend/utils/traversal.h +++ b/src/middleend/utils/traversal.h @@ -3,6 +3,7 @@ #include "middleend/mir/mir.h" namespace middleend { + using TraversalOrderMap = std::unordered_map; // TODO: make iterators @@ -14,4 +15,5 @@ std::list numberPostorder(mir::FunctionDefinition *f, std::list traversePostorder(mir::FunctionDefinition *f); std::list traverseTraces(mir::FunctionDefinition *f); + } // namespace middleend From d0730e323e26306c1f250ec00290e32972e3cc7d Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Wed, 20 May 2026 19:20:33 -0500 Subject: [PATCH 02/12] rewrite analyses --- src/middleend/analysis/dominator_tree.cpp | 93 ++++++++++++----------- src/middleend/analysis/dominator_tree.h | 4 + src/middleend/analysis/number_ir.cpp | 10 ++- src/middleend/analysis/number_ir.h | 3 + 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/middleend/analysis/dominator_tree.cpp b/src/middleend/analysis/dominator_tree.cpp index eea2ff8e..143d1e6b 100644 --- a/src/middleend/analysis/dominator_tree.cpp +++ b/src/middleend/analysis/dominator_tree.cpp @@ -1,57 +1,59 @@ -#include - #include "middleend/analysis/dominator_tree.h" #include "middleend/utils/traversal.h" +#include + namespace middleend { void DominatorTree::run(mir::Program &p) { - for (auto &f : p.getFunctions()) { - auto definition = dynamic_cast(f.get()); - if (!definition) - continue; - - TraversalOrderMap traversal_numbers; - auto traversal_order = numberPostorder(definition, traversal_numbers); - std::ranges::reverse_view reverse_traversal_order{traversal_order}; - - auto findLCA = [&](mir::BasicBlock *b1, mir::BasicBlock *b2) { - while (b1 != b2) { - if (traversal_numbers[b1] < traversal_numbers[b2]) - b1 = immediate_dominators[b1]; - else - b2 = immediate_dominators[b2]; - } - return b1; - }; - - auto entry = definition->getEntryBlock(); - immediate_dominators[entry] = entry; - - bool changed = true; - while (changed) { - changed = false; - for (auto &bb : reverse_traversal_order) { - if (bb == entry) - continue; - - mir::BasicBlock *idom = nullptr; - for (auto pred : bb->getPredecessors().getEdges()) { - if (immediate_dominators.contains(pred)) - idom = idom ? findLCA(idom, pred) : pred; - } - - if (idom && idom != immediate_dominators[bb]) { - immediate_dominators[bb] = idom; - changed = true; - } - } + for (auto &f : p.getFunctions()) + run(f.get()); +} + +void DominatorTree::run(mir::Function *f) { + auto *definition = dynamic_cast(f); + if (!definition) + return; + + TraversalOrderMap traversal_numbers; + auto traversal_order = numberPostorder(definition, traversal_numbers); + std::ranges::reverse_view reverse_traversal_order{traversal_order}; + + auto findLCA = [&](mir::BasicBlock *b1, mir::BasicBlock *b2) { + while (b1 != b2) { + if (traversal_numbers[b1] < traversal_numbers[b2]) + b1 = immediate_dominators[b1]; + else + b2 = immediate_dominators[b2]; } + return b1; + }; + + auto *entry = definition->getEntryBlock(); + immediate_dominators[entry] = entry; + + bool changed = true; + while (changed) { + changed = false; + for (auto &bb : reverse_traversal_order) { + if (bb == entry) + continue; + + mir::BasicBlock *idom = nullptr; + for (auto *pred : bb->getPredecessors().getEdges()) + if (immediate_dominators.contains(pred)) + idom = idom ? findLCA(idom, pred) : pred; - for (auto pair : immediate_dominators) { - immediate_dominated[pair.second].push_back(pair.first); + if (idom && idom != immediate_dominators[bb]) { + immediate_dominators[bb] = idom; + changed = true; + } } } + + for (auto &[dominator, dominated] : immediate_dominators) { + immediate_dominated[dominated].push_back(dominator); + } } // TODO: replace bracket operator with nullptr return @@ -59,7 +61,7 @@ bool DominatorTree::dominates(mir::BasicBlock *bb1, mir::BasicBlock *bb2) { if (immediate_dominators[bb1] == bb1) return true; - auto cur = bb2; + auto *cur = bb2; while (cur != immediate_dominators[cur]) { if (cur == bb1) return true; @@ -76,4 +78,5 @@ const std::vector & DominatorTree::getDominees(mir::BasicBlock *bb) { return immediate_dominated[bb]; } + } // namespace middleend diff --git a/src/middleend/analysis/dominator_tree.h b/src/middleend/analysis/dominator_tree.h index fcf69e12..92d1435d 100644 --- a/src/middleend/analysis/dominator_tree.h +++ b/src/middleend/analysis/dominator_tree.h @@ -3,9 +3,12 @@ #include "middleend/pass.h" namespace middleend { + class DominatorTree : public AnalysisPass { public: void run(mir::Program &p) override; + void run(mir::Function *f); + bool dominates(mir::BasicBlock *bb1, mir::BasicBlock *bb2); mir::BasicBlock *getImmediateDominator(mir::BasicBlock *bb); const std::vector &getDominees(mir::BasicBlock *bb); @@ -16,4 +19,5 @@ class DominatorTree : public AnalysisPass { std::unordered_map> immediate_dominated; }; + } // namespace middleend diff --git a/src/middleend/analysis/number_ir.cpp b/src/middleend/analysis/number_ir.cpp index 61ad5b42..4bca151b 100644 --- a/src/middleend/analysis/number_ir.cpp +++ b/src/middleend/analysis/number_ir.cpp @@ -1,13 +1,14 @@ #include "middleend/analysis/number_ir.h" namespace middleend { + void NumberIR::run(mir::Program &p) { for (auto &f : p.getFunctions()) run(f.get()); } void NumberIR::run(mir::Function *f) { - auto definition = dynamic_cast(f); + auto *definition = dynamic_cast(f); if (!definition) return; @@ -16,17 +17,17 @@ void NumberIR::run(mir::Function *f) { for (auto ¶m : definition->getParameters()) value_ids[param.get()] = counter++; - auto entry = definition->getEntryBlock(); + auto *entry = definition->getEntryBlock(); for (auto &bb : definition->getBasicBlocks()) { basic_block_ids[bb.get()] = bb.get() == entry ? -1 : counter++; for (auto &i : bb->getInstructions()) { - auto v = dynamic_cast(i.get()); + auto *v = dynamic_cast(i.get()); if (v) value_ids[v] = counter++; } - auto t = dynamic_cast(bb->getTerminator().get()); + auto *t = dynamic_cast(bb->getTerminator()); if (t) value_ids[t] = counter++; } @@ -43,4 +44,5 @@ uint64_t NumberIR::getNumber(mir::Value *i) { // that's always going to be mapped to a basic block so who cares return -1; } + } // namespace middleend diff --git a/src/middleend/analysis/number_ir.h b/src/middleend/analysis/number_ir.h index 7e11cff6..72f31b39 100644 --- a/src/middleend/analysis/number_ir.h +++ b/src/middleend/analysis/number_ir.h @@ -3,10 +3,12 @@ #include "middleend/pass.h" namespace middleend { + class NumberIR : public AnalysisPass { public: void run(mir::Program &p) override; void run(mir::Function *f); + uint64_t getNumber(mir::BasicBlock *bb); uint64_t getNumber(mir::Value *i); @@ -14,4 +16,5 @@ class NumberIR : public AnalysisPass { std::unordered_map basic_block_ids; std::unordered_map value_ids; }; + } // namespace middleend From 023fb97318d993d4f9b39b95def3809704966568 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Wed, 27 May 2026 18:28:07 -0500 Subject: [PATCH 03/12] readd functionality in mir (terminator replacement) --- src/middleend/mir/instruction.cpp | 13 +++++++++++++ src/middleend/mir/instruction.h | 5 +++++ src/middleend/mir/mir.cpp | 4 ++++ src/middleend/mir/mir.h | 1 + 4 files changed, 23 insertions(+) diff --git a/src/middleend/mir/instruction.cpp b/src/middleend/mir/instruction.cpp index b69c0b94..4ce87147 100644 --- a/src/middleend/mir/instruction.cpp +++ b/src/middleend/mir/instruction.cpp @@ -142,6 +142,10 @@ void TerminatorReturn::setValue(Value *new_val) { val = new_val; } +std::unique_ptr TerminatorReturn::clone() { + return std::make_unique(val); +} + void TerminatorReturn::accept(InstructionVisitor *v) { v->visit(this); } TerminatorBranch::TerminatorBranch(BasicBlock *successor) @@ -153,6 +157,10 @@ void TerminatorBranch::setSuccessor(BasicBlock *new_succ) { successor = new_succ; } +std::unique_ptr TerminatorBranch::clone() { + return std::make_unique(successor); +} + void TerminatorBranch::accept(InstructionVisitor *v) { v->visit(this); } TerminatorCondBranch::TerminatorCondBranch(Value *cond, BasicBlock *t_successor, @@ -181,6 +189,11 @@ void TerminatorCondBranch::setFSuccessor(BasicBlock *new_succ) { f_successor = new_succ; } +std::unique_ptr TerminatorCondBranch::clone() { + return std::make_unique(cond, t_successor, + f_successor); +} + void TerminatorCondBranch::accept(InstructionVisitor *v) { v->visit(this); } } // namespace middleend::mir diff --git a/src/middleend/mir/instruction.h b/src/middleend/mir/instruction.h index f7c1964d..77a38305 100644 --- a/src/middleend/mir/instruction.h +++ b/src/middleend/mir/instruction.h @@ -3,6 +3,7 @@ #include "middleend/mir/operator.h" #include "middleend/mir/value.h" +#include #include namespace middleend::mir { @@ -107,6 +108,7 @@ class InstructionParallelCopy : public Instruction { class Terminator : public Instruction { public: virtual void accept(InstructionVisitor *v) = 0; + virtual std::unique_ptr clone() = 0; virtual ~Terminator() = default; }; @@ -115,6 +117,7 @@ class TerminatorReturn : public Terminator { TerminatorReturn(Value *val); Value *getValue(); void setValue(Value *new_val); + std::unique_ptr clone() override; void accept(InstructionVisitor *v) override; private: @@ -126,6 +129,7 @@ class TerminatorBranch : public Terminator { TerminatorBranch(BasicBlock *successor); BasicBlock *getSuccessor(); void setSuccessor(BasicBlock *new_succ); + std::unique_ptr clone() override; void accept(InstructionVisitor *v) override; private: @@ -142,6 +146,7 @@ class TerminatorCondBranch : public Terminator { void setCond(Value *new_val); void setTSuccessor(BasicBlock *new_succ); void setFSuccessor(BasicBlock *new_succ); + std::unique_ptr clone() override; void accept(InstructionVisitor *v) override; private: diff --git a/src/middleend/mir/mir.cpp b/src/middleend/mir/mir.cpp index 9e08d454..b737d447 100644 --- a/src/middleend/mir/mir.cpp +++ b/src/middleend/mir/mir.cpp @@ -53,6 +53,10 @@ BasicBlockEdges &BasicBlock::getPredecessors() { return predecessors; } BasicBlockEdges &BasicBlock::getSuccessors() { return successors; } +void BasicBlock::setTerminator(std::unique_ptr new_terminator) { + terminator = std::move(new_terminator); +} + std::string BasicBlock::toString(NumberIR *nir) { uint64_t block_id = nir->getNumber(this); std::string name = block_id == -1 ? "entry" : std::to_string(block_id); diff --git a/src/middleend/mir/mir.h b/src/middleend/mir/mir.h index 651c90c1..61bc1b08 100644 --- a/src/middleend/mir/mir.h +++ b/src/middleend/mir/mir.h @@ -40,6 +40,7 @@ class BasicBlock { Terminator *getTerminator(); BasicBlockEdges &getPredecessors(); BasicBlockEdges &getSuccessors(); + void setTerminator(std::unique_ptr new_terminator); std::string toString(NumberIR *nir); private: From 08dc207f167e302ca07678b495ce23677cfb2bf5 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Wed, 27 May 2026 18:28:53 -0500 Subject: [PATCH 04/12] we changed headers. we gotta change the stuff that uses em too --- src/frontend/ast/to_mir.cpp | 2 +- src/frontend/utils/operator.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/ast/to_mir.cpp b/src/frontend/ast/to_mir.cpp index 47623cf0..882afee5 100644 --- a/src/frontend/ast/to_mir.cpp +++ b/src/frontend/ast/to_mir.cpp @@ -133,7 +133,7 @@ void ToMIRVisitor::makeReturnBB(mir::Type return_type) { void ToMIRVisitor::resolveBBEdges() { for (auto &bb : basic_blocks) { - auto *t = bb->getTerminator().get(); + auto *t = bb->getTerminator(); auto br = dynamic_cast(t); if (br) { diff --git a/src/frontend/utils/operator.cpp b/src/frontend/utils/operator.cpp index 52aed407..a3b3ec1e 100644 --- a/src/frontend/utils/operator.cpp +++ b/src/frontend/utils/operator.cpp @@ -1,5 +1,6 @@ #include "frontend/utils/operator.h" +#include #include namespace frontend { From fe5c39d3f5da0366883b3a08deb5a3d8f93cb979 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Wed, 27 May 2026 18:46:25 -0500 Subject: [PATCH 05/12] update formatting for all transforms + add some function pass splitting --- .../transform/insert_parallel_copies.cpp | 61 +-- .../transform/insert_parallel_copies.h | 3 + src/middleend/transform/inst_combine.cpp | 14 +- src/middleend/transform/inst_combine.h | 2 + src/middleend/transform/mem2reg.cpp | 428 +++++++++--------- src/middleend/transform/mem2reg.h | 3 + src/middleend/transform/simplify_cfg.cpp | 271 +++++------ src/middleend/transform/simplify_cfg.h | 3 + src/middleend/transform/split_critical.cpp | 125 ++--- src/middleend/transform/split_critical.h | 3 + 10 files changed, 473 insertions(+), 440 deletions(-) diff --git a/src/middleend/transform/insert_parallel_copies.cpp b/src/middleend/transform/insert_parallel_copies.cpp index 94c2a465..dbe1e26b 100644 --- a/src/middleend/transform/insert_parallel_copies.cpp +++ b/src/middleend/transform/insert_parallel_copies.cpp @@ -2,40 +2,45 @@ #include "middleend/mir/instruction.h" namespace middleend { + void InsertParallelCopies::run(mir::Program &p) { - for (auto &f : p.getFunctions()) { - auto definition = dynamic_cast(f.get()); - if (!definition) - return; - - for (auto &bb : definition->getBasicBlocks()) { - for (auto &i : bb->getInstructions()) { - auto phi = dynamic_cast(i.get()); - if (!phi) - break; - auto &phi_preds = phi->getPredecessors(); - - auto &preds = bb->getPredecessors(); - for (auto &pred : preds.getUniqueEdges()) { - auto &pred_instructions = pred->getInstructions(); - - // TODO: represent with attribute, not instruction - if (pred_instructions.empty() || - !dynamic_cast( - pred_instructions.back().get())) { - auto parallel_copy = - std::make_unique(); - pred_instructions.push_back(std::move(parallel_copy)); - } + for (auto &f : p.getFunctions()) + run(f.get()); +} - auto parallel_copy = - static_cast( - pred_instructions.back().get()); +void InsertParallelCopies::run(mir::Function *f) { + auto definition = dynamic_cast(f); + if (!definition) + return; + + for (auto &bb : definition->getBasicBlocks()) { + for (auto &i : bb->getInstructions()) { + auto phi = dynamic_cast(i.get()); + if (!phi) + break; + auto &phi_preds = phi->getPredecessors(); + + auto &preds = bb->getPredecessors(); + for (auto &pred : preds.getUniqueEdges()) { + auto &pred_instructions = pred->getInstructions(); - parallel_copy->setCopy(phi, phi_preds.at(pred)); + // TODO: represent with attribute, not instruction + if (pred_instructions.empty() || + !dynamic_cast( + pred_instructions.back().get())) { + auto parallel_copy = + std::make_unique(); + pred_instructions.push_back(std::move(parallel_copy)); } + + auto parallel_copy = + static_cast( + pred_instructions.back().get()); + + parallel_copy->setCopy(phi, phi_preds.at(pred)); } } } } + } // namespace middleend diff --git a/src/middleend/transform/insert_parallel_copies.h b/src/middleend/transform/insert_parallel_copies.h index 5e163474..29a15535 100644 --- a/src/middleend/transform/insert_parallel_copies.h +++ b/src/middleend/transform/insert_parallel_copies.h @@ -3,8 +3,11 @@ #include "middleend/pass.h" namespace middleend { + class InsertParallelCopies : public TransformPass { public: void run(mir::Program &p) override; + void run(mir::Function *f); }; + } // namespace middleend diff --git a/src/middleend/transform/inst_combine.cpp b/src/middleend/transform/inst_combine.cpp index 68ebe912..8d7178e1 100644 --- a/src/middleend/transform/inst_combine.cpp +++ b/src/middleend/transform/inst_combine.cpp @@ -1,10 +1,11 @@ -#include - #include "middleend/transform/inst_combine.h" #include "middleend/utils/erase_uses.h" #include "middleend/utils/replace_uses.h" +#include + namespace middleend { + void InstCombine::run(mir::Program &p) { EraseUsesVisitor euv; for (auto &f : p.getFunctions()) { @@ -96,11 +97,11 @@ void InstCombine::run(mir::Program &p) { return true; }; - // clang-format off - if (false - || tryConstantFold() - ) { + if (false + // clang-format off + || tryConstantFold() // clang-format on + ) { changed = true; continue; } @@ -111,4 +112,5 @@ void InstCombine::run(mir::Program &p) { } } } + } // namespace middleend diff --git a/src/middleend/transform/inst_combine.h b/src/middleend/transform/inst_combine.h index 5a795ebe..19414d41 100644 --- a/src/middleend/transform/inst_combine.h +++ b/src/middleend/transform/inst_combine.h @@ -3,8 +3,10 @@ #include "middleend/pass.h" namespace middleend { + class InstCombine : public TransformPass { public: void run(mir::Program &p) override; }; + } // namespace middleend diff --git a/src/middleend/transform/mem2reg.cpp b/src/middleend/transform/mem2reg.cpp index e6c246fe..b4ebee5a 100644 --- a/src/middleend/transform/mem2reg.cpp +++ b/src/middleend/transform/mem2reg.cpp @@ -1,16 +1,17 @@ -#include -#include -#include -#include - +#include "middleend/transform/mem2reg.h" #include "middleend/analysis/dominator_tree.h" #include "middleend/mir/instruction.h" #include "middleend/mir/mir.h" -#include "middleend/transform/mem2reg.h" #include "middleend/utils/erase_uses.h" #include "middleend/utils/replace_uses.h" +#include +#include +#include +#include + namespace middleend { + std::unordered_map> computeDominanceFrontiers(DominatorTree *dt, mir::FunctionDefinition *f) { std::unordered_map> res; @@ -34,250 +35,250 @@ computeDominanceFrontiers(DominatorTree *dt, mir::FunctionDefinition *f) { } void Mem2Reg::run(mir::Program &p) { - EraseUsesVisitor euv; - for (auto &f : p.getFunctions()) { - auto definition = dynamic_cast(f.get()); - if (!definition) - continue; + for (auto &f : p.getFunctions()) + run(f.get()); +} - // - // Compute dominance frontiers - // - std::unordered_map> - dominance_frontiers = computeDominanceFrontiers(dt, definition); - - // - // Get all defs and mark unpromotable allocas - // - std::unordered_map> - defs; - std::unordered_set unpromotable; - for (auto &bb : definition->getBasicBlocks()) { - for (auto &i : bb->getInstructions()) { - // Mark unpromotable allocas - auto *alloca = dynamic_cast(i.get()); - if (alloca) { - for (auto &[use, _] : alloca->getUses()) { - if (dynamic_cast(use)) - continue; - - auto *use_store = - dynamic_cast(use); - if (use_store && dynamic_cast( - use_store->getValue()) != alloca) - continue; - - unpromotable.insert(alloca); - break; - } - } +void Mem2Reg::run(mir::Function *f) { + EraseUsesVisitor euv; - // Mark defs - auto *store = dynamic_cast(i.get()); - if (store) { - auto ptr_alloca = - dynamic_cast(store->getPtr()); - if (!ptr_alloca) + auto definition = dynamic_cast(f); + if (!definition) + return; + + // + // Compute dominance frontiers + // + std::unordered_map> + dominance_frontiers = computeDominanceFrontiers(dt, definition); + + // + // Get all defs and mark unpromotable allocas + // + std::unordered_map> + defs; + std::unordered_set unpromotable; + for (auto &bb : definition->getBasicBlocks()) { + for (auto &i : bb->getInstructions()) { + // Mark unpromotable allocas + auto *alloca = dynamic_cast(i.get()); + if (alloca) { + for (auto &[use, _] : alloca->getUses()) { + if (dynamic_cast(use)) continue; - defs[ptr_alloca].insert(bb.get()); - } - } - } - - // - // Phi Insertion - // - std::unordered_map< - mir::BasicBlock *, - std::unordered_map>> - phis; - for (auto const &[alloca, def_blocks] : defs) { - if (unpromotable.contains(alloca)) - continue; - mir::Type type = alloca->getAllocType(); - std::vector worklist(def_blocks.begin(), - def_blocks.end()); - std::unordered_set visited; - while (!worklist.empty()) { - auto &block = worklist.back(); - worklist.pop_back(); - for (auto &bb : dominance_frontiers[block]) { - if (visited.contains(bb)) + auto *use_store = + dynamic_cast(use); + if (use_store && dynamic_cast( + use_store->getValue()) != alloca) continue; - phis[bb][alloca] = - std::make_unique(type); - - visited.insert(bb); - if (!def_blocks.contains(bb)) - worklist.push_back(bb); + unpromotable.insert(alloca); + break; } } + + // Mark defs + auto *store = dynamic_cast(i.get()); + if (store) { + auto ptr_alloca = + dynamic_cast(store->getPtr()); + if (!ptr_alloca) + continue; + defs[ptr_alloca].insert(bb.get()); + } } + } + + // + // Phi Insertion + // + std::unordered_map>> + phis; + for (auto const &[alloca, def_blocks] : defs) { + if (unpromotable.contains(alloca)) + continue; - // - // Variable renaming - // - std::vector>> - worklist = {{definition->getEntryBlock(), {}}}; + mir::Type type = alloca->getAllocType(); + std::vector worklist(def_blocks.begin(), + def_blocks.end()); std::unordered_set visited; - std::vector> to_drop; while (!worklist.empty()) { - auto &bb = worklist.back().first; - auto reaching = std::move(worklist.back().second); + auto &block = worklist.back(); worklist.pop_back(); + for (auto &bb : dominance_frontiers[block]) { + if (visited.contains(bb)) + continue; - for (auto &[alloca, phi] : phis[bb]) { - // Safely assume no unlowerable allocas - reaching[alloca] = phi.get(); - for (auto succ : bb->getSuccessors().getUniqueEdges()) { - auto &succ_phis = phis[succ]; - if (succ_phis.contains(alloca)) - succ_phis[alloca]->setPredecessor(bb, phi.get()); - } + phis[bb][alloca] = std::make_unique(type); + + visited.insert(bb); + if (!def_blocks.contains(bb)) + worklist.push_back(bb); } + } + } - auto &instructions = bb->getInstructions(); - auto iter = instructions.begin(); - while (iter != instructions.end()) { - auto i = iter->get(); + // + // Variable renaming + // + std::vector>> + worklist = {{definition->getEntryBlock(), {}}}; + std::unordered_set visited; + std::vector> to_drop; + while (!worklist.empty()) { + auto &bb = worklist.back().first; + auto reaching = std::move(worklist.back().second); + worklist.pop_back(); + + for (auto &[alloca, phi] : phis[bb]) { + // Safely assume no unlowerable allocas + reaching[alloca] = phi.get(); + for (auto succ : bb->getSuccessors().getUniqueEdges()) { + auto &succ_phis = phis[succ]; + if (succ_phis.contains(alloca)) + succ_phis[alloca]->setPredecessor(bb, phi.get()); + } + } - // Alloca: mark for drop - auto *alloca = dynamic_cast(i); - if (alloca) { - if (unpromotable.contains(alloca)) { - iter++; - continue; - } + auto &instructions = bb->getInstructions(); + auto iter = instructions.begin(); + while (iter != instructions.end()) { + auto i = iter->get(); - i->accept(&euv); - to_drop.push_back(std::move(*iter)); - iter = instructions.erase(iter); + // Alloca: mark for drop + auto *alloca = dynamic_cast(i); + if (alloca) { + if (unpromotable.contains(alloca)) { + iter++; continue; } - // Store: update reaching def, delete - auto *store = dynamic_cast(i); - if (store) { - auto alloca = - dynamic_cast(store->getPtr()); - if (!alloca || unpromotable.contains(alloca)) { - iter++; - continue; - } - - auto value = store->getValue(); - reaching[alloca] = value; - for (auto succ : bb->getSuccessors().getUniqueEdges()) { - auto &succ_phis = phis[succ]; - if (succ_phis.contains(alloca)) - succ_phis[alloca]->setPredecessor(bb, value); - } - - i->accept(&euv); - to_drop.push_back(std::move(*iter)); - iter = instructions.erase(iter); + i->accept(&euv); + to_drop.push_back(std::move(*iter)); + iter = instructions.erase(iter); + continue; + } + + // Store: update reaching def, delete + auto *store = dynamic_cast(i); + if (store) { + auto alloca = + dynamic_cast(store->getPtr()); + if (!alloca || unpromotable.contains(alloca)) { + iter++; continue; } - // Load: replace uses with reaching def, delete - auto *load = dynamic_cast(i); - if (load) { - auto alloca = - dynamic_cast(load->getPtr()); - if (!alloca || unpromotable.contains(alloca)) { - iter++; - continue; - } - ReplaceUsesVisitor ruv(load, reaching[load->getPtr()]); - auto uses_range = std::views::keys(load->getUses()); - std::vector uses(uses_range.begin(), - uses_range.end()); - for (auto &use : uses) - use->accept(&ruv); - - i->accept(&euv); - to_drop.push_back(std::move(*iter)); - iter = instructions.erase(iter); - continue; + auto value = store->getValue(); + reaching[alloca] = value; + for (auto succ : bb->getSuccessors().getUniqueEdges()) { + auto &succ_phis = phis[succ]; + if (succ_phis.contains(alloca)) + succ_phis[alloca]->setPredecessor(bb, value); } - iter++; + i->accept(&euv); + to_drop.push_back(std::move(*iter)); + iter = instructions.erase(iter); + continue; } - visited.insert(bb); - for (auto succ : bb->getSuccessors().getUniqueEdges()) { - if (visited.contains(succ)) + // Load: replace uses with reaching def, delete + auto *load = dynamic_cast(i); + if (load) { + auto alloca = + dynamic_cast(load->getPtr()); + if (!alloca || unpromotable.contains(alloca)) { + iter++; continue; - worklist.push_back({succ, reaching}); + } + ReplaceUsesVisitor ruv(load, reaching[load->getPtr()]); + auto uses_range = std::views::keys(load->getUses()); + std::vector uses(uses_range.begin(), + uses_range.end()); + for (auto &use : uses) + use->accept(&ruv); + + i->accept(&euv); + to_drop.push_back(std::move(*iter)); + iter = instructions.erase(iter); + continue; } + + iter++; } - // - // Finalize phis - // - auto cmp_phi = [&](std::unique_ptr &first, - std::unique_ptr &second) { - auto first_preds = first->getPredecessors(), - second_preds = second->getPredecessors(); - auto first_size = first_preds.size(), - second_size = second_preds.size(); - - if (first_size != second_size) - return first_size < second_size; - - std::map first_map, second_map; - for (auto [bb, val] : first_preds) - first_map[nir->getNumber(bb)] = nir->getNumber(val); - for (auto [bb, val] : second_preds) - second_map[nir->getNumber(bb)] = nir->getNumber(val); - - auto first_iter = first_map.begin(), - second_iter = second_map.begin(); - while (first_iter != first_map.end()) { - if (*first_iter != *second_iter) { - auto [first_bb, first_val] = *first_iter; - auto [second_bb, second_val] = *second_iter; - return first_bb < second_bb || - first_bb == second_bb && first_val < second_val; - } - first_iter++; - second_iter++; + visited.insert(bb); + for (auto succ : bb->getSuccessors().getUniqueEdges()) { + if (visited.contains(succ)) + continue; + worklist.push_back({succ, reaching}); + } + } + + // + // Finalize phis + // + auto cmp_phi = [&](std::unique_ptr &first, + std::unique_ptr &second) { + auto first_preds = first->getPredecessors(), + second_preds = second->getPredecessors(); + auto first_size = first_preds.size(), second_size = second_preds.size(); + + if (first_size != second_size) + return first_size < second_size; + + std::map first_map, second_map; + for (auto [bb, val] : first_preds) + first_map[nir->getNumber(bb)] = nir->getNumber(val); + for (auto [bb, val] : second_preds) + second_map[nir->getNumber(bb)] = nir->getNumber(val); + + auto first_iter = first_map.begin(), second_iter = second_map.begin(); + while (first_iter != first_map.end()) { + if (*first_iter != *second_iter) { + auto [first_bb, first_val] = *first_iter; + auto [second_bb, second_val] = *second_iter; + return first_bb < second_bb || + first_bb == second_bb && first_val < second_val; } + first_iter++; + second_iter++; + } - return false; - }; + return false; + }; - for (auto &[bb, map] : phis) { - std::vector> to_sort; - for (auto &[_, phi] : map) { - switch (phi->getPredecessors().size()) { - default: - to_sort.push_back(std::move(phi)); - continue; - case 0: // empty phi: omit - continue; - case 1: // single branch phi: replace use with value - ReplaceUsesVisitor ruv( - phi.get(), phi->getPredecessors().begin()->second); - auto uses_range = std::views::keys(phi->getUses()); - std::vector uses(uses_range.begin(), - uses_range.end()); - for (auto use : uses) - use->accept(&ruv); - phi->accept(&euv); - continue; - } + for (auto &[bb, map] : phis) { + std::vector> to_sort; + for (auto &[_, phi] : map) { + switch (phi->getPredecessors().size()) { + default: + to_sort.push_back(std::move(phi)); + continue; + case 0: // empty phi: omit + continue; + case 1: // single branch phi: replace use with value + ReplaceUsesVisitor ruv(phi.get(), + phi->getPredecessors().begin()->second); + auto uses_range = std::views::keys(phi->getUses()); + std::vector uses(uses_range.begin(), + uses_range.end()); + for (auto use : uses) + use->accept(&ruv); + phi->accept(&euv); + continue; } - - std::sort(to_sort.begin(), to_sort.end(), cmp_phi); - for (auto &phi : to_sort) - bb->getInstructions().push_front(std::move(phi)); } + + std::sort(to_sort.begin(), to_sort.end(), cmp_phi); + for (auto &phi : to_sort) + bb->getInstructions().push_front(std::move(phi)); } } @@ -312,4 +313,5 @@ void Mem2Reg::registerAnalyses( analyses.push_back(std::move(nir)); } } + } // namespace middleend diff --git a/src/middleend/transform/mem2reg.h b/src/middleend/transform/mem2reg.h index c6a9433b..3ec634b6 100644 --- a/src/middleend/transform/mem2reg.h +++ b/src/middleend/transform/mem2reg.h @@ -5,9 +5,11 @@ #include "middleend/pass.h" namespace middleend { + class Mem2Reg : public TransformPass { public: void run(mir::Program &p) override; + void run(mir::Function *f); void registerAnalyses( std::vector> &analyses) override; @@ -15,4 +17,5 @@ class Mem2Reg : public TransformPass { DominatorTree *dt; NumberIR *nir; }; + } // namespace middleend diff --git a/src/middleend/transform/simplify_cfg.cpp b/src/middleend/transform/simplify_cfg.cpp index 8015ee61..6e9f40d2 100644 --- a/src/middleend/transform/simplify_cfg.cpp +++ b/src/middleend/transform/simplify_cfg.cpp @@ -1,156 +1,161 @@ -#include - #include "middleend/transform/simplify_cfg.h" -namespace middleend { -void SimplifyCFG::run(mir::Program &p) { - for (auto &f : p.getFunctions()) { - auto definition = dynamic_cast(f.get()); - if (!definition) - continue; - - bool changed = true; - while (changed) { - changed = false; - std::vector> to_drop; - auto &bbs = definition->getBasicBlocks(); - // TODO: handle non-sequential BB storage order - auto iter = bbs.begin(); - while (iter != bbs.end()) { - auto bb = iter->get(); - - auto &preds = bb->getPredecessors(); - auto &succs = bb->getSuccessors(); - - auto tryRemoveOrphaned = [&]() { - if (preds.getSize() || bb == definition->getEntryBlock()) - return false; - - for (auto succ : succs.getEdges()) - succ->getPredecessors().removeEdge(bb); - - to_drop.push_back(std::move(*iter)); - iter = bbs.erase(iter); - return true; - }; - - auto tryMergeStraightLine = [&]() { - if (preds.getSize() != 1) - return false; - auto pred = preds.getEdges()[0]; - if (pred->getSuccessors().getSize() != 1) - return false; - - auto &pred_insts = pred->getInstructions(); - for (auto &i : bb->getInstructions()) { - assert(!dynamic_cast(i.get())); - pred_insts.push_back(std::move(i)); - } - - for (auto succ : succs.getEdges()) { - auto &succ_preds = succ->getPredecessors(); - succ_preds.removeEdge(bb); - succ_preds.addEdge(pred); - - for (auto &i : succ->getInstructions()) { - auto phi = - dynamic_cast(i.get()); - if (!phi) - break; - if (!phi->getPredecessors().contains(bb)) - continue; - - auto pair = phi->getPredecessors().extract(bb); - phi->getPredecessors()[pred] = pair.mapped(); - } - } +#include - pred->getSuccessors() = std::move(succs); - pred->getTerminator().swap(bb->getTerminator()); +namespace middleend { - if (bb == definition->getEntryBlock()) - definition->setEntryBlock(pred); +void SimplifyCFG::run(mir::Program &p) { + for (auto &f : p.getFunctions()) + run(f.get()); +} - to_drop.push_back(std::move(*iter)); - iter = bbs.erase(iter); - return true; - }; +void SimplifyCFG::run(mir::Function *f) { + auto *definition = dynamic_cast(f); + if (!definition) + return; + + bool changed = true; + while (changed) { + changed = false; + std::vector> to_drop; + + auto &bbs = definition->getBasicBlocks(); + // TODO: handle non-sequential BB storage order + auto iter = bbs.begin(); + while (iter != bbs.end()) { + auto bb = iter->get(); + + auto &preds = bb->getPredecessors(); + auto &succs = bb->getSuccessors(); + + auto tryRemoveOrphaned = [&]() { + if (preds.getSize() || bb == definition->getEntryBlock()) + return false; + + for (auto succ : succs.getEdges()) + succ->getPredecessors().removeEdge(bb); + + to_drop.push_back(std::move(*iter)); + iter = bbs.erase(iter); + return true; + }; + + auto tryMergeStraightLine = [&]() { + if (preds.getSize() != 1) + return false; + auto pred = preds.getEdges()[0]; + if (pred->getSuccessors().getSize() != 1) + return false; + + auto &pred_insts = pred->getInstructions(); + for (auto &i : bb->getInstructions()) { + assert(!dynamic_cast(i.get())); + pred_insts.push_back(std::move(i)); + } - auto tryMergeUncondBr = [&]() { - auto terminator = dynamic_cast( - bb->getTerminator().get()); - if (!terminator || bb->getInstructions().size()) - return false; - auto succ = terminator->getSuccessor(); + for (auto succ : succs.getEdges()) { auto &succ_preds = succ->getPredecessors(); - auto succ_preds_has = succ_preds.getUniqueEdges(); - // TODO: handle this case properly: we can't join if - // succ has a phi since its value depends on - // previous block - auto &succ_insts = succ->getInstructions(); - bool succ_has_phi = !succ_insts.empty() && - dynamic_cast( - succ_insts.front().get()); - if (succ_has_phi) - return false; - succ_preds.removeEdge(bb); - for (auto pred : preds.getEdges()) { - // Replace succ preds - succ_preds.addEdge(pred); + succ_preds.addEdge(pred); + + for (auto &i : succ->getInstructions()) { + auto phi = dynamic_cast(i.get()); + if (!phi) + break; + if (!phi->getPredecessors().contains(bb)) + continue; - // Replace pred succs - auto &pred_succs = pred->getSuccessors(); - pred_succs.removeEdge(bb); - pred_succs.addEdge(succ); + auto pair = phi->getPredecessors().extract(bb); + phi->getPredecessors()[pred] = pair.mapped(); + } + } - // Replace pred terminator blocks - auto pred_terminator = pred->getTerminator().get(); + pred->getSuccessors() = std::move(succs); + pred->setTerminator(bb->getTerminator()->clone()); + + if (bb == definition->getEntryBlock()) + definition->setEntryBlock(pred); + + to_drop.push_back(std::move(*iter)); + iter = bbs.erase(iter); + return true; + }; + + auto tryMergeUncondBr = [&]() { + auto terminator = + dynamic_cast(bb->getTerminator()); + if (!terminator || bb->getInstructions().size()) + return false; + auto succ = terminator->getSuccessor(); + auto &succ_preds = succ->getPredecessors(); + auto succ_preds_has = succ_preds.getUniqueEdges(); + // TODO: handle this case properly: we can't join if + // succ has a phi since its value depends on + // previous block + auto &succ_insts = succ->getInstructions(); + bool succ_has_phi = + !succ_insts.empty() && dynamic_cast( + succ_insts.front().get()); + if (succ_has_phi) + return false; + + succ_preds.removeEdge(bb); + for (auto pred : preds.getEdges()) { + // Replace succ preds + succ_preds.addEdge(pred); + + // Replace pred succs + auto &pred_succs = pred->getSuccessors(); + pred_succs.removeEdge(bb); + pred_succs.addEdge(succ); + + // Replace pred terminator blocks + auto pred_terminator = pred->getTerminator(); + + auto branch = + dynamic_cast(pred_terminator); + if (branch) { + branch->setSuccessor(succ); + continue; + } - auto branch = dynamic_cast( + auto cond_branch = + dynamic_cast( pred_terminator); - if (branch) { - branch->setSuccessor(succ); - continue; - } - - auto cond_branch = - dynamic_cast( - pred_terminator); - if (cond_branch) { - if (cond_branch->getTSuccessor() == bb) - cond_branch->setTSuccessor(succ); - if (cond_branch->getFSuccessor() == bb) - cond_branch->setFSuccessor(succ); - } + if (cond_branch) { + if (cond_branch->getTSuccessor() == bb) + cond_branch->setTSuccessor(succ); + if (cond_branch->getFSuccessor() == bb) + cond_branch->setFSuccessor(succ); } + } - if (bb == definition->getEntryBlock()) - definition->setEntryBlock(succ); + if (bb == definition->getEntryBlock()) + definition->setEntryBlock(succ); - to_drop.push_back(std::move(*iter)); - iter = bbs.erase(iter); - return true; - }; + to_drop.push_back(std::move(*iter)); + iter = bbs.erase(iter); + return true; + }; - // TODO: eliminate phi if only one successor - auto tryResolvePhi = [&]() { return false; }; + // TODO: eliminate phi if only one successor + auto tryResolvePhi = [&]() { return false; }; + if (false // clang-format off - if (false - || tryRemoveOrphaned() - || tryMergeStraightLine() - || tryMergeUncondBr() - || tryResolvePhi() - ) { - // clang-format on - changed = true; - continue; - } - - iter++; + || tryRemoveOrphaned() + || tryMergeStraightLine() + || tryMergeUncondBr() + || tryResolvePhi() + // clang-format on + ) { + changed = true; + continue; } + + iter++; } } } + } // namespace middleend diff --git a/src/middleend/transform/simplify_cfg.h b/src/middleend/transform/simplify_cfg.h index 52bcb7b8..5ae46fb9 100644 --- a/src/middleend/transform/simplify_cfg.h +++ b/src/middleend/transform/simplify_cfg.h @@ -3,8 +3,11 @@ #include "middleend/pass.h" namespace middleend { + class SimplifyCFG : public TransformPass { public: void run(mir::Program &p) override; + void run(mir::Function *f); }; + } // namespace middleend diff --git a/src/middleend/transform/split_critical.cpp b/src/middleend/transform/split_critical.cpp index 1fa69535..17e22981 100644 --- a/src/middleend/transform/split_critical.cpp +++ b/src/middleend/transform/split_critical.cpp @@ -2,79 +2,84 @@ #include "middleend/mir/instruction.h" namespace middleend { -void SplitCritical::run(mir::Program &p) { - for (auto &f : p.getFunctions()) { - auto definition = dynamic_cast(f.get()); - if (!definition) - continue; - auto &bbs = definition->getBasicBlocks(); - for (auto bb_iter = bbs.begin(); bb_iter != bbs.end(); bb_iter++) { - auto bb = bb_iter->get(); +void SplitCritical::run(mir::Program &p) { + for (auto &f : p.getFunctions()) + run(f.get()); +} - auto &bb_preds = bb->getPredecessors(); - for (auto &pred : bb_preds.getUniqueEdges()) { - auto &pred_succs = pred->getSuccessors(); - if (pred_succs.getUniqueEdges().size() < 2) - continue; +void SplitCritical::run(mir::Function *f) { + auto *definition = dynamic_cast(f); + if (!definition) + return; - // Insert new block - std::list> body; - auto terminator = std::make_unique(bb); - auto new_block_unique = std::make_unique( - std::move(body), std::move(terminator)); - auto new_block = new_block_unique.get(); - bbs.insert(bb_iter, std::move(new_block_unique)); + auto &bbs = definition->getBasicBlocks(); + for (auto bb_iter = bbs.begin(); bb_iter != bbs.end(); bb_iter++) { + auto *bb = bb_iter->get(); - // Update pred out edges + new block in edges - auto &new_preds = new_block->getPredecessors(); - for (auto out_edge : pred_succs.getEdges()) - if (out_edge == bb) { - pred_succs.removeEdge(bb); - pred_succs.addEdge(new_block); - new_preds.addEdge(pred); - } + auto &bb_preds = bb->getPredecessors(); + for (auto &pred : bb_preds.getUniqueEdges()) { + auto &pred_succs = pred->getSuccessors(); + if (pred_succs.getUniqueEdges().size() < 2) + continue; - // Update bb in edges + new block out edges - auto &new_succs = new_block->getSuccessors(); - for (auto in_edge : bb_preds.getEdges()) - if (in_edge == pred) { - bb_preds.removeEdge(pred); - bb_preds.addEdge(new_block); - new_succs.addEdge(bb); - } + // Insert new block + std::list> body; + auto terminator = std::make_unique(bb); + auto new_block_unique = std::make_unique( + std::move(body), std::move(terminator)); + auto *new_block = new_block_unique.get(); + bbs.insert(bb_iter, std::move(new_block_unique)); - // Update phis in bb - for (auto &i : bb->getInstructions()) { - auto phi = dynamic_cast(i.get()); - if (!phi) - break; + // Update pred out edges + new block in edges + auto &new_preds = new_block->getPredecessors(); + for (auto *out_edge : pred_succs.getEdges()) + if (out_edge == bb) { + pred_succs.removeEdge(bb); + pred_succs.addEdge(new_block); + new_preds.addEdge(pred); + } - auto &phi_preds = phi->getPredecessors(); - phi_preds[new_block] = phi_preds.at(pred); - phi_preds.erase(pred); + // Update bb in edges + new block out edges + auto &new_succs = new_block->getSuccessors(); + for (auto *in_edge : bb_preds.getEdges()) + if (in_edge == pred) { + bb_preds.removeEdge(pred); + bb_preds.addEdge(new_block); + new_succs.addEdge(bb); } - // Clean up pred terminator - auto pred_terminator = pred->getTerminator().get(); + // Update phis in bb + for (auto &i : bb->getInstructions()) { + auto *phi = dynamic_cast(i.get()); + if (!phi) + break; - auto branch = - dynamic_cast(pred_terminator); - if (branch) { - branch->setSuccessor(new_block); - continue; - } + auto &phi_preds = phi->getPredecessors(); + phi_preds[new_block] = phi_preds.at(pred); + phi_preds.erase(pred); + } - auto cond_branch = - dynamic_cast(pred_terminator); - if (cond_branch) { - if (cond_branch->getTSuccessor() == bb) - cond_branch->setTSuccessor(new_block); - if (cond_branch->getFSuccessor() == bb) - cond_branch->setFSuccessor(new_block); - } + // Clean up pred terminator + auto *pred_terminator = pred->getTerminator(); + + auto *branch = + dynamic_cast(pred_terminator); + if (branch) { + branch->setSuccessor(new_block); + continue; + } + + auto *cond_branch = + dynamic_cast(pred_terminator); + if (cond_branch) { + if (cond_branch->getTSuccessor() == bb) + cond_branch->setTSuccessor(new_block); + if (cond_branch->getFSuccessor() == bb) + cond_branch->setFSuccessor(new_block); } } } } + } // namespace middleend diff --git a/src/middleend/transform/split_critical.h b/src/middleend/transform/split_critical.h index 269ee66a..3e30b0b9 100644 --- a/src/middleend/transform/split_critical.h +++ b/src/middleend/transform/split_critical.h @@ -3,8 +3,11 @@ #include "middleend/pass.h" namespace middleend { + class SplitCritical : public TransformPass { public: void run(mir::Program &p) override; + void run(mir::Function *f); }; + } // namespace middleend From e49c40e74324fca8f4b03106149f2ddd94df77eb Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Wed, 27 May 2026 18:51:41 -0500 Subject: [PATCH 06/12] clean up driver stuff --- src/driver/compiler.cpp | 7 +++---- src/driver/runtime.c | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/driver/compiler.cpp b/src/driver/compiler.cpp index bf98501d..9a9c89ca 100644 --- a/src/driver/compiler.cpp +++ b/src/driver/compiler.cpp @@ -32,7 +32,7 @@ void printHelp(const std::string &program_name) { PRINT(" --help Show this help message"); PRINT(" -o Output file"); PRINT(""); - PRINT(" -E, --preprocess Only run preprocessor (WIP)"); + PRINT(" -E, --preprocess Only run preprocessor"); PRINT(""); PRINT(" --emit-ast Output AST to file"); PRINT(""); @@ -45,8 +45,8 @@ void printHelp(const std::string &program_name) { PRINT(" --emit-lir-regalloc Output LIR to file, after register " "allocation"); PRINT(""); - PRINT(" -S, --assemble Output assembly"); - PRINT(" -c, --compile Output assembly (WIP)"); + PRINT(" -c, --compile Stop before assembling"); + PRINT(" -S, --assemble Stop before linking"); } void output(const std::string &output, std::filesystem::path output_path) { @@ -159,7 +159,6 @@ int main(int argc, char *argv[]) { } } - // TODO: preprocessor std::string preprocessed = frontend::preprocess(input_file); if (output_level == OutputLevel::PREPROCESS) { output(preprocessed, output_file); diff --git a/src/driver/runtime.c b/src/driver/runtime.c index a5393106..5998dcfe 100644 --- a/src/driver/runtime.c +++ b/src/driver/runtime.c @@ -1,8 +1,8 @@ +#include "runtime.h" + #include #include -#include "runtime.h" - int *alloc(int size) { return (int *)malloc(size); } int dealloc(int *ptr) { From 76cac2c84e665952b867197596464c0b26da0434 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Fri, 29 May 2026 19:23:47 -0500 Subject: [PATCH 07/12] reformat lir --- src/backend/lir/condition_code.cpp | 6 ++++-- src/backend/lir/condition_code.h | 3 ++- src/backend/lir/data_size.cpp | 6 ++++-- src/backend/lir/data_size.h | 3 ++- src/backend/lir/instruction.cpp | 6 ++++-- src/backend/lir/instruction.h | 4 ++-- src/backend/lir/lir.cpp | 2 ++ src/backend/lir/lir.h | 6 ++++-- src/backend/lir/operand.cpp | 6 ++++-- src/backend/lir/operand.h | 6 ++++-- src/backend/lir/register_num.cpp | 6 ++++-- src/backend/lir/register_num.h | 8 ++++---- 12 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/backend/lir/condition_code.cpp b/src/backend/lir/condition_code.cpp index e51d9d98..08b15907 100644 --- a/src/backend/lir/condition_code.cpp +++ b/src/backend/lir/condition_code.cpp @@ -1,8 +1,9 @@ -#include - #include "backend/lir/condition_code.h" +#include + namespace backend::lir { + ConditionCode invert(ConditionCode cc) { switch (cc) { case ConditionCode::EQ: @@ -22,4 +23,5 @@ std::string toString(ConditionCode cc) { } std::unreachable(); } + } // namespace backend::lir diff --git a/src/backend/lir/condition_code.h b/src/backend/lir/condition_code.h index b0788323..9c0bc446 100644 --- a/src/backend/lir/condition_code.h +++ b/src/backend/lir/condition_code.h @@ -3,12 +3,13 @@ #include namespace backend::lir { + enum class ConditionCode { EQ, NEQ, }; ConditionCode invert(ConditionCode cc); - std::string toString(ConditionCode cc); + } // namespace backend::lir diff --git a/src/backend/lir/data_size.cpp b/src/backend/lir/data_size.cpp index b097c766..48422b03 100644 --- a/src/backend/lir/data_size.cpp +++ b/src/backend/lir/data_size.cpp @@ -1,8 +1,9 @@ -#include - #include "backend/lir/data_size.h" +#include + namespace backend::lir { + char toChar(Extend extend) { switch (extend) { case Extend::NONE: @@ -39,4 +40,5 @@ char toChar(DataSize size) { } std::unreachable(); } + } // namespace backend::lir diff --git a/src/backend/lir/data_size.h b/src/backend/lir/data_size.h index c7846654..9c7e110c 100644 --- a/src/backend/lir/data_size.h +++ b/src/backend/lir/data_size.h @@ -3,6 +3,7 @@ #include "middleend/mir/type.h" namespace backend::lir { + enum class Extend { NONE, ZERO, @@ -19,6 +20,6 @@ enum class DataSize { }; DataSize fromMir(middleend::mir::Type type); - char toChar(DataSize size); + } // namespace backend::lir diff --git a/src/backend/lir/instruction.cpp b/src/backend/lir/instruction.cpp index e5459fa2..c7a0fc74 100644 --- a/src/backend/lir/instruction.cpp +++ b/src/backend/lir/instruction.cpp @@ -1,8 +1,9 @@ -#include - #include "backend/lir/instruction.h" +#include + namespace backend::lir { + Label::Label(std::string name) : name(name) {} std::string Label::getName() { return name; } @@ -206,4 +207,5 @@ void InstructionCall::accept(InstructionVisitor *v) { v->visit(this); } void InstructionRet::accept(InstructionVisitor *v) { v->visit(this); } void InstructionUnknown::accept(InstructionVisitor *v) { v->visit(this); } + } // namespace backend::lir diff --git a/src/backend/lir/instruction.h b/src/backend/lir/instruction.h index 21d9a7ab..d89f2a3d 100644 --- a/src/backend/lir/instruction.h +++ b/src/backend/lir/instruction.h @@ -6,6 +6,7 @@ #include "middleend/mir/operator.h" namespace backend::lir { + class InstructionVisitor; class Instruction { @@ -97,7 +98,6 @@ enum class BinaryOp { }; BinaryOp fromMir(middleend::mir::BinaryOp op); - std::string toString(BinaryOp op); // TODO: div, inc, dec, neg, not @@ -211,7 +211,6 @@ class InstructionRet : public Instruction { void accept(InstructionVisitor *v) override; }; -// TODO: remove once tiling's implemented class InstructionUnknown : public Instruction { public: void accept(InstructionVisitor *v) override; @@ -235,4 +234,5 @@ class InstructionVisitor { virtual void visit(InstructionRet *i) = 0; virtual void visit(InstructionUnknown *i) = 0; }; + } // namespace backend::lir diff --git a/src/backend/lir/lir.cpp b/src/backend/lir/lir.cpp index 4a4566b7..85b06192 100644 --- a/src/backend/lir/lir.cpp +++ b/src/backend/lir/lir.cpp @@ -1,6 +1,7 @@ #include "backend/lir/lir.h" namespace backend::lir { + Function::Function(std::string name, uint64_t num_params, uint64_t stack_bytes, std::list> instructions) : name(name), num_params(num_params), stack_bytes(stack_bytes), @@ -177,4 +178,5 @@ void ToStringVisitor::visit(InstructionUnknown *i) { result += "\n "; result += "unknown"; } + } // namespace backend::lir diff --git a/src/backend/lir/lir.h b/src/backend/lir/lir.h index 9bbcb2ec..90bfb681 100644 --- a/src/backend/lir/lir.h +++ b/src/backend/lir/lir.h @@ -1,11 +1,12 @@ #pragma once +#include "backend/lir/instruction.h" + #include #include -#include "backend/lir/instruction.h" - namespace backend::lir { + class Function { public: Function(std::string name, uint64_t num_params, uint64_t stack_bytes, @@ -60,4 +61,5 @@ class ToStringVisitor : public InstructionVisitor { protected: std::string result; }; + } // namespace backend::lir diff --git a/src/backend/lir/operand.cpp b/src/backend/lir/operand.cpp index 129dc318..ae919c90 100644 --- a/src/backend/lir/operand.cpp +++ b/src/backend/lir/operand.cpp @@ -1,8 +1,9 @@ -#include - #include "backend/lir/operand.h" +#include + namespace backend::lir { + static uint64_t cur_id = 0; Immediate::Immediate(uint64_t value) : value(value) {} @@ -140,4 +141,5 @@ StackArg *OperandManager::getStackArg(uint64_t arg_num) { stack_args.insert({arg_num, std::make_unique(arg_num)}); return stack_args.at(arg_num).get(); } + } // namespace backend::lir diff --git a/src/backend/lir/operand.h b/src/backend/lir/operand.h index 7caa6161..f763df28 100644 --- a/src/backend/lir/operand.h +++ b/src/backend/lir/operand.h @@ -1,13 +1,14 @@ #pragma once +#include "backend/lir/register_num.h" + #include #include #include #include -#include "backend/lir/register_num.h" - namespace backend::lir { + class Operand { public: virtual std::string toString() = 0; @@ -108,4 +109,5 @@ class OperandManager { std::vector> addresses; std::unordered_map> stack_args; }; + } // namespace backend::lir diff --git a/src/backend/lir/register_num.cpp b/src/backend/lir/register_num.cpp index c6af762f..1a3047a0 100644 --- a/src/backend/lir/register_num.cpp +++ b/src/backend/lir/register_num.cpp @@ -1,8 +1,9 @@ -#include - #include "backend/lir/register_num.h" +#include + namespace backend::lir { + DataSize getSize(RegisterNum rn) { switch (rn) { case RegisterNum::RAX: @@ -331,4 +332,5 @@ const std::vector &getColoringPriority() { }; return coloring_priority; } + } // namespace backend::lir diff --git a/src/backend/lir/register_num.h b/src/backend/lir/register_num.h index 0cebe78d..3e18b207 100644 --- a/src/backend/lir/register_num.h +++ b/src/backend/lir/register_num.h @@ -1,10 +1,11 @@ #pragma once -#include - #include "backend/lir/data_size.h" +#include + namespace backend::lir { + enum class RegisterNum { VIRTUAL, @@ -46,9 +47,7 @@ enum class RegisterNum { }; DataSize getSize(RegisterNum rn); - RegisterNum toSized(RegisterNum rn, DataSize size); - std::string toString(RegisterNum rn); const std::vector &getAllRegisters(); @@ -56,4 +55,5 @@ const std::vector &getArgRegisters(); const std::vector &getCalleeSavedRegisters(); const std::vector &getCallerSavedRegisters(); const std::vector &getColoringPriority(); + } // namespace backend::lir From 5ab45aad28322fec385deaa25475dafbe0a9bcd0 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Fri, 29 May 2026 19:26:56 -0500 Subject: [PATCH 08/12] reformat lir_tree --- src/backend/lir_tree/function_info.cpp | 2 ++ src/backend/lir_tree/function_info.h | 2 ++ src/backend/lir_tree/gen_trees.cpp | 8 +++++--- src/backend/lir_tree/gen_trees.h | 1 + src/backend/lir_tree/merge_trees.cpp | 9 +++++---- src/backend/lir_tree/merge_trees.h | 2 ++ src/backend/lir_tree/node.cpp | 2 ++ src/backend/lir_tree/node.h | 8 +++++--- src/backend/lir_tree/tile_trees.cpp | 2 ++ src/backend/lir_tree/tile_trees.h | 2 ++ 10 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/backend/lir_tree/function_info.cpp b/src/backend/lir_tree/function_info.cpp index 511a3492..61ab4299 100644 --- a/src/backend/lir_tree/function_info.cpp +++ b/src/backend/lir_tree/function_info.cpp @@ -1,6 +1,7 @@ #include "function_info.h" namespace backend::lir_tree { + FunctionInfo::FunctionInfo(std::string name, uint64_t num_params) : name(name), num_params(num_params), stack_bytes(0) {} @@ -16,4 +17,5 @@ uint64_t FunctionInfo::allocate(uint64_t num_bytes) { stack_bytes += num_bytes; return offset; } + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/function_info.h b/src/backend/lir_tree/function_info.h index fe231e02..b3f6c5fc 100644 --- a/src/backend/lir_tree/function_info.h +++ b/src/backend/lir_tree/function_info.h @@ -4,6 +4,7 @@ #include namespace backend::lir_tree { + class FunctionInfo { public: FunctionInfo(std::string name, uint64_t num_params); @@ -17,4 +18,5 @@ class FunctionInfo { uint64_t num_params; uint64_t stack_bytes; }; + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/gen_trees.cpp b/src/backend/lir_tree/gen_trees.cpp index 4f52beca..0bc7246f 100644 --- a/src/backend/lir_tree/gen_trees.cpp +++ b/src/backend/lir_tree/gen_trees.cpp @@ -1,10 +1,11 @@ -#include - +#include "backend/lir_tree/gen_trees.h" #include "backend/lir/data_size.h" #include "backend/lir/operand.h" -#include "backend/lir_tree/gen_trees.h" + +#include namespace backend::lir_tree { + TreeGenVisitor::TreeGenVisitor(middleend::mir::Program &p, lir::OperandManager *om) : next_block(nullptr), om(om), tree_info(std::make_unique()) { @@ -371,4 +372,5 @@ void TreeGenVisitor::visit(middleend::mir::TerminatorCondBranch *t) { auto assembly = std::make_unique(std::move(instructions)); function_trees.push_back(std::move(assembly)); } + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/gen_trees.h b/src/backend/lir_tree/gen_trees.h index f788ec21..257882d7 100644 --- a/src/backend/lir_tree/gen_trees.h +++ b/src/backend/lir_tree/gen_trees.h @@ -49,4 +49,5 @@ class TreeGenVisitor : public middleend::mir::InstructionVisitor { std::vector> all_function_info; std::unique_ptr tree_info; }; + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/merge_trees.cpp b/src/backend/lir_tree/merge_trees.cpp index a3596464..292065ad 100644 --- a/src/backend/lir_tree/merge_trees.cpp +++ b/src/backend/lir_tree/merge_trees.cpp @@ -1,10 +1,11 @@ -#include -#include - #include "backend/lir_tree/merge_trees.h" #include "backend/lir_tree/node.h" +#include +#include + namespace backend::lir_tree { + TreeMerger::TreeMerger(TreeInfo *tree_info, lir::OperandManager *om) : tree_info(tree_info), om(om) {} @@ -156,7 +157,6 @@ void TreeMerger::mergeTrees(FunctionTrees &trees) { tryMerge(context, uses); merged.splice(merged.end(), context); merged.push_back(std::move(tree)); - // uses.clear(); } // try merge one more time @@ -166,4 +166,5 @@ void TreeMerger::mergeTrees(FunctionTrees &trees) { merged.reverse(); trees = std::move(merged); } + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/merge_trees.h b/src/backend/lir_tree/merge_trees.h index 54c2de25..f3c8be3a 100644 --- a/src/backend/lir_tree/merge_trees.h +++ b/src/backend/lir_tree/merge_trees.h @@ -3,6 +3,7 @@ #include "backend/lir_tree/node.h" namespace backend::lir_tree { + class TreeMerger { public: TreeMerger(TreeInfo *tree_info, lir::OperandManager *om); @@ -14,4 +15,5 @@ class TreeMerger { lir::OperandManager *om; TreeInfo *tree_info; }; + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/node.cpp b/src/backend/lir_tree/node.cpp index fc450255..b340b575 100644 --- a/src/backend/lir_tree/node.cpp +++ b/src/backend/lir_tree/node.cpp @@ -1,6 +1,7 @@ #include "backend/lir_tree/node.h" namespace backend::lir_tree { + lir::DataSize Node::getSize() { return lir::DataSize::QUADWORD; } RegisterNode::RegisterNode(lir::Register *reg, std::unique_ptr source) @@ -182,4 +183,5 @@ bool TreeInfo::hasMemInst(Node *tree) { void TreeInfo::setMemInst(Node *tree) { trees_with_memory_instruction.insert(tree); } + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/node.h b/src/backend/lir_tree/node.h index 26cd7112..3855b2d6 100644 --- a/src/backend/lir_tree/node.h +++ b/src/backend/lir_tree/node.h @@ -1,12 +1,13 @@ #pragma once -#include -#include - #include "backend/lir/instruction.h" #include "middleend/mir/operator.h" +#include +#include + namespace backend::lir_tree { + class NodeVisitor; enum class NodeType { @@ -171,4 +172,5 @@ class TreeInfo { std::unordered_map> tree_leaves; std::unordered_set trees_with_memory_instruction; }; + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/tile_trees.cpp b/src/backend/lir_tree/tile_trees.cpp index 0edd8854..f364429f 100644 --- a/src/backend/lir_tree/tile_trees.cpp +++ b/src/backend/lir_tree/tile_trees.cpp @@ -1,6 +1,7 @@ #include "backend/lir_tree/tile_trees.h" namespace backend::lir_tree { + bool matchIS(RegisterNode *node, RegisterNode **index_res, ImmediateNode **scale_res) { auto ®_src = node->getSource(); @@ -876,4 +877,5 @@ void TreeTiler::tile(Node *tree) { assembly.splice(assembly.end(), tree_instructions); } + } // namespace backend::lir_tree diff --git a/src/backend/lir_tree/tile_trees.h b/src/backend/lir_tree/tile_trees.h index b2ce1d64..8a59aae3 100644 --- a/src/backend/lir_tree/tile_trees.h +++ b/src/backend/lir_tree/tile_trees.h @@ -3,6 +3,7 @@ #include "backend/lir_tree/node.h" namespace backend::lir_tree { + class Tile { public: Tile(lir::OperandManager *om); @@ -193,4 +194,5 @@ class TreeTiler { std::vector> all_tiles; std::list> assembly; }; + } // namespace backend::lir_tree From b4771b75591fafda0bec4421a0d2d5a7d6b932eb Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Fri, 29 May 2026 19:31:35 -0500 Subject: [PATCH 09/12] reformat backend passes --- src/backend/passes/coalesce.cpp | 2 ++ src/backend/passes/coalesce.h | 2 ++ src/backend/passes/coloring.cpp | 10 ++++++---- src/backend/passes/coloring.h | 1 + src/backend/passes/interference.cpp | 8 +++++--- src/backend/passes/interference.h | 2 ++ src/backend/passes/legalize.cpp | 9 +++++---- src/backend/passes/legalize.h | 2 ++ src/backend/passes/liveness.cpp | 10 ++++++---- src/backend/passes/liveness.h | 6 ++++-- src/backend/passes/spill.cpp | 2 ++ src/backend/passes/spill.h | 2 ++ 12 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/backend/passes/coalesce.cpp b/src/backend/passes/coalesce.cpp index ff482a8f..03ef71fe 100644 --- a/src/backend/passes/coalesce.cpp +++ b/src/backend/passes/coalesce.cpp @@ -1,8 +1,10 @@ #include "backend/passes/coalesce.h" namespace backend { + bool tryCoalesce(lir::Function *f, Interference &interference) { // TODO: coalesce registers return false; } + } // namespace backend diff --git a/src/backend/passes/coalesce.h b/src/backend/passes/coalesce.h index adac8fee..bab8140c 100644 --- a/src/backend/passes/coalesce.h +++ b/src/backend/passes/coalesce.h @@ -3,5 +3,7 @@ #include "backend/passes/interference.h" namespace backend { + bool tryCoalesce(lir::Function *f, Interference &interference); + } // namespace backend diff --git a/src/backend/passes/coloring.cpp b/src/backend/passes/coloring.cpp index 098e3178..3c1d9716 100644 --- a/src/backend/passes/coloring.cpp +++ b/src/backend/passes/coloring.cpp @@ -1,11 +1,12 @@ -#include -#include - +#include "backend/passes/coloring.h" #include "backend/lir/operand.h" #include "backend/lir/register_num.h" -#include "backend/passes/coloring.h" + +#include +#include namespace backend { + PrecoloringVisitor::PrecoloringVisitor(lir::OperandManager *om) : om(om) {} // TODO: fill the rest of this in, im lazy rn @@ -300,4 +301,5 @@ void printColoring(RegisterColoring &coloring) { std::cout << reg->toString() << ": " << lir::toString(color) << std::endl; } + } // namespace backend diff --git a/src/backend/passes/coloring.h b/src/backend/passes/coloring.h index 591df99c..be9c5d06 100644 --- a/src/backend/passes/coloring.h +++ b/src/backend/passes/coloring.h @@ -5,6 +5,7 @@ #include "backend/passes/spill.h" namespace backend { + using RegisterColoring = std::unordered_map; class PrecoloringVisitor : public lir::InstructionVisitor { diff --git a/src/backend/passes/interference.cpp b/src/backend/passes/interference.cpp index f5572e59..e7c1b3c9 100644 --- a/src/backend/passes/interference.cpp +++ b/src/backend/passes/interference.cpp @@ -1,9 +1,10 @@ -#include - -#include "backend/lir/operand.h" #include "backend/passes/interference.h" +#include "backend/lir/operand.h" + +#include namespace backend { + InterferenceBuilder::InterferenceBuilder(lir::OperandManager *om) : om(om) {} Interference InterferenceBuilder::getInterference() { return interference; } @@ -96,4 +97,5 @@ void printInterference(Interference &i) { std::cout << "}" << std::endl; } } + } // namespace backend diff --git a/src/backend/passes/interference.h b/src/backend/passes/interference.h index 93db4fa4..a7ef257c 100644 --- a/src/backend/passes/interference.h +++ b/src/backend/passes/interference.h @@ -3,6 +3,7 @@ #include "backend/passes/liveness.h" namespace backend { + using Interference = std::unordered_map; constexpr lir::DataSize flat_size = lir::DataSize::QUADWORD; @@ -27,4 +28,5 @@ class InterferenceBuilder { lir::OperandManager *om; Interference interference; }; + } // namespace backend diff --git a/src/backend/passes/legalize.cpp b/src/backend/passes/legalize.cpp index 0d6864a5..92902281 100644 --- a/src/backend/passes/legalize.cpp +++ b/src/backend/passes/legalize.cpp @@ -1,10 +1,11 @@ -#include - -#include "backend/lir/register_num.h" #include "backend/passes/legalize.h" +#include "backend/lir/register_num.h" #include "backend/passes/liveness.h" +#include + namespace backend { + // TODO: unhardcode constexpr auto reg_size = lir::DataSize::QUADWORD; @@ -307,5 +308,5 @@ void legalize(lir::Program &lir) { instructions.insert(ret_iter, std::move(deallocate)); } } + } // namespace backend -; diff --git a/src/backend/passes/legalize.h b/src/backend/passes/legalize.h index 98b964f1..1cc05c30 100644 --- a/src/backend/passes/legalize.h +++ b/src/backend/passes/legalize.h @@ -3,6 +3,7 @@ #include "backend/lir/lir.h" namespace backend { + class ReplaceStackArgVisitor : public lir::InstructionVisitor { public: ReplaceStackArgVisitor(uint64_t stack_bytes, lir::OperandManager *om); @@ -31,4 +32,5 @@ class ReplaceStackArgVisitor : public lir::InstructionVisitor { }; void legalize(lir::Program &lir); + } // namespace backend diff --git a/src/backend/passes/liveness.cpp b/src/backend/passes/liveness.cpp index 1673f2ba..9cd16800 100644 --- a/src/backend/passes/liveness.cpp +++ b/src/backend/passes/liveness.cpp @@ -1,11 +1,12 @@ -#include -#include - +#include "backend/passes/liveness.h" #include "backend/lir/lir.h" #include "backend/lir/operand.h" -#include "backend/passes/liveness.h" + +#include +#include namespace backend { + Liveness::Liveness(std::vector gen, std::vector kill, std::vector in, std::vector out) : gen(gen), kill(kill), in(in), out(out) {} @@ -360,4 +361,5 @@ void printLiveness(lir::Function *f, Liveness &l) { } std::cout << "}" << std::endl; } + } // namespace backend diff --git a/src/backend/passes/liveness.h b/src/backend/passes/liveness.h index fb102552..ca5fdcec 100644 --- a/src/backend/passes/liveness.h +++ b/src/backend/passes/liveness.h @@ -1,10 +1,11 @@ #pragma once -#include - #include "backend/lir/lir.h" +#include + namespace backend { + using RegisterSet = std::unordered_set; class Liveness { @@ -108,4 +109,5 @@ class SuccessorVisitor : public lir::InstructionVisitor { std::unordered_map label_index; std::vector successors; }; + } // namespace backend diff --git a/src/backend/passes/spill.cpp b/src/backend/passes/spill.cpp index e9275670..8d5894b6 100644 --- a/src/backend/passes/spill.cpp +++ b/src/backend/passes/spill.cpp @@ -2,6 +2,7 @@ #include "backend/passes/interference.h" namespace backend { + static constexpr uint64_t def_weight = 5; static constexpr uint64_t use_weight = 10; static constexpr uint64_t max_weight = -1; @@ -143,4 +144,5 @@ void spillLowestCost(lir::Function *f, const SpillCosts &sc, Liveness &l, auto virtual_reg = static_cast(min_reg); spill(f, virtual_reg, l, om); } + } // namespace backend diff --git a/src/backend/passes/spill.h b/src/backend/passes/spill.h index 13e95971..e0491efc 100644 --- a/src/backend/passes/spill.h +++ b/src/backend/passes/spill.h @@ -4,6 +4,7 @@ #include "backend/passes/liveness.h" namespace backend { + using SpillCosts = std::unordered_map; SpillCosts computeSpillCosts(lir::Function *f, const Liveness &l, @@ -13,4 +14,5 @@ void spill(lir::Function *f, lir::VirtualRegister *reg, Liveness &l, lir::OperandManager *om); void spillLowestCost(lir::Function *f, const SpillCosts &sc, Liveness &l, lir::OperandManager *om); + } // namespace backend From 887f8373763db195ce69619fb8edf16c9e84b438 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Fri, 29 May 2026 19:32:19 -0500 Subject: [PATCH 10/12] reformat backend glue --- src/backend/codegen.cpp | 2 ++ src/backend/codegen.h | 2 ++ src/backend/mir_to_lir.cpp | 2 ++ src/backend/mir_to_lir.h | 2 ++ src/backend/regalloc.cpp | 2 ++ src/backend/regalloc.h | 2 ++ 6 files changed, 12 insertions(+) diff --git a/src/backend/codegen.cpp b/src/backend/codegen.cpp index cd0589ff..26f144e0 100644 --- a/src/backend/codegen.cpp +++ b/src/backend/codegen.cpp @@ -2,6 +2,7 @@ #include "backend/passes/legalize.h" namespace backend { + void CodeGenVisitor::generateFilePreamble() { result += " .text"; } void CodeGenVisitor::generateFilePostamble() { @@ -49,4 +50,5 @@ std::string generateCode(lir::Program &lir) { return cgv.getResult(); } + } // namespace backend diff --git a/src/backend/codegen.h b/src/backend/codegen.h index 772421ca..8f4503fb 100644 --- a/src/backend/codegen.h +++ b/src/backend/codegen.h @@ -3,6 +3,7 @@ #include "backend/lir/lir.h" namespace backend { + class CodeGenVisitor : public lir::ToStringVisitor { public: void generateFilePreamble(); @@ -14,4 +15,5 @@ class CodeGenVisitor : public lir::ToStringVisitor { }; std::string generateCode(lir::Program &lir); + } // namespace backend diff --git a/src/backend/mir_to_lir.cpp b/src/backend/mir_to_lir.cpp index 18f849d1..9fd32040 100644 --- a/src/backend/mir_to_lir.cpp +++ b/src/backend/mir_to_lir.cpp @@ -7,6 +7,7 @@ #include "middleend/utils/traversal.h" namespace backend { + std::tuple, std::unique_ptr, std::vector>> @@ -93,4 +94,5 @@ lir::Program mirToLir(middleend::mir::Program &mir) { lir::Program lir(std::move(functions), std::move(om)); return std::move(lir); } + } // namespace backend diff --git a/src/backend/mir_to_lir.h b/src/backend/mir_to_lir.h index 3a384103..fccb7a72 100644 --- a/src/backend/mir_to_lir.h +++ b/src/backend/mir_to_lir.h @@ -4,5 +4,7 @@ #include "middleend/mir/mir.h" namespace backend { + lir::Program mirToLir(middleend::mir::Program &mir); + } diff --git a/src/backend/regalloc.cpp b/src/backend/regalloc.cpp index 848028ca..4c9fba0a 100644 --- a/src/backend/regalloc.cpp +++ b/src/backend/regalloc.cpp @@ -6,6 +6,7 @@ #include "backend/passes/spill.h" namespace backend { + void allocateRegisters(lir::Program &lir) { auto om = lir.getOm(); @@ -37,4 +38,5 @@ void allocateRegisters(lir::Program &lir) { } } } + } // namespace backend diff --git a/src/backend/regalloc.h b/src/backend/regalloc.h index aa1638d5..3232d30f 100644 --- a/src/backend/regalloc.h +++ b/src/backend/regalloc.h @@ -3,5 +3,7 @@ #include "backend/lir/lir.h" namespace backend { + void allocateRegisters(lir::Program &lir); + } From eafa2843365ff2c8b33e5dd40a94d3fae3ecab95 Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Fri, 29 May 2026 19:38:08 -0500 Subject: [PATCH 11/12] update formatter --- .github/workflows/formatting.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 1fa9a861..01a44253 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -9,8 +9,16 @@ jobs: steps: - uses: actions/checkout@v5 + - name: Get updated LLVM + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 22 + - name: Install clang-format - run: sudo apt-get update && sudo apt-get install -y clang-format + run: | + sudo apt-get install -y clang-format-22 + sudo ln -sf $(which clang-format-22) /usr/local/bin/clang-format - name: Check formatting run: | From 75aafa738162f72cea261852df42a470c73ba27b Mon Sep 17 00:00:00 2001 From: Benjamin Ye Date: Fri, 29 May 2026 19:56:56 -0500 Subject: [PATCH 12/12] update README --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9ea45554..4e92e22b 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,12 @@ Currently PANNICC supports the following subset of C: - Pointers (just int***... for now) - Comments -Refer to the grammar in [parser.cpp](https://github.com/Golf0ned/PANNICC/blob/main/src/frontend/parser.cpp) for more specifics. +Refer to the grammar in [the parser](https://github.com/Golf0ned/PANNICC/tree/main/src/frontend/parser) for more specifics. ## Installation/Usage +This section assumes you are working in a unix environment. + Clone the repo: ``` @@ -36,12 +38,21 @@ To build and run tests, run: make ``` +To add to path, run: +``` +source enable +``` + To view the help message, run: ``` -./build/bin/pannicc +pannicc ``` +When writing programs for PANNICC, there are a few things to note: +- The subset of C supported is very limited (see [Language Support](https://github.com/Golf0ned/PANNICC/tree/main#language-support)) +- Since the C standard library uses a lot of features not yet supported by PANNICC, use the [runtime library](https://github.com/Golf0ned/PANNICC/blob/main/include/runtime.h) instead. + ## Contributing The best way to support this project is by [sponsoring me](https://github.com/sponsors/Golf0ned).