Skip to content
Merged

Ir #9

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions include/minic/IR.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#ifndef MINIC_IR_HPP
#define MINIC_IR_HPP

#include "AST.hpp"
#include <memory>
#include <string>
#include <vector>

namespace minic
{

/**
* @brief Intermediate Representation (IR) opcodes for miniC.
*
* Represents a compact set of operations used by the IR layer:
* arithmetic, comparisons, assignments, memory access, control flow, and labels.
*/
enum class IROpcode
{
ADD,
SUB,
MUL,
DIV, // Arithmetic
NEG,
NOT,
EQ,
NEQ,
LT,
GT,
LE,
GE, // Comparisons
ASSIGN, // Assignment
LOAD,
STORE, // Variable access
JUMP,
JUMPIF, // Control flow
JUMPIFNOT, // Control flow
RETURN, // Return
LABEL // Block label
};

/**
* @class IRInstruction
* @brief A single IR instruction.
*
* An IR instruction has an opcode and up to two operands plus an optional
* result (used for temporary variables or label names).
*/
class IRInstruction
{
public:
IROpcode opcode; ///< The opcode for this instruction
std::string result; ///< Destination (temp var or label)
std::string operand1; ///< First operand (or sole operand)
std::string operand2; ///< Second operand (for binary ops)

/**
* @brief Construct an IRInstruction.
* @param op The opcode.
* @param res Optional result name.
* @param op1 Optional first operand.
* @param op2 Optional second operand.
*/
IRInstruction(IROpcode op,
const std::string& res = {},
const std::string& op1 = {},
const std::string& op2 = {})
: opcode(op)
, result(res)
, operand1(op1)
, operand2(op2)
{
}
};

/**
* @class BasicBlock
* @brief A sequence of IR instructions with a label.
*
* Basic blocks group instructions and are the unit of control-flow in the IR.
*/
class BasicBlock
{
public:
std::string label; ///< Unique label for the block
std::vector<IRInstruction> instructions; ///< Instructions contained in the block

/**
* @brief Construct a BasicBlock with the given label.
* @param lbl The block label.
*/
explicit BasicBlock(const std::string& lbl)
: label(lbl)
{
}
};

/**
* @class IRFunction
* @brief Represents a function in the IR.
*
* Stores function name, return type, parameter list, and a sequence of basic blocks.
*/
class IRFunction
{
public:
std::string name; ///< Function name
TokenType return_type; ///< Function return type (from AST/Token)
std::vector<Parameter> parameters; ///< Function parameters
std::vector<std::unique_ptr<BasicBlock>> blocks; ///< Owned basic blocks

/**
* @brief Construct an IRFunction.
* @param n Function name.
* @param rt Return type.
* @param params Parameter list (moved).
*/
IRFunction(const std::string& n, TokenType rt, std::vector<Parameter> params)
: name(n)
, return_type(rt)
, parameters(std::move(params))
{
}
};

/**
* @class IRProgram
* @brief A container for all IR functions comprising the program.
*/
class IRProgram
{
public:
std::vector<std::unique_ptr<IRFunction>> functions; ///< Owned functions
};

} // namespace minic

#endif // MINIC_IR_HPP
126 changes: 126 additions & 0 deletions include/minic/IRGenerator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#ifndef MINIC_IR_GENERATOR_HPP
#define MINIC_IR_GENERATOR_HPP

#include "minic/ASTVisitor.hpp"
#include "minic/IR.hpp"
#include <map>
#include <memory>
#include <stdexcept>
#include <string>

namespace minic
{

/**
* @class IRGenerator
* @brief Generate Intermediate Representation (IR) from the AST.
*
* IRGenerator is an ASTVisitor that traverses the parsed AST and emits a
* sequence of IRFunction and BasicBlock objects inside an IRProgram.
* It maintains generation state such as the current function and block,
* temporary and label counters, and a mapping from source variable names to
* IR temporaries/variables.
*/
class IRGenerator : public ASTVisitor
{
public:
/**
* @brief Generate an IRProgram for the given AST program.
*
* Traverses the top-level Program node and produces a unique_ptr to an
* IRProgram containing one IRFunction per source function and the
* corresponding basic blocks and instructions.
*
* @param program AST root Program node.
* @return Owned IRProgram representing the compiled IR.
*/
std::unique_ptr<IRProgram> generate(const Program& program);

/**
* @brief Visit a Program node.
*
* Called during traversal of the AST's root program; responsible for
* visiting contained functions and populating the IRProgram.
*/
void visit(const Program& program) override;

/**
* @brief Visit a Function node.
*
* Creates a corresponding IRFunction, initializes entry BasicBlock(s),
* and emits IR for the function body.
*/
void visit(const Function& function) override;

/**
* @brief Visit a statement node.
*
* Emits IR instructions or control-flow modifications corresponding to
* the given statement.
*/
void visit(const Stmt& stmt) override;

/**
* @brief Visit an expression node.
*
* Evaluates the expression into IR by emitting necessary instructions and
* returning/recording temporaries via generate_expr.
*/
void visit(const Expr& expr) override;

private:
std::unique_ptr<IRProgram> ir_program_; ///< Owned IRProgram being built
IRFunction* current_function_ = nullptr; ///< Currently emitting function (non-owning)
BasicBlock* current_block_ = nullptr; ///< Currently emitting basic block (non-owning)
int temp_counter_ = 0; ///< Counter to generate unique temporary names
int label_counter_ = 0; ///< Counter to generate unique labels
std::map<std::string, std::string> var_map_; ///< Map from source var name to IR var/temp

/**
* @brief Create a fresh temporary variable name.
*
* Returns a unique temporary string (used as result names for instructions).
*/
std::string new_temp();

/**
* @brief Create a fresh label with the given prefix.
*
* Useful for generating basic block labels or branch targets.
*
* @param prefix Label prefix to make generated labels more readable.
*/
std::string new_label(const std::string& prefix);

/**
* @brief Emit an IR instruction into the current basic block.
*
* Convenience helper to append an IRInstruction with the supplied opcode
* and operands to the current_block_. If no current block is set, this
* function should handle that error state appropriately.
*
* @param op Opcode for the instruction.
* @param res Optional result destination (temp/variable/label).
* @param op1 Optional first operand.
* @param op2 Optional second operand.
*/
void emit(IROpcode op, const std::string& res = "", const std::string& op1 = "", const std::string& op2 = "");

/**
* @brief Generate IR for an expression and return its result name.
*
* Traverses the expression subtree, emits instructions to compute its
* value, and returns the name of the temporary or variable holding the
* computed value.
*
* @param expr Expression AST node to translate.
* @return Name of the IR temporary or variable that contains the result.
*/
std::string generate_expr(const Expr& expr); // Returns result temp/var

friend class PublicIRGenerator; // Allow testing class to access private members
};

} // namespace minic

#endif // MINIC_IR_GENERATOR_HPP
8 changes: 6 additions & 2 deletions include/minic/Parser.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#pragma once
#ifndef MINIC_PARSER_HPP
#define MINIC_PARSER_HPP

#include "AST.hpp"

/**
Expand Down Expand Up @@ -169,4 +171,6 @@ class Parser
friend class PublicParser; ///< Exposes internals for testing or controlled external access.
};

} // namespace minic
} // namespace minic

#endif // MINIC_PARSER_HPP
Loading