/* * par2serial-cc: ir.h - Three-address code Intermediate Representation * Designed for optimization passes: parallel detection, vectorization, tiling */ #ifndef P2S_IR_H #define P2S_IR_H #include "ast.h" /* ── IR Operation Codes ──────────────────────────────────── */ typedef enum { /* Arithmetic */ IR_ADD, IR_SUB, IR_MUL, IR_DIV, IR_MOD, IR_NEG, IR_FADD, IR_FSUB, IR_FMUL, IR_FDIV, /* float variants */ /* Bitwise */ IR_AND, IR_OR, IR_XOR, IR_NOT, IR_SHL, IR_SHR, /* Comparison */ IR_EQ, IR_NE, IR_LT, IR_GT, IR_LE, IR_GE, IR_FEQ, IR_FNE, IR_FLT, IR_FGT, IR_FLE, IR_FGE, /* Data movement */ IR_LOAD, /* dst = *src (memory load) */ IR_STORE, /* *dst = src (memory store) */ IR_MOVE, /* dst = src */ IR_LOAD_IMM, /* dst = immediate */ IR_LOAD_FIMM, /* dst = float immediate */ IR_LOAD_ADDR, /* dst = &var */ IR_INDEX, /* dst = base + idx * stride */ /* Control flow */ IR_LABEL, IR_JUMP, IR_BRANCH, /* if cond goto label */ IR_BRANCH_FALSE, /* if !cond goto label */ IR_CALL, /* dst = call func(args) */ IR_RET, /* return val */ /* Type conversion */ IR_INT_TO_FLOAT, IR_FLOAT_TO_INT, IR_WIDEN, /* sign/zero extend */ IR_NARROW, /* truncate */ /* Parallel constructs (high-level, lowered by optimization passes) */ IR_PAR_FOR_BEGIN, /* marks start of parallel for */ IR_PAR_FOR_END, /* marks end */ IR_PAR_REDUCE_BEGIN, /* marks start of reduction */ IR_PAR_REDUCE_END, IR_PAR_SCAN_BEGIN, IR_PAR_SCAN_END, IR_BARRIER, /* synchronization barrier */ IR_ATOMIC_ADD, /* atomic add */ /* SIMD operations (inserted by vectorization pass) */ IR_SIMD_LOAD, /* vdst = simd_load(addr) */ IR_SIMD_STORE, /* simd_store(addr, vsrc) */ IR_SIMD_BROADCAST, /* vdst = broadcast(scalar) */ IR_SIMD_ADD, /* vdst = vadd(va, vb) */ IR_SIMD_SUB, IR_SIMD_MUL, IR_SIMD_FMA, /* vdst = fma(va, vb, vc) */ IR_SIMD_HADD, /* horizontal add (reduction) */ IR_SIMD_MIN, IR_SIMD_MAX, /* Memory operations */ IR_PREFETCH, /* prefetch hint */ IR_ALLOCA, /* stack allocation */ /* Special */ IR_NOP, IR_PHI, /* SSA phi node */ IR_COMMENT, /* optimization annotation */ IR_OP_COUNT } IROp; /* ── IR Value (virtual register or constant) ─────────────── */ typedef enum { VAL_REG, /* virtual register %t0, %t1, ... */ VAL_INT, /* integer constant */ VAL_FLOAT, /* float constant */ VAL_LABEL, /* label reference */ VAL_NAME, /* named variable/function */ VAL_NONE, /* no value */ } IRValKind; typedef struct { IRValKind kind; union { int reg; /* register number */ int64_t int_val; double float_val; int label_id; const char *name; }; /* type info */ TypeKind type; /* data type of this value */ int simd_width; /* 0 = scalar, 4/8/16 = SIMD lanes */ } IRValue; /* ── IR Instruction ──────────────────────────────────────── */ typedef struct IRInst { IROp op; IRValue dst; /* destination */ IRValue src1; /* first operand */ IRValue src2; /* second operand */ IRValue src3; /* third operand (FMA, etc) */ SourceLoc loc; /* source location for diagnostics */ /* Parallel metadata */ struct { const char *iter_var; int lo_reg; /* register holding loop bound */ int hi_reg; int step_reg; ReduceOp reduce_op; int accum_reg; } par; /* Annotations */ const char *comment; int label_id; /* for IR_LABEL */ struct IRInst *next; struct IRInst *prev; } IRInst; VEC_TYPEDEF(IRInst*, IRInstVec); /* ── IR Basic Block ──────────────────────────────────────── */ typedef struct IRBlock { int id; const char *name; IRInstVec insts; struct IRBlock *next; /* linked list */ /* CFG edges */ struct IRBlock *succ[2]; /* successors (branch: [true, false]) */ struct IRBlock **preds; int pred_count; /* Loop info (filled by analysis) */ bool is_loop_header; int loop_depth; struct IRBlock *loop_latch; } IRBlock; VEC_TYPEDEF(IRBlock*, IRBlockVec); /* ── IR Function ─────────────────────────────────────────── */ typedef struct IRFunc { const char *name; IRBlockVec blocks; int reg_count; /* next register number */ int label_count; /* next label number */ int param_count; TypeKind return_type; struct IRFunc *next; } IRFunc; /* ── IR Module (compilation unit) ────────────────────────── */ typedef struct { Arena *arena; IRFunc *functions; /* linked list */ int func_count; /* Global declarations (passed through) */ NodeVec preproc_lines; /* #include, #define, etc */ NodeVec global_vars; /* global variable declarations */ } IRModule; /* ── IR Builder API ──────────────────────────────────────── */ IRModule *ir_module_create(Arena *arena); IRFunc *ir_func_create(IRModule *mod, const char *name); IRBlock *ir_block_create(IRFunc *func, const char *name); /* Value constructors */ IRValue ir_reg(int reg, TypeKind type); IRValue ir_int(int64_t val); IRValue ir_float(double val); IRValue ir_label(int id); IRValue ir_name(const char *name); IRValue ir_none(void); IRValue ir_simd_reg(int reg, TypeKind type, int width); /* Instruction emission */ int ir_new_reg(IRFunc *func); int ir_new_label(IRFunc *func); IRInst *ir_emit(Arena *arena, IRBlock *bb, IROp op, IRValue dst, IRValue src1, IRValue src2); IRInst *ir_emit_comment(Arena *arena, IRBlock *bb, const char *comment); /* AST → IR lowering */ IRModule *ir_build_from_ast(Arena *arena, ASTNode *program); /* IR printing */ void ir_print_module(IRModule *mod); void ir_print_value(IRValue v); const char *ir_op_name(IROp op); #endif /* P2S_IR_H */