Compare commits

..

7 Commits

@ -1,3 +1,4 @@
include_directories(${PROJECT_SOURCE_DIR}/src/antlr4)
cmake_minimum_required(VERSION 3.20)
project(compiler LANGUAGES C CXX)

@ -0,0 +1,34 @@
OUTPUT_DIR="test_outputs"
mkdir -p "$OUTPUT_DIR"
echo "=== 编译器功能测试 ==="
echo "结果将保存到 $OUTPUT_DIR/ 目录"
echo ""
for test in test/test_case/functional/*.sy; do
name=$(basename "$test" .sy)
echo "正在测试: $name"
# 检查是否有对应的输入文件
in_file="test/test_case/functional/${name}.in"
out_file="$OUTPUT_DIR/${name}.ll"
if [ -f "$in_file" ]; then
echo " 使用输入文件: $in_file"
echo " 输出保存到: $out_file"
echo ""
./build/bin/compiler --emit-ir "$test" < "$in_file" 2>&1 | tee "$out_file"
else
echo " 输出保存到: $out_file"
echo ""
./build/bin/compiler --emit-ir "$test" 2>&1 | tee "$out_file"
fi
echo ""
echo "--- 测试完成 ---"
echo ""
done
echo "所有测试完成!"
echo "查看结果: ls -la $OUTPUT_DIR/"

@ -0,0 +1,12 @@
## Lab1
# 1.构建
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=ON
cmake --build build -j "$(nproc)"
# 2.单例查看
./build/bin/compiler --emit-parse-tree test/test_case/functional/simple_add.sy
# 3.批量检查
find test/test_case -name '*.sy' | sort | while read f; do ./build/bin/compiler --emit-parse-tree "$f" >/dev/null || echo "FAIL $f"; done

@ -20,6 +20,8 @@ Lab2 的目标是在该示例基础上扩展语义覆盖范围,并逐步把更
- `include/sem/SymbolTable.h`
- `src/sem/Sema.cpp`
- `src/sem/SymbolTable.cpp`
- `include/ir/IR.h`
- `src/ir/Context.cpp`
- `src/ir/Value.cpp`

@ -0,0 +1,353 @@
# Lab2 小组协作修改方案(可直接执行)
## 1. 目标与现状
当前仓库的最小实现只能覆盖:
1. 局部 int 变量的 alloca/load/store。
2. 整数字面量、变量引用、加法表达式。
3. return 语句。
4. 单函数 main 的最小流程。
Lab2 的目标是把语法覆盖扩展到课程要求范围,并通过 IR 验证链路。
统一验收标准:
1. 能生成结构正确的 IR。
2. 通过脚本运行并和 .out 比对一致。
3. 最终覆盖 test/test_case 下应测样例。
---
## 2. 团队分工建议
建议至少拆成 4 条工作线并行推进。
### A. IR 基础设施组(你负责)
负责文件:
- include/ir/IR.h
- src/ir/Instruction.cpp
- src/ir/IRBuilder.cpp
- src/ir/Type.cpp
- src/ir/BasicBlock.cpp
- src/ir/Function.cpp
- src/ir/Module.cpp
- src/ir/IRPrinter.cpp
职责:
1. 补齐 IR 指令与构建接口(算术、比较、分支、调用、内存访问等)。
2. 保证基本块终结规则与 use-def 关系一致。
3. 保证 IRPrinter 输出格式可被 llc/clang 工具链接受。
### B. 语义分析组Sema
负责文件:
- include/sem/Sema.h
- include/sem/SymbolTable.h
- src/sem/Sema.cpp
- src/sem/SymbolTable.cpp
- src/sem/ConstEval.cpp
职责:
1. 名称绑定、作用域管理、重复定义与未定义检查。
2. 常量表达式求值与 const 相关约束。
3. 为 IRGen 提供稳定的绑定结果。
### C. IR 生成组IRGen
负责文件:
- include/irgen/IRGen.h
- src/irgen/IRGenFunc.cpp
- src/irgen/IRGenStmt.cpp
- src/irgen/IRGenExp.cpp
- src/irgen/IRGenDecl.cpp
- src/irgen/IRGenDriver.cpp
职责:
1. 按语法树节点生成 IR。
2. 正确构造控制流图if/while/break/continue
3. 正确处理函数定义、调用、参数、局部变量与数组访问。
### D. 测试与集成组
负责内容:
- 脚本化回归。
- 失败样例归因grammar/sema/irgen/ir/printer 哪层出错)。
- 每日合并后 smoke test。
---
## 3. 必须先对齐的接口约定(第一天完成)
这一步不做,后面会高频返工。
### 3.1 Sema -> IRGen 约定
1. 变量使用节点如何唯一绑定到声明节点。
2. 函数符号如何绑定(函数重名、参数信息、返回类型)。
3. 块作用域遮蔽规则:同名变量按最近作用域优先。
### 3.2 IRGen -> IRBuilder 约定
1. 每类语句/表达式映射到哪些构建接口。
2. 基本块终结规则ret/br 后禁止继续在同块插指令。
3. 比较和逻辑运算的返回类型与约定值。
4. 调用约定参数顺序、返回值处理、void 调用行为。
### 3.3 IR -> IRPrinter 约定
1. 新增指令的打印语法。
2. 类型打印规则int/float/ptr/array/function
3. 全局对象、函数声明与定义的输出顺序。
### 3.4 IR 第一版接口清单(函数名级别,建议 Day1 冻结)
这份清单用于你先做 src/ir其他同学按接口跟随开发。
第一批只覆盖 M1 到 M3 的最小闭环M4 和 M5 另开第二版接口。
1. 当前已存在并继续保留
- IRBuilder.CreateConstInt(int v)
- IRBuilder.CreateBinary(Opcode op, Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateAdd(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateAllocaI32(const std::string& name)
- IRBuilder.CreateLoad(Value* ptr, const std::string& name)
- IRBuilder.CreateStore(Value* val, Value* ptr)
- IRBuilder.CreateRet(Value* v)
2. 第一版必须新增M1
- Opcode 扩展Div、Mod
- IRBuilder.CreateSub(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateMul(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateDiv(Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateMod(Value* lhs, Value* rhs, const std::string& name)
- 一元负号先复用 CreateSub(0, x)
- 一元逻辑非先复用比较接口(见下一条)
3. 第一版建议新增M1 到 M3
- CmpOp 枚举Eq、Ne、Lt、Le、Gt、Ge
- IRBuilder.CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name)
- IRBuilder.CreateBr(BasicBlock* target)
- IRBuilder.CreateCondBr(Value* cond, BasicBlock* true_bb, BasicBlock* false_bb)
4. 第二版预留M2
- IRBuilder.CreateCall(Function* callee, const std::vector<Value*>& args, const std::string& name)
- Function 需要完整函数签名表示(返回类型 + 形参类型)
5. 基本块终结规则(第一版必须执行)
1. terminator 指令包含 Ret、Br、CondBr。
2. BasicBlock 一旦出现 terminator禁止继续追加普通指令。
3. IRGen 负责在新块上重新设置插入点。
6. 参数与类型约定(第一版)
1. M1 到 M3 阶段先统一为 i32 值语义。
2. cond 分支条件统一约定为 i320 为假,非 0 为真。
3. CreateBinary 输入输出类型必须一致;不一致直接报错。
7. 打印约定IRPrinter 第一版)
1. Sub、Mul、Div、Mod、比较、Br、CondBr、Call 必须同步可打印。
2. 新增指令的打印格式由 IR 组给出单页示例IRGen 组按示例比对。
8. 接口冻结与变更流程
1. Day1 晚上冻结第一版接口,不再改函数签名。
2. Day2 到 Day3 只允许修实现 bug不改接口名字和参数。
3. 必须改接口时,提前半天发迁移说明并提供一条替代写法。
---
## 4. 分阶段里程碑(按功能从低风险到高风险)
## M1整数基础表达式与赋值
目标样例:
- test/test_case/functional/simple_add.sy
- test/test_case/functional/11_add2.sy
- test/test_case/functional/13_sub2.sy
- test/test_case/functional/36_op_priority2.sy
完成定义:
1. 支持赋值语句。
2. 支持一元 + - !。
3. 支持二元 + - * / %。
4. 支持比较表达式的语义与 IR 生成。
## M2函数与作用域
目标样例:
- test/test_case/functional/09_func_defn.sy
- test/test_case/functional/25_scope3.sy
完成定义:
1. 多函数定义。
2. 参数传递与函数调用。
3. 块级作用域与变量遮蔽正确。
## M3控制流
目标样例:
- test/test_case/functional/29_break.sy
完成定义:
1. if/else。
2. while。
3. break/continue循环栈管理
## M4数组与全局对象
目标样例:
- test/test_case/functional/05_arr_defn4.sy
- test/test_case/functional/22_matrix_multiply.sy
完成定义:
1. 数组定义、初始化与下标访问。
2. 全局变量/常量。
3. constExp 维度与初始化相关检查。
## M5浮点若课程阶段要求
目标样例:
- test/test_case/functional/95_float.sy
完成定义:
1. float 类型与常量。
2. int/float 隐式转换。
3. float 运算、比较、控制流条件。
---
## 5. 你负责的 src/ir 详细任务清单
建议按下面顺序提交,每次只做一类能力,便于联调。
### T1. 指令枚举和 IRBuilder 基础扩展
1. 补齐一元/二元整数运算。
2. 补齐比较与条件分支指令。
3. 提供统一的 CreateBinary、CreateCmp、CreateBr、CreateCondBr、CreateCall。
### T2. 基本块与终结指令约束
1. BasicBlock 显式记录 terminator。
2. 插入终结指令后拒绝继续插普通指令。
3. Function 级别提供校验接口(可用于 debug 断言)。
### T3. 类型与函数签名表达
1. 类型系统支持函数参数和返回类型表达。
2. 调用点参数个数与签名一致性检查(至少 debug 模式可查)。
### T4. IRPrinter 同步
1. 新增指令全部可打印。
2. 打印结果可通过 llc。
3. 保证测试输出稳定(避免不必要随机命名波动)。
### T5. 数组与地址计算(如果 M4 开启)
1. 元素地址计算接口。
2. 多维下标线性化或 GEP 风格接口。
---
## 6. 每日协作机制(必须执行)
1. 每天固定 15 分钟站会:同步昨天完成、今天计划、阻塞点。
2. 每个接口变更先发讨论再改,避免主干反复冲突。
3. 每个里程碑前冻结接口半天,只做修 bug 和联调。
推荐沟通模板:
1. 我改了什么接口。
2. 旧行为与新行为差异。
3. 受影响文件。
4. 调用方需要同步的改动。
5. 最晚切换时间点。
---
## 7. 分支与提交流程
1. 一人一功能分支,不直接在主分支开发。
2. 提交粒度小而清晰:一个提交只解决一类问题。
3. 提交信息建议feat(ir), fix(irgen), fix(sema), test(lab2)。
4. 合并前必须附上通过样例列表。
---
## 8. 统一验证命令
构建:
```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=OFF
cmake --build build -j "$(nproc)"
```
单样例验证:
```bash
./scripts/verify_ir.sh test/test_case/functional/simple_add.sy test/test_result/function/ir --run
```
功能样例批量验证:
```bash
for f in test/test_case/functional/*.sy; do
echo "== $f =="
./scripts/verify_ir.sh "$f" test/test_result/function/ir --run || break
done
```
---
## 9. 风险与应对
1. 风险grammar 变更导致 visitor 接口失配。
应对:变更 grammar 后第一时间重新生成 ANTLR 文件并通知 Sema/IRGen。
2. 风险IRPrinter 语法偏差导致 llc 失败。
应对:新增指令时同步补打印和最小样例回归。
3. 风险:组员并行修改同一接口冲突严重。
应对:接口 owner 机制IR 接口由 IR 组最终拍板。
4. 风险:只测 simple_add阶段性误判成功。
应对:每个里程碑绑定指定样例集,全部通过才进入下一阶段。
---
## 10. 本周可执行排期(示例)
1. Day1接口对齐会完成 M1 任务拆分。
2. Day2IR 组完成 T1/T2Sema/IRGen 同步接入。
3. Day3打通 M1 全样例。
4. Day4推进 M2函数与作用域
5. Day5推进 M3控制流并做一次集成回归。
如果进度顺利,再进入 M4数组与全局

@ -0,0 +1,108 @@
我先快速读取当前 IRGen 的入口与表达式/语句文件,然后按“节点到接口调用映射”给你一份可以直接交给 IRGen 同学实现的调用说明。
Read [](file:///home/shrink/nudt-compiler-cpp/include/ir/IR.h#320-320), lines 320 to 387
Read [](file:///home/shrink/nudt-compiler-cpp/include/irgen/IRGen.h)
Read [](file:///home/shrink/nudt-compiler-cpp/src/irgen/IRGenExp.cpp)
Read [](file:///home/shrink/nudt-compiler-cpp/src/irgen/IRGenStmt.cpp)
Read [](file:///home/shrink/nudt-compiler-cpp/src/irgen/IRGenFunc.cpp)
可以,下面给你一份面向 IRGen 同学的“如何调用你新增 IR 接口”的实现说明,按落地顺序写。
先看调用边界
1. IRGen 只负责把语法树翻译成 IR不做符号查找
变量和函数绑定依赖 Sema 结果,参考 IRGenExp.cpp 的变量读取流程。
2. 所有指令创建都通过 IRBuilder
新增接口定义在 IR.h。
3. 终结指令规则必须遵守
Ret/Br/CondBr 一旦插入当前块,这个块不能再插普通指令,规则在 Instruction.cpp 和 BasicBlock.cpp。
建议 IRGen 调用映射
一、表达式层
1. 加减乘除模
- a + b: CreateAdd(lhs, rhs, temp)
- a - b: CreateSub(lhs, rhs, temp)
- a * b: CreateMul(lhs, rhs, temp)
- a / b: CreateDiv(lhs, rhs, temp)
- a % b: CreateMod(lhs, rhs, temp)
2. 比较表达式
- == != < <= > >= 统一走 CreateCmp(op, lhs, rhs, temp)
- 返回 i32约定 0 为假,非 0 为真
3. 一元运算建议
- -x: CreateSub(const0, x, temp)
- !x: CreateCmp(Eq, x, const0, temp)
- +x: 直接返回 x
4. 变量读取和赋值
- 读取: 先由 Sema 绑定 use 到 decl再从 storage_map 找槽位CreateLoad
- 赋值: EvalExpr(rhs) 后对槽位 CreateStore(rhs_val, slot)
对应修改文件:
- IRGenExp.cpp
- IRGenDecl.cpp
- IRGenStmt.cpp
二、控制流层
1. if/else
- 创建三个块: then, else, merge
- cond = EvalExpr(condExp)
- 当前块插 CreateCondBr(cond, then, else)
- 切入 then 块生成语句,末尾若未终结则 CreateBr(merge)
- 切入 else 块同理
- 最后 SetInsertPoint(merge)
2. while
- 创建三个块: cond, body, exit
- 进入前先 CreateBr(cond)
- cond 块计算条件CreateCondBr(cond_val, body, exit)
- body 块生成循环体,若未终结则回跳 CreateBr(cond)
- 最后 SetInsertPoint(exit)
3. break/continue
- IRGen 维护循环栈,每层保存 continue_target 和 break_target
- break 直接 CreateBr(break_target)
- continue 直接 CreateBr(continue_target)
对应修改文件:
- IRGenStmt.cpp
三、函数与调用层
1. 函数定义
- 用 Module.CreateFunction(name, ret_type, param_types) 建函数
- 入口块 SetInsertPoint(entry)
- 形参落栈策略建议:每个参数先 alloca再 store 到本地槽位,后续统一按 load/store 访问
2. 函数调用
- 先拿到 callee 对应的 Function
- 实参逐个 EvalExpr 得到 args
- 调用 CreateCall(callee, args, temp)
- 若返回值非 void把返回 Value 继续参与表达式计算
对应修改文件:
- IRGenFunc.cpp
- IRGenExp.cpp
四、你要提醒 IRGen 同学的两个关键点
1. 插入点管理
每次生成 Br/CondBr/Ret 后,必须切换到新块再继续生成。否则会触发块已终结错误。
2. grammar 上下文名先对齐
你们当前 IRGen 里还在用 ParenExpContext、AdditiveExpContext 这类命名,实际 grammar 是另一套层级时要先改 Visitor 入口,否则接口再全也接不上。可先核对 SysY.g4 与 IRGen.h。
最小接入顺序
1. 先接表达式算术与比较M1
2. 再接 if/while/break/continueM3
3. 再接函数参数和调用M2
如果你要,我下一步可以给你一版“按当前 grammar 的具体 visitor 函数名”逐条对照表IRGen 同学可以直接照着改函数签名和调用点。

@ -4,8 +4,8 @@
#include <memory>
#include <string>
#include "SysYLexer.h"
#include "SysYParser.h"
#include "antlr4/SysYLexer.h"
#include "antlr4/SysYParser.h"
#include "antlr4-runtime.h"
struct AntlrResult {

@ -151,8 +151,24 @@ class ConstantInt : public ConstantValue {
int value_{};
};
// 后续还需要扩展更多指令类型。
enum class Opcode { Add, Sub, Mul, Alloca, Load, Store, Ret };
// 第一版 Lab2 需要的指令集合。
enum class Opcode {
Add,
Sub,
Mul,
Div,
Mod,
Cmp,
Br,
CondBr,
Call,
Alloca,
Load,
Store,
Ret,
};
enum class CmpOp { Eq, Ne, Lt, Le, Gt, Ge };
// User 是所有“会使用其他 Value 作为输入”的 IR 对象的抽象基类。
// 当前实现中只有 Instruction 继承自 User。
@ -196,7 +212,19 @@ class BinaryInst : public Instruction {
BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs,
std::string name);
Value* GetLhs() const;
Value* GetRhs() const;
Value* GetRhs() const;
};
class CmpInst : public Instruction {
public:
CmpInst(CmpOp op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs,
std::string name);
CmpOp GetCmpOp() const;
Value* GetLhs() const;
Value* GetRhs() const;
private:
CmpOp cmp_op_;
};
class ReturnInst : public Instruction {
@ -223,6 +251,30 @@ class StoreInst : public Instruction {
Value* GetPtr() const;
};
class BranchInst : public Instruction {
public:
BranchInst(std::shared_ptr<Type> void_ty, BasicBlock* target);
BasicBlock* GetTarget() const;
};
class CondBranchInst : public Instruction {
public:
CondBranchInst(std::shared_ptr<Type> void_ty, Value* cond,
BasicBlock* true_bb, BasicBlock* false_bb);
Value* GetCond() const;
BasicBlock* GetTrueBlock() const;
BasicBlock* GetFalseBlock() const;
};
class CallInst : public Instruction {
public:
CallInst(std::shared_ptr<Type> ret_ty, Function* callee,
std::vector<Value*> args, std::string name);
Function* GetCallee() const;
size_t GetNumArgs() const;
Value* GetArg(size_t index) const;
};
// BasicBlock 已纳入 Value 体系,便于后续向更完整 IR 类图靠拢。
// 当前其类型仍使用 void 作为占位,后续可替换为专门的 label type。
class BasicBlock : public Value {
@ -234,6 +286,8 @@ class BasicBlock : public Value {
const std::vector<std::unique_ptr<Instruction>>& GetInstructions() const;
const std::vector<BasicBlock*>& GetPredecessors() const;
const std::vector<BasicBlock*>& GetSuccessors() const;
void AddPredecessor(BasicBlock* pred);
void AddSuccessor(BasicBlock* succ);
template <typename T, typename... Args>
T* Append(Args&&... args) {
if (HasTerminator()) {
@ -262,15 +316,18 @@ class BasicBlock : public Value {
// 形参和调用,通常需要引入专门的函数类型表示。
class Function : public Value {
public:
// 当前构造函数接收的也是返回类型,而不是完整函数类型。
Function(std::string name, std::shared_ptr<Type> ret_type);
Function(std::string name, std::shared_ptr<Type> ret_type,
std::vector<std::shared_ptr<Type>> param_types = {});
BasicBlock* CreateBlock(const std::string& name);
BasicBlock* GetEntry();
const BasicBlock* GetEntry() const;
const std::vector<std::shared_ptr<Type>>& GetParamTypes() const;
size_t GetNumParams() const;
const std::vector<std::unique_ptr<BasicBlock>>& GetBlocks() const;
private:
BasicBlock* entry_ = nullptr;
std::vector<std::shared_ptr<Type>> param_types_;
std::vector<std::unique_ptr<BasicBlock>> blocks_;
};
@ -281,7 +338,8 @@ class Module {
const Context& GetContext() const;
// 创建函数时当前只显式传入返回类型,尚未接入完整的 FunctionType。
Function* CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type);
std::shared_ptr<Type> ret_type,
std::vector<std::shared_ptr<Type>> param_types = {});
const std::vector<std::unique_ptr<Function>>& GetFunctions() const;
private:
@ -300,9 +358,19 @@ class IRBuilder {
BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs,
const std::string& name);
BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateSub(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateMul(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateDiv(Value* lhs, Value* rhs, const std::string& name);
BinaryInst* CreateMod(Value* lhs, Value* rhs, const std::string& name);
CmpInst* CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name);
AllocaInst* CreateAllocaI32(const std::string& name);
LoadInst* CreateLoad(Value* ptr, const std::string& name);
StoreInst* CreateStore(Value* val, Value* ptr);
BranchInst* CreateBr(BasicBlock* target);
CondBranchInst* CreateCondBr(Value* cond, BasicBlock* true_bb,
BasicBlock* false_bb);
CallInst* CreateCall(Function* callee, const std::vector<Value*>& args,
const std::string& name);
ReturnInst* CreateRet(Value* v);
private:

@ -6,13 +6,18 @@
#include <any>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
#include "SysYBaseVisitor.h"
#include "SysYParser.h"
#include "antlr4/SysYBaseVisitor.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "sem/Sema.h"
// 前向声明:语义层可能在未来提供更明确的符号类型,用于把符号唯一标识映射到 IR 对象。
struct SemanticVarSymbol;
struct SemanticFuncSymbol;
namespace ir {
class Module;
class Function;
@ -29,13 +34,26 @@ class IRGenImpl final : public SysYBaseVisitor {
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override;
std::any visitStmt(SysYParser::StmtContext* ctx) override;
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
std::any visitParenExp(SysYParser::ParenExpContext* ctx) override;
std::any visitNumberExp(SysYParser::NumberExpContext* ctx) override;
std::any visitVarExp(SysYParser::VarExpContext* ctx) override;
std::any visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) override;
std::any visitExp(SysYParser::ExpContext* ctx) override;
std::any visitCond(SysYParser::CondContext* ctx) override;
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
std::any visitNumber(SysYParser::NumberContext* ctx) override;
std::any visitLValue(SysYParser::LValueContext* ctx) override;
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override;
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
// 辅助接口:数组下标地址计算与全局变量生成
ir::Value* EmitArrayIndex(ir::Value* base_ptr, SysYParser::ExpContext* idx_expr);
void EmitGlobalVariable(SysYParser::VarDefContext* ctx);
private:
enum class BlockFlow {
@ -43,15 +61,39 @@ class IRGenImpl final : public SysYBaseVisitor {
Terminated,
};
struct LoopTargets {
ir::BasicBlock* continue_target;
ir::BasicBlock* break_target;
};
BlockFlow VisitBlockItemResult(SysYParser::BlockItemContext& item);
ir::Value* EvalExpr(SysYParser::ExpContext& expr);
ir::Value* EvalCond(SysYParser::CondContext& cond);
ir::Value* ToBoolValue(ir::Value* v);
ir::Value* FindInScope(const std::string& name);
std::string NextBlockName();
ir::Function* FindFunctionByName(const std::string& name);
ir::Value* ResolveLValueAddress(SysYParser::LValueContext* ctx);
ir::Module& module_;
const SemanticContext& sema_;
ir::Function* func_;
ir::IRBuilder builder_;
bool in_function_ = false;
// 当前函数的参数对应的栈槽位(在函数入口处为每个形参分配的 alloca
std::vector<ir::Value*> param_slots_;
// 将 Sema 提供的变量符号映射到对应的存储槽位(避免仅按名字查找)
std::unordered_map<const SemanticVarSymbol*, ir::Value*> symbol_storage_map_;
// 将 Sema 提供的函数符号映射到已创建的 IR 函数对象
std::unordered_map<const SemanticFuncSymbol*, ir::Function*> func_symbol_map_;
// 作用域栈:每个作用域维护一个从名称到存储槽位的映射
std::vector<std::unordered_map<std::string, ir::Value*>> scope_storage_;
// 名称绑定由 Sema 负责IRGen 只维护“声明 -> 存储槽位”的代码生成状态。
std::unordered_map<SysYParser::VarDefContext*, ir::Value*> storage_map_;
// 保留按名字的映射以兼容现有代码路径,但优先使用 symbol_storage_map_
std::unordered_map<std::string, ir::Value*> named_storage_;
std::vector<LoopTargets> loop_stack_;
};
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,

@ -1,30 +1,213 @@
// 基于语法树的语义检查与名称绑定。
#pragma once
#ifndef SEMANTIC_ANALYSIS_H
#define SEMANTIC_ANALYSIS_H
#include "SymbolTable.h"
#include "antlr4/SysYBaseVisitor.h"
#include "antlr4/SysYParser.h"
#include <vector>
#include <string>
#include <sstream>
#include <unordered_map>
#include <any>
#include <memory>
#include "SysYParser.h"
// 错误信息结构体
struct ErrorMsg {
std::string msg;
int line;
int column;
ErrorMsg(std::string m, int l, int c) : msg(std::move(m)), line(l), column(c) {}
};
// 前向声明
namespace antlr4 {
class ParserRuleContext;
namespace tree {
class ParseTree;
}
}
// 语义/IR生成上下文核心类
class IRGenContext {
public:
// 错误管理
void RecordError(const ErrorMsg& err) { errors_.push_back(err); }
const std::vector<ErrorMsg>& GetErrors() const { return errors_; }
bool HasError() const { return !errors_.empty(); }
void ClearErrors() { errors_.clear(); }
// 类型绑定/查询 - 使用 void* 以兼容测试代码
void SetType(void* ctx, SymbolType type) {
node_type_map_[ctx] = type;
}
SymbolType GetType(void* ctx) const {
auto it = node_type_map_.find(ctx);
return it == node_type_map_.end() ? SymbolType::TYPE_UNKNOWN : it->second;
}
// 常量值绑定/查询 - 使用 void* 以兼容测试代码
void SetConstVal(void* ctx, const std::any& val) {
const_val_map_[ctx] = val;
}
std::any GetConstVal(void* ctx) const {
auto it = const_val_map_.find(ctx);
return it == const_val_map_.end() ? std::any() : it->second;
}
// 循环状态管理
void EnterLoop() { sym_table_.EnterLoop(); }
void ExitLoop() { sym_table_.ExitLoop(); }
bool InLoop() const { return sym_table_.InLoop(); }
// 类型判断工具函数
bool IsIntType(const std::any& val) const {
return val.type() == typeid(long) || val.type() == typeid(int);
}
bool IsFloatType(const std::any& val) const {
return val.type() == typeid(double) || val.type() == typeid(float);
}
// 当前函数返回类型
SymbolType GetCurrentFuncReturnType() const {
return current_func_ret_type_;
}
void SetCurrentFuncReturnType(SymbolType type) {
current_func_ret_type_ = type;
}
// 符号表访问
SymbolTable& GetSymbolTable() { return sym_table_; }
const SymbolTable& GetSymbolTable() const { return sym_table_; }
// 作用域管理
void EnterScope() { sym_table_.EnterScope(); }
void LeaveScope() { sym_table_.LeaveScope(); }
size_t GetScopeDepth() const { return sym_table_.GetScopeDepth(); }
private:
SymbolTable sym_table_;
std::unordered_map<void*, SymbolType> node_type_map_;
std::unordered_map<void*, std::any> const_val_map_;
std::vector<ErrorMsg> errors_;
SymbolType current_func_ret_type_ = SymbolType::TYPE_UNKNOWN;
};
// 与现有 IRGen/主流程保持兼容的语义上下文占位。
class SemanticContext {
public:
void BindVarUse(SysYParser::VarContext* use,
SysYParser::VarDefContext* decl) {
var_uses_[use] = decl;
}
void BindVarUse(const SysYParser::LValueContext* use,
SysYParser::VarDefContext* decl) {
var_uses_[use] = decl;
}
SysYParser::VarDefContext* ResolveVarUse(
const SysYParser::VarContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
SysYParser::VarDefContext* ResolveVarUse(
const SysYParser::LValueContext* use) const {
auto it = var_uses_.find(use);
return it == var_uses_.end() ? nullptr : it->second;
}
private:
std::unordered_map<const SysYParser::VarContext*,
SysYParser::VarDefContext*>
var_uses_;
std::unordered_map<const SysYParser::LValueContext*,
SysYParser::VarDefContext*>
var_uses_;
};
// 错误信息格式化工具函数
inline std::string FormatErrMsg(const std::string& msg, int line, int col) {
std::ostringstream oss;
oss << "[行:" << line << ",列:" << col << "] " << msg;
return oss.str();
}
// 语义分析访问器 - 继承自生成的基类
class SemaVisitor : public SysYBaseVisitor {
public:
explicit SemaVisitor(IRGenContext& ctx) : ir_ctx_(ctx) {}
// 必须实现的 ANTLR4 接口
std::any visit(antlr4::tree::ParseTree* tree) override {
if (tree) {
return tree->accept(this);
}
return std::any();
}
std::any visitTerminal(antlr4::tree::TerminalNode* node) override {
return std::any();
}
std::any visitErrorNode(antlr4::tree::ErrorNode* node) override {
if (node) {
int line = node->getSymbol()->getLine();
int col = node->getSymbol()->getCharPositionInLine() + 1;
ir_ctx_.RecordError(ErrorMsg("语法错误节点", line, col));
}
return std::any();
}
// 核心访问方法
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
std::any visitDecl(SysYParser::DeclContext* ctx) override;
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override;
std::any visitBtype(SysYParser::BtypeContext* ctx) override;
std::any visitConstDef(SysYParser::ConstDefContext* ctx) override;
std::any visitConstInitValue(SysYParser::ConstInitValueContext* ctx) override;
std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override;
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
std::any visitInitValue(SysYParser::InitValueContext* ctx) override;
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
std::any visitFuncType(SysYParser::FuncTypeContext* ctx) override;
std::any visitFuncFParams(SysYParser::FuncFParamsContext* ctx) override;
std::any visitFuncFParam(SysYParser::FuncFParamContext* ctx) override;
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override;
std::any visitStmt(SysYParser::StmtContext* ctx) override;
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
std::any visitExp(SysYParser::ExpContext* ctx) override;
std::any visitCond(SysYParser::CondContext* ctx) override;
std::any visitLValue(SysYParser::LValueContext* ctx) override;
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
std::any visitNumber(SysYParser::NumberContext* ctx) override;
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override;
std::any visitUnaryOp(SysYParser::UnaryOpContext* ctx) override;
std::any visitFuncRParams(SysYParser::FuncRParamsContext* ctx) override;
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
std::any visitConstExp(SysYParser::ConstExpContext* ctx) override;
// 通用子节点访问
std::any visitChildren(antlr4::tree::ParseTree* node) override {
std::any result;
if (node) {
for (auto* child : node->children) {
if (child) {
result = child->accept(this);
}
}
}
return result;
}
// 获取上下文引用
IRGenContext& GetContext() { return ir_ctx_; }
const IRGenContext& GetContext() const { return ir_ctx_; }
private:
IRGenContext& ir_ctx_;
};
// 目前仅检查:
// - 变量先声明后使用
// - 局部变量不允许重复定义
// 语义分析入口函数
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx);
// 兼容旧流程入口。
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
#endif // SEMANTIC_ANALYSIS_H

@ -1,17 +1,201 @@
// 极简符号表:记录局部变量定义点。
#pragma once
#ifndef SYMBOL_TABLE_H
#define SYMBOL_TABLE_H
#include <any>
#include <string>
#include <vector>
#include <unordered_map>
#include <stack>
#include <utility>
#include "SysYParser.h"
// 核心类型枚举
enum class SymbolType {
TYPE_UNKNOWN, // 未知类型
TYPE_INT, // 整型
TYPE_FLOAT, // 浮点型
TYPE_VOID, // 空类型
TYPE_ARRAY, // 数组类型
TYPE_FUNCTION // 函数类型
};
// 获取类型名称字符串
inline const char* SymbolTypeToString(SymbolType type) {
switch (type) {
case SymbolType::TYPE_INT: return "int";
case SymbolType::TYPE_FLOAT: return "float";
case SymbolType::TYPE_VOID: return "void";
case SymbolType::TYPE_ARRAY: return "array";
case SymbolType::TYPE_FUNCTION: return "function";
default: return "unknown";
}
}
// 变量信息结构体
struct VarInfo {
SymbolType type = SymbolType::TYPE_UNKNOWN;
bool is_const = false;
std::any const_val;
std::vector<int> array_dims; // 数组维度,空表示非数组
void* decl_ctx = nullptr; // 关联的语法节点
// 检查是否为数组类型
bool IsArray() const { return !array_dims.empty(); }
// 获取数组元素总数
int GetArrayElementCount() const {
int count = 1;
for (int dim : array_dims) {
count *= dim;
}
return count;
}
};
// 函数信息结构体
struct FuncInfo {
SymbolType ret_type = SymbolType::TYPE_UNKNOWN;
std::string name;
std::vector<SymbolType> param_types; // 参数类型列表
void* decl_ctx = nullptr; // 关联的语法节点
// 检查参数匹配
bool CheckParams(const std::vector<SymbolType>& actual_params) const {
if (actual_params.size() != param_types.size()) {
return false;
}
for (size_t i = 0; i < param_types.size(); ++i) {
if (param_types[i] != actual_params[i] &&
param_types[i] != SymbolType::TYPE_UNKNOWN &&
actual_params[i] != SymbolType::TYPE_UNKNOWN) {
return false;
}
}
return true;
}
};
// 作用域条目结构体
struct ScopeEntry {
// 变量符号表:符号名 -> (符号信息, 声明节点)
std::unordered_map<std::string, std::pair<VarInfo, void*>> var_symbols;
// 函数符号表:符号名 -> (函数信息, 声明节点)
std::unordered_map<std::string, std::pair<FuncInfo, void*>> func_symbols;
// 清空作用域
void Clear() {
var_symbols.clear();
func_symbols.clear();
}
};
// 符号表核心类
class SymbolTable {
public:
void Add(const std::string& name, SysYParser::VarDefContext* decl);
bool Contains(const std::string& name) const;
SysYParser::VarDefContext* Lookup(const std::string& name) const;
public:
// ========== 作用域管理 ==========
// 进入新作用域
void EnterScope();
// 离开当前作用域
void LeaveScope();
// 获取当前作用域深度
size_t GetScopeDepth() const { return scopes_.size(); }
// 检查作用域栈是否为空
bool IsEmpty() const { return scopes_.empty(); }
// ========== 变量符号管理 ==========
// 检查当前作用域是否包含指定变量
bool CurrentScopeHasVar(const std::string& name) const;
// 绑定变量到当前作用域
void BindVar(const std::string& name, const VarInfo& info, void* decl_ctx);
// 查找变量(从当前作用域向上遍历)
bool LookupVar(const std::string& name, VarInfo& out_info, void*& out_decl_ctx) const;
// 快速查找变量(不获取详细信息)
bool HasVar(const std::string& name) const {
VarInfo info;
void* ctx;
return LookupVar(name, info, ctx);
}
// ========== 函数符号管理 ==========
// 检查当前作用域是否包含指定函数
bool CurrentScopeHasFunc(const std::string& name) const;
// 绑定函数到当前作用域
void BindFunc(const std::string& name, const FuncInfo& info, void* decl_ctx);
// 查找函数(从当前作用域向上遍历)
bool LookupFunc(const std::string& name, FuncInfo& out_info, void*& out_decl_ctx) const;
// 快速查找函数(不获取详细信息)
bool HasFunc(const std::string& name) const {
FuncInfo info;
void* ctx;
return LookupFunc(name, info, ctx);
}
// ========== 循环状态管理 ==========
// 进入循环
void EnterLoop();
// 离开循环
void ExitLoop();
// 检查是否在循环内
bool InLoop() const;
// 获取循环嵌套深度
int GetLoopDepth() const { return loop_depth_; }
// ========== 辅助功能 ==========
// 清空所有作用域和状态
void Clear();
// 获取当前作用域中所有变量名
std::vector<std::string> GetCurrentScopeVarNames() const;
// 获取当前作用域中所有函数名
std::vector<std::string> GetCurrentScopeFuncNames() const;
// 调试:打印符号表内容
void Dump() const;
private:
std::unordered_map<std::string, SysYParser::VarDefContext*> table_;
private:
// 作用域栈
std::stack<ScopeEntry> scopes_;
// 循环嵌套深度
int loop_depth_ = 0;
};
// 类型兼容性检查函数
inline bool IsTypeCompatible(SymbolType expected, SymbolType actual) {
if (expected == SymbolType::TYPE_UNKNOWN || actual == SymbolType::TYPE_UNKNOWN) {
return true; // 未知类型视为兼容
}
// 基本类型兼容规则
if (expected == actual) {
return true;
}
// int 可以隐式转换为 float
if (expected == SymbolType::TYPE_FLOAT && actual == SymbolType::TYPE_INT) {
return true;
}
return false;
}
#endif // SYMBOL_TABLE_H

6
node_modules/.package-lock.json generated vendored

@ -0,0 +1,6 @@
{
"name": "nudt-compiler-cpp",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,3 @@
This project is dual-licensed under the Unlicense and MIT licenses.
You may use this code under the terms of either license.

@ -0,0 +1,46 @@
# `@img/sharp-libvips-linux-x64`
Prebuilt libvips and dependencies for use with sharp on Linux (glibc) x64.
## Licensing
This software contains third-party libraries
used under the terms of the following licences:
| Library | Used under the terms of |
|---------------|-----------------------------------------------------------------------------------------------------------|
| aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
| cairo | Mozilla Public License 2.0 |
| cgif | MIT Licence |
| expat | MIT Licence |
| fontconfig | [fontconfig Licence](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
| freetype | [freetype Licence](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
| fribidi | LGPLv3 |
| glib | LGPLv3 |
| harfbuzz | MIT Licence |
| highway | Apache-2.0 License, BSD 3-Clause |
| lcms | MIT Licence |
| libarchive | BSD 2-Clause |
| libexif | LGPLv3 |
| libffi | MIT Licence |
| libheif | LGPLv3 |
| libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
| libnsgif | MIT Licence |
| libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
| librsvg | LGPLv3 |
| libspng | [BSD 2-Clause, libpng License](https://github.com/randy408/libspng/blob/master/LICENSE) |
| libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
| libvips | LGPLv3 |
| libwebp | New BSD License |
| libxml2 | MIT Licence |
| mozjpeg | [zlib License, IJG License, BSD-3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
| pango | LGPLv3 |
| pixman | MIT Licence |
| proxy-libintl | LGPLv3 |
| zlib-ng | [zlib Licence](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
Use of libraries under the terms of the LGPLv3 is via the
"any later version" clause of the LGPLv2 or LGPLv2.1.
Please report any errors or omissions via
https://github.com/lovell/sharp-libvips/issues/new

@ -0,0 +1,221 @@
/* glibconfig.h
*
* This is a generated file. Please modify 'glibconfig.h.in'
*/
#ifndef __GLIBCONFIG_H__
#define __GLIBCONFIG_H__
#include <glib/gmacros.h>
#include <limits.h>
#include <float.h>
#define GLIB_HAVE_ALLOCA_H
#define GLIB_STATIC_COMPILATION 1
#define GOBJECT_STATIC_COMPILATION 1
#define GIO_STATIC_COMPILATION 1
#define GMODULE_STATIC_COMPILATION 1
#define GI_STATIC_COMPILATION 1
#define G_INTL_STATIC_COMPILATION 1
#define FFI_STATIC_BUILD 1
/* Specifies that GLib's g_print*() functions wrap the
* system printf functions. This is useful to know, for example,
* when using glibc's register_printf_function().
*/
#define GLIB_USING_SYSTEM_PRINTF
G_BEGIN_DECLS
#define G_MINFLOAT FLT_MIN
#define G_MAXFLOAT FLT_MAX
#define G_MINDOUBLE DBL_MIN
#define G_MAXDOUBLE DBL_MAX
#define G_MINSHORT SHRT_MIN
#define G_MAXSHORT SHRT_MAX
#define G_MAXUSHORT USHRT_MAX
#define G_MININT INT_MIN
#define G_MAXINT INT_MAX
#define G_MAXUINT UINT_MAX
#define G_MINLONG LONG_MIN
#define G_MAXLONG LONG_MAX
#define G_MAXULONG ULONG_MAX
typedef signed char gint8;
typedef unsigned char guint8;
typedef signed short gint16;
typedef unsigned short guint16;
#define G_GINT16_MODIFIER "h"
#define G_GINT16_FORMAT "hi"
#define G_GUINT16_FORMAT "hu"
typedef signed int gint32;
typedef unsigned int guint32;
#define G_GINT32_MODIFIER ""
#define G_GINT32_FORMAT "i"
#define G_GUINT32_FORMAT "u"
#define G_HAVE_GINT64 1 /* deprecated, always true */
typedef signed long gint64;
typedef unsigned long guint64;
#define G_GINT64_CONSTANT(val) (val##L)
#define G_GUINT64_CONSTANT(val) (val##UL)
#define G_GINT64_MODIFIER "l"
#define G_GINT64_FORMAT "li"
#define G_GUINT64_FORMAT "lu"
#define GLIB_SIZEOF_VOID_P 8
#define GLIB_SIZEOF_LONG 8
#define GLIB_SIZEOF_SIZE_T 8
#define GLIB_SIZEOF_SSIZE_T 8
typedef signed long gssize;
typedef unsigned long gsize;
#define G_GSIZE_MODIFIER "l"
#define G_GSSIZE_MODIFIER "l"
#define G_GSIZE_FORMAT "lu"
#define G_GSSIZE_FORMAT "li"
#define G_MAXSIZE G_MAXULONG
#define G_MINSSIZE G_MINLONG
#define G_MAXSSIZE G_MAXLONG
typedef gint64 goffset;
#define G_MINOFFSET G_MININT64
#define G_MAXOFFSET G_MAXINT64
#define G_GOFFSET_MODIFIER G_GINT64_MODIFIER
#define G_GOFFSET_FORMAT G_GINT64_FORMAT
#define G_GOFFSET_CONSTANT(val) G_GINT64_CONSTANT(val)
#define G_POLLFD_FORMAT "%d"
#define GPOINTER_TO_INT(p) ((gint) (glong) (p))
#define GPOINTER_TO_UINT(p) ((guint) (gulong) (p))
#define GINT_TO_POINTER(i) ((gpointer) (glong) (i))
#define GUINT_TO_POINTER(u) ((gpointer) (gulong) (u))
typedef signed long gintptr;
typedef unsigned long guintptr;
#define G_GINTPTR_MODIFIER "l"
#define G_GINTPTR_FORMAT "li"
#define G_GUINTPTR_FORMAT "lu"
#define GLIB_MAJOR_VERSION 2
#define GLIB_MINOR_VERSION 86
#define GLIB_MICRO_VERSION 1
#define G_OS_UNIX
#define G_VA_COPY va_copy
#define G_VA_COPY_AS_ARRAY 1
#define G_HAVE_ISO_VARARGS 1
/* gcc-2.95.x supports both gnu style and ISO varargs, but if -ansi
* is passed ISO vararg support is turned off, and there is no work
* around to turn it on, so we unconditionally turn it off.
*/
#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
# undef G_HAVE_ISO_VARARGS
#endif
#define G_HAVE_GROWING_STACK 0
#ifndef _MSC_VER
# define G_HAVE_GNUC_VARARGS 1
#endif
#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
#define G_GNUC_INTERNAL __attribute__((visibility("hidden")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
#define G_GNUC_INTERNAL __hidden
#elif defined (__GNUC__) && defined (G_HAVE_GNUC_VISIBILITY)
#define G_GNUC_INTERNAL __attribute__((visibility("hidden")))
#else
#define G_GNUC_INTERNAL
#endif
#define G_THREADS_ENABLED
#define G_THREADS_IMPL_POSIX
#define G_ATOMIC_LOCK_FREE
#define GINT16_TO_LE(val) ((gint16) (val))
#define GUINT16_TO_LE(val) ((guint16) (val))
#define GINT16_TO_BE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
#define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE (val))
#define GINT32_TO_LE(val) ((gint32) (val))
#define GUINT32_TO_LE(val) ((guint32) (val))
#define GINT32_TO_BE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
#define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE (val))
#define GINT64_TO_LE(val) ((gint64) (val))
#define GUINT64_TO_LE(val) ((guint64) (val))
#define GINT64_TO_BE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
#define GUINT64_TO_BE(val) (GUINT64_SWAP_LE_BE (val))
#define GLONG_TO_LE(val) ((glong) GINT64_TO_LE (val))
#define GULONG_TO_LE(val) ((gulong) GUINT64_TO_LE (val))
#define GLONG_TO_BE(val) ((glong) GINT64_TO_BE (val))
#define GULONG_TO_BE(val) ((gulong) GUINT64_TO_BE (val))
#define GINT_TO_LE(val) ((gint) GINT32_TO_LE (val))
#define GUINT_TO_LE(val) ((guint) GUINT32_TO_LE (val))
#define GINT_TO_BE(val) ((gint) GINT32_TO_BE (val))
#define GUINT_TO_BE(val) ((guint) GUINT32_TO_BE (val))
#define GSIZE_TO_LE(val) ((gsize) GUINT64_TO_LE (val))
#define GSSIZE_TO_LE(val) ((gssize) GINT64_TO_LE (val))
#define GSIZE_TO_BE(val) ((gsize) GUINT64_TO_BE (val))
#define GSSIZE_TO_BE(val) ((gssize) GINT64_TO_BE (val))
#define G_BYTE_ORDER G_LITTLE_ENDIAN
#define GLIB_SYSDEF_POLLIN =1
#define GLIB_SYSDEF_POLLOUT =4
#define GLIB_SYSDEF_POLLPRI =2
#define GLIB_SYSDEF_POLLHUP =16
#define GLIB_SYSDEF_POLLERR =8
#define GLIB_SYSDEF_POLLNVAL =32
/* No way to disable deprecation warnings for macros, so only emit deprecation
* warnings on platforms where usage of this macro is broken */
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__CYGWIN__)
#define G_MODULE_SUFFIX "so" GLIB_DEPRECATED_MACRO_IN_2_76
#else
#define G_MODULE_SUFFIX "so"
#endif
typedef int GPid;
#define G_PID_FORMAT "i"
#define GLIB_SYSDEF_AF_UNIX 1
#define GLIB_SYSDEF_AF_INET 2
#define GLIB_SYSDEF_AF_INET6 10
#define GLIB_SYSDEF_MSG_OOB 1
#define GLIB_SYSDEF_MSG_PEEK 2
#define GLIB_SYSDEF_MSG_DONTROUTE 4
#define G_DIR_SEPARATOR '/'
#define G_DIR_SEPARATOR_S "/"
#define G_SEARCHPATH_SEPARATOR ':'
#define G_SEARCHPATH_SEPARATOR_S ":"
#undef G_HAVE_FREE_SIZED
G_END_DECLS
#endif /* __GLIBCONFIG_H__ */

@ -0,0 +1 @@
module.exports = __dirname;

@ -0,0 +1,42 @@
{
"name": "@img/sharp-libvips-linux-x64",
"version": "1.2.4",
"description": "Prebuilt libvips and dependencies for use with sharp on Linux (glibc) x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
"repository": {
"type": "git",
"url": "git+https://github.com/lovell/sharp-libvips.git",
"directory": "npm/linux-x64"
},
"license": "LGPL-3.0-or-later",
"funding": {
"url": "https://opencollective.com/libvips"
},
"preferUnplugged": true,
"publishConfig": {
"access": "public"
},
"files": [
"lib",
"versions.json"
],
"type": "commonjs",
"exports": {
"./lib": "./lib/index.js",
"./package": "./package.json",
"./versions": "./versions.json"
},
"config": {
"glibc": ">=2.26"
},
"os": [
"linux"
],
"libc": [
"glibc"
],
"cpu": [
"x64"
]
}

@ -0,0 +1,30 @@
{
"aom": "3.13.1",
"archive": "3.8.2",
"cairo": "1.18.4",
"cgif": "0.5.0",
"exif": "0.6.25",
"expat": "2.7.3",
"ffi": "3.5.2",
"fontconfig": "2.17.1",
"freetype": "2.14.1",
"fribidi": "1.0.16",
"glib": "2.86.1",
"harfbuzz": "12.1.0",
"heif": "1.20.2",
"highway": "1.3.0",
"imagequant": "2.4.1",
"lcms": "2.17",
"mozjpeg": "0826579",
"pango": "1.57.0",
"pixman": "0.46.4",
"png": "1.6.50",
"proxy-libintl": "0.5",
"rsvg": "2.61.2",
"spng": "0.7.4",
"tiff": "4.7.1",
"vips": "8.17.3",
"webp": "1.6.0",
"xml2": "2.15.1",
"zlib-ng": "2.2.5"
}

@ -0,0 +1,46 @@
# `@img/sharp-libvips-linuxmusl-x64`
Prebuilt libvips and dependencies for use with sharp on Linux (musl) x64.
## Licensing
This software contains third-party libraries
used under the terms of the following licences:
| Library | Used under the terms of |
|---------------|-----------------------------------------------------------------------------------------------------------|
| aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
| cairo | Mozilla Public License 2.0 |
| cgif | MIT Licence |
| expat | MIT Licence |
| fontconfig | [fontconfig Licence](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
| freetype | [freetype Licence](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
| fribidi | LGPLv3 |
| glib | LGPLv3 |
| harfbuzz | MIT Licence |
| highway | Apache-2.0 License, BSD 3-Clause |
| lcms | MIT Licence |
| libarchive | BSD 2-Clause |
| libexif | LGPLv3 |
| libffi | MIT Licence |
| libheif | LGPLv3 |
| libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
| libnsgif | MIT Licence |
| libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
| librsvg | LGPLv3 |
| libspng | [BSD 2-Clause, libpng License](https://github.com/randy408/libspng/blob/master/LICENSE) |
| libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
| libvips | LGPLv3 |
| libwebp | New BSD License |
| libxml2 | MIT Licence |
| mozjpeg | [zlib License, IJG License, BSD-3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
| pango | LGPLv3 |
| pixman | MIT Licence |
| proxy-libintl | LGPLv3 |
| zlib-ng | [zlib Licence](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
Use of libraries under the terms of the LGPLv3 is via the
"any later version" clause of the LGPLv2 or LGPLv2.1.
Please report any errors or omissions via
https://github.com/lovell/sharp-libvips/issues/new

@ -0,0 +1,221 @@
/* glibconfig.h
*
* This is a generated file. Please modify 'glibconfig.h.in'
*/
#ifndef __GLIBCONFIG_H__
#define __GLIBCONFIG_H__
#include <glib/gmacros.h>
#include <limits.h>
#include <float.h>
#define GLIB_HAVE_ALLOCA_H
#define GLIB_STATIC_COMPILATION 1
#define GOBJECT_STATIC_COMPILATION 1
#define GIO_STATIC_COMPILATION 1
#define GMODULE_STATIC_COMPILATION 1
#define GI_STATIC_COMPILATION 1
#define G_INTL_STATIC_COMPILATION 1
#define FFI_STATIC_BUILD 1
/* Specifies that GLib's g_print*() functions wrap the
* system printf functions. This is useful to know, for example,
* when using glibc's register_printf_function().
*/
#define GLIB_USING_SYSTEM_PRINTF
G_BEGIN_DECLS
#define G_MINFLOAT FLT_MIN
#define G_MAXFLOAT FLT_MAX
#define G_MINDOUBLE DBL_MIN
#define G_MAXDOUBLE DBL_MAX
#define G_MINSHORT SHRT_MIN
#define G_MAXSHORT SHRT_MAX
#define G_MAXUSHORT USHRT_MAX
#define G_MININT INT_MIN
#define G_MAXINT INT_MAX
#define G_MAXUINT UINT_MAX
#define G_MINLONG LONG_MIN
#define G_MAXLONG LONG_MAX
#define G_MAXULONG ULONG_MAX
typedef signed char gint8;
typedef unsigned char guint8;
typedef signed short gint16;
typedef unsigned short guint16;
#define G_GINT16_MODIFIER "h"
#define G_GINT16_FORMAT "hi"
#define G_GUINT16_FORMAT "hu"
typedef signed int gint32;
typedef unsigned int guint32;
#define G_GINT32_MODIFIER ""
#define G_GINT32_FORMAT "i"
#define G_GUINT32_FORMAT "u"
#define G_HAVE_GINT64 1 /* deprecated, always true */
typedef signed long gint64;
typedef unsigned long guint64;
#define G_GINT64_CONSTANT(val) (val##L)
#define G_GUINT64_CONSTANT(val) (val##UL)
#define G_GINT64_MODIFIER "l"
#define G_GINT64_FORMAT "li"
#define G_GUINT64_FORMAT "lu"
#define GLIB_SIZEOF_VOID_P 8
#define GLIB_SIZEOF_LONG 8
#define GLIB_SIZEOF_SIZE_T 8
#define GLIB_SIZEOF_SSIZE_T 8
typedef signed long gssize;
typedef unsigned long gsize;
#define G_GSIZE_MODIFIER "l"
#define G_GSSIZE_MODIFIER "l"
#define G_GSIZE_FORMAT "lu"
#define G_GSSIZE_FORMAT "li"
#define G_MAXSIZE G_MAXULONG
#define G_MINSSIZE G_MINLONG
#define G_MAXSSIZE G_MAXLONG
typedef gint64 goffset;
#define G_MINOFFSET G_MININT64
#define G_MAXOFFSET G_MAXINT64
#define G_GOFFSET_MODIFIER G_GINT64_MODIFIER
#define G_GOFFSET_FORMAT G_GINT64_FORMAT
#define G_GOFFSET_CONSTANT(val) G_GINT64_CONSTANT(val)
#define G_POLLFD_FORMAT "%d"
#define GPOINTER_TO_INT(p) ((gint) (glong) (p))
#define GPOINTER_TO_UINT(p) ((guint) (gulong) (p))
#define GINT_TO_POINTER(i) ((gpointer) (glong) (i))
#define GUINT_TO_POINTER(u) ((gpointer) (gulong) (u))
typedef signed long gintptr;
typedef unsigned long guintptr;
#define G_GINTPTR_MODIFIER "l"
#define G_GINTPTR_FORMAT "li"
#define G_GUINTPTR_FORMAT "lu"
#define GLIB_MAJOR_VERSION 2
#define GLIB_MINOR_VERSION 86
#define GLIB_MICRO_VERSION 1
#define G_OS_UNIX
#define G_VA_COPY va_copy
#define G_VA_COPY_AS_ARRAY 1
#define G_HAVE_ISO_VARARGS 1
/* gcc-2.95.x supports both gnu style and ISO varargs, but if -ansi
* is passed ISO vararg support is turned off, and there is no work
* around to turn it on, so we unconditionally turn it off.
*/
#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
# undef G_HAVE_ISO_VARARGS
#endif
#define G_HAVE_GROWING_STACK 0
#ifndef _MSC_VER
# define G_HAVE_GNUC_VARARGS 1
#endif
#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
#define G_GNUC_INTERNAL __attribute__((visibility("hidden")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
#define G_GNUC_INTERNAL __hidden
#elif defined (__GNUC__) && defined (G_HAVE_GNUC_VISIBILITY)
#define G_GNUC_INTERNAL __attribute__((visibility("hidden")))
#else
#define G_GNUC_INTERNAL
#endif
#define G_THREADS_ENABLED
#define G_THREADS_IMPL_POSIX
#define G_ATOMIC_LOCK_FREE
#define GINT16_TO_LE(val) ((gint16) (val))
#define GUINT16_TO_LE(val) ((guint16) (val))
#define GINT16_TO_BE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
#define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE (val))
#define GINT32_TO_LE(val) ((gint32) (val))
#define GUINT32_TO_LE(val) ((guint32) (val))
#define GINT32_TO_BE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
#define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE (val))
#define GINT64_TO_LE(val) ((gint64) (val))
#define GUINT64_TO_LE(val) ((guint64) (val))
#define GINT64_TO_BE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
#define GUINT64_TO_BE(val) (GUINT64_SWAP_LE_BE (val))
#define GLONG_TO_LE(val) ((glong) GINT64_TO_LE (val))
#define GULONG_TO_LE(val) ((gulong) GUINT64_TO_LE (val))
#define GLONG_TO_BE(val) ((glong) GINT64_TO_BE (val))
#define GULONG_TO_BE(val) ((gulong) GUINT64_TO_BE (val))
#define GINT_TO_LE(val) ((gint) GINT32_TO_LE (val))
#define GUINT_TO_LE(val) ((guint) GUINT32_TO_LE (val))
#define GINT_TO_BE(val) ((gint) GINT32_TO_BE (val))
#define GUINT_TO_BE(val) ((guint) GUINT32_TO_BE (val))
#define GSIZE_TO_LE(val) ((gsize) GUINT64_TO_LE (val))
#define GSSIZE_TO_LE(val) ((gssize) GINT64_TO_LE (val))
#define GSIZE_TO_BE(val) ((gsize) GUINT64_TO_BE (val))
#define GSSIZE_TO_BE(val) ((gssize) GINT64_TO_BE (val))
#define G_BYTE_ORDER G_LITTLE_ENDIAN
#define GLIB_SYSDEF_POLLIN =1
#define GLIB_SYSDEF_POLLOUT =4
#define GLIB_SYSDEF_POLLPRI =2
#define GLIB_SYSDEF_POLLHUP =16
#define GLIB_SYSDEF_POLLERR =8
#define GLIB_SYSDEF_POLLNVAL =32
/* No way to disable deprecation warnings for macros, so only emit deprecation
* warnings on platforms where usage of this macro is broken */
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__CYGWIN__)
#define G_MODULE_SUFFIX "so" GLIB_DEPRECATED_MACRO_IN_2_76
#else
#define G_MODULE_SUFFIX "so"
#endif
typedef int GPid;
#define G_PID_FORMAT "i"
#define GLIB_SYSDEF_AF_UNIX 1
#define GLIB_SYSDEF_AF_INET 2
#define GLIB_SYSDEF_AF_INET6 10
#define GLIB_SYSDEF_MSG_OOB 1
#define GLIB_SYSDEF_MSG_PEEK 2
#define GLIB_SYSDEF_MSG_DONTROUTE 4
#define G_DIR_SEPARATOR '/'
#define G_DIR_SEPARATOR_S "/"
#define G_SEARCHPATH_SEPARATOR ':'
#define G_SEARCHPATH_SEPARATOR_S ":"
#undef G_HAVE_FREE_SIZED
G_END_DECLS
#endif /* __GLIBCONFIG_H__ */

@ -0,0 +1 @@
module.exports = __dirname;

@ -0,0 +1,42 @@
{
"name": "@img/sharp-libvips-linuxmusl-x64",
"version": "1.2.4",
"description": "Prebuilt libvips and dependencies for use with sharp on Linux (musl) x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
"repository": {
"type": "git",
"url": "git+https://github.com/lovell/sharp-libvips.git",
"directory": "npm/linuxmusl-x64"
},
"license": "LGPL-3.0-or-later",
"funding": {
"url": "https://opencollective.com/libvips"
},
"preferUnplugged": true,
"publishConfig": {
"access": "public"
},
"files": [
"lib",
"versions.json"
],
"type": "commonjs",
"exports": {
"./lib": "./lib/index.js",
"./package": "./package.json",
"./versions": "./versions.json"
},
"config": {
"musl": ">=1.2.2"
},
"os": [
"linux"
],
"libc": [
"musl"
],
"cpu": [
"x64"
]
}

@ -0,0 +1,30 @@
{
"aom": "3.13.1",
"archive": "3.8.2",
"cairo": "1.18.4",
"cgif": "0.5.0",
"exif": "0.6.25",
"expat": "2.7.3",
"ffi": "3.5.2",
"fontconfig": "2.17.1",
"freetype": "2.14.1",
"fribidi": "1.0.16",
"glib": "2.86.1",
"harfbuzz": "12.1.0",
"heif": "1.20.2",
"highway": "1.3.0",
"imagequant": "2.4.1",
"lcms": "2.17",
"mozjpeg": "0826579",
"pango": "1.57.0",
"pixman": "0.46.4",
"png": "1.6.50",
"proxy-libintl": "0.5",
"rsvg": "2.61.2",
"spng": "0.7.4",
"tiff": "4.7.1",
"vips": "8.17.3",
"webp": "1.6.0",
"xml2": "2.15.1",
"zlib-ng": "2.2.5"
}

6
package-lock.json generated

@ -0,0 +1,6 @@
{
"name": "nudt-compiler-cpp",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

@ -0,0 +1,97 @@
Lab1 语法树构建
要做什么:补全 SysY 文法,保证更多合法程序可被解析并打印语法树。
主要改哪些文件:
Lab1-语法树构建.md
SysY.g4
AntlrDriver.cpp
SyntaxTreePrinter.cpp
修改方式:
扩展 grammar 规则和 token保持解析入口稳定错误信息要可定位到行列语法树打印结构清晰。
验收parse-tree 模式批量通过测试集。
Lab2 中间表示生成
要做什么:把语义检查和 IR 生成从最小子集扩展到课程要求语法。
主要改哪些文件:
Lab2-中间表示生成.md
Sema.h
SymbolTable.h
Sema.cpp
SymbolTable.cpp
IR.h
IRBuilder.cpp
Instruction.cpp
IRPrinter.cpp
IRGen.h
IRGenDecl.cpp
IRGenStmt.cpp
IRGenExp.cpp
IRGenFunc.cpp
IRGenDriver.cpp
修改方式:
先补语义绑定和错误检查,再补 IR 指令与类型,最后在 Visitor 里把各类语句表达式翻译到 IR。
验收IR 能生成,并且 verify_ir 脚本 run 模式和输出比对通过。
Lab3 指令选择与汇编生成
要做什么:把 IR 正确 lower 到 AArch64 汇编,覆盖更多语义。
主要改哪些文件:
Lab3-指令选择与汇编生成.md
MIR.h
Lowering.cpp
RegAlloc.cpp
FrameLowering.cpp
AsmPrinter.cpp
修改方式:
扩充 MIR 指令和操作数表示;完善 lowering 映射;保证栈帧和函数序言尾声正确;输出可汇编可运行的 asm。
验收verify_asm 脚本 run 模式通过。
Lab4 基本标量优化
要做什么:先做 mem2reg再做常量相关优化、DCE、CFG 简化、CSE 等。
主要改哪些文件:
Lab4-基本标量优化.md
Mem2Reg.cpp
ConstFold.cpp
ConstProp.cpp
DCE.cpp
CSE.cpp
CFGSimplify.cpp
PassManager.cpp
DominatorTree.cpp
LoopInfo.cpp
修改方式:
实现每个 pass 的核心逻辑,并在 PassManager 固化顺序和迭代策略。
验收优化前后语义一致IR/ASM 回归测试通过。
Lab5 寄存器分配与后端优化
要做什么:从固定寄存器模板,升级到虚拟寄存器+真实分配+spill/reload再做后端局部优化。
主要改哪些文件:
Lab5-寄存器分配.md
MIR.h
Lowering.cpp
RegAlloc.cpp
FrameLowering.cpp
AsmPrinter.cpp
Peephole.cpp
PassManager.cpp
修改方式:
Lowering 先产出 vregRA 选图着色或线扫;处理调用约定和栈槽;最后做 peephole 与冗余访存清理。
验收:全测试正确,且汇编明显减少无效 move/load/store。
Lab6 并行与循环优化
要做什么:识别循环结构并做循环优化,必要时尝试并行化识别。
主要改哪些文件:
Lab6-并行与循环优化.md
DominatorTree.cpp
LoopInfo.cpp
PassManager.cpp
CMakeLists.txt
修改方式:
补稳定的循环分析,再实现 LICM、强度削弱、展开、分裂中的一部分并接入 pass 流程。
验收:功能回归全通过,同时在代表性用例看到性能或代码质量收益。
你可以直接照这个顺序推进
先做 Lab2优先把语义和 IR 生成功能面补全。
再做 Lab3保证语义到汇编端到端正确。
接着做 Lab4把优化 pass 跑通。
然后做 Lab5完成真实寄存器分配。
最后做 Lab6补循环优化和并行化探索。

@ -0,0 +1,39 @@
import os
import subprocess
COMPILER = "./build/bin/compiler"
TEST_DIR = "./test/test_case/performance"
pass_cnt = 0
fail_cnt = 0
print("===== SysY Batch Test Start =====")
for file in os.listdir(TEST_DIR):
if not file.endswith(".sy"):
continue
path = os.path.join(TEST_DIR, file)
print(f"[TEST] {file} ... ", end="")
result = subprocess.run(
[COMPILER, "--emit-parse-tree", path],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE
)
if result.returncode == 0:
print("PASS")
pass_cnt += 1
else:
print("FAIL")
fail_cnt += 1
print("---- Error ----")
print(result.stderr.decode())
print("---------------")
print("===============================")
print(f"Total: {pass_cnt + fail_cnt}")
print(f"PASS : {pass_cnt}")
print(f"FAIL : {fail_cnt}")
print("===============================")

@ -1,8 +1,4 @@
// SysY 子集语法:支持形如
// int main() { int a = 1; int b = 2; return a + b; }
// 的最小返回表达式编译。
// 后续需要自行添加
// SysY Lab1 语法:覆盖常见声明、控制流、数组、函数与表达式优先级。
grammar SysY;
@ -10,20 +6,72 @@ grammar SysY;
/* Lexer rules */
/*===-------------------------------------------===*/
CONST: 'const';
INT: 'int';
FLOAT: 'float';
VOID: 'void';
IF: 'if';
ELSE: 'else';
WHILE: 'while';
BREAK: 'break';
CONTINUE: 'continue';
RETURN: 'return';
ASSIGN: '=';
EQ: '==';
NE: '!=';
LT: '<';
GT: '>';
LE: '<=';
GE: '>=';
ADD: '+';
SUB: '-';
MUL: '*';
DIV: '/';
MOD: '%';
NOT: '!';
AND: '&&';
OR: '||';
LPAREN: '(';
RPAREN: ')';
LBRACK: '[';
RBRACK: ']';
LBRACE: '{';
RBRACE: '}';
COMMA: ',';
SEMICOLON: ';';
ID: [a-zA-Z_][a-zA-Z_0-9]*;
ILITERAL: [0-9]+;
FLITERAL
: DECIMAL_FLOAT
| HEX_FLOAT
;
ILITERAL
: HEX_INT
| OCT_INT
| DEC_INT
;
fragment DEC_INT: '0' | [1-9] [0-9]*;
fragment OCT_INT: '0' [0-7]+;
fragment HEX_INT: '0' [xX] [0-9a-fA-F]+;
fragment DECIMAL_FLOAT
: [0-9]+ '.' [0-9]* EXP?
| '.' [0-9]+ EXP?
| [0-9]+ EXP
;
fragment HEX_FLOAT
: '0' [xX] [0-9a-fA-F]+ ('.' [0-9a-fA-F]*)? [pP] [+-]? [0-9]+
| '0' [xX] '.' [0-9a-fA-F]+ [pP] [+-]? [0-9]+
;
fragment EXP: [eE] [+-]? [0-9]+;
WS: [ \t\r\n] -> skip;
LINECOMMENT: '//' ~[\r\n]* -> skip;
@ -34,31 +82,61 @@ BLOCKCOMMENT: '/*' .*? '*/' -> skip;
/*===-------------------------------------------===*/
compUnit
: funcDef EOF
: (decl | funcDef)+ EOF
;
decl
: btype varDef SEMICOLON
: constDecl
| varDecl
;
constDecl
: CONST btype constDef (COMMA constDef)* SEMICOLON
;
constDef
: ID (LBRACK constExp RBRACK)* ASSIGN constInitValue
;
constInitValue
: constExp
| LBRACE (constInitValue (COMMA constInitValue)*)? RBRACE
;
varDecl
: btype varDef (COMMA varDef)* SEMICOLON
;
btype
: INT
| FLOAT
;
varDef
: lValue (ASSIGN initValue)?
: ID (LBRACK constExp RBRACK)* (ASSIGN initValue)?
;
initValue
: exp
| LBRACE (initValue (COMMA initValue)*)? RBRACE
;
funcDef
: funcType ID LPAREN RPAREN blockStmt
: funcType ID LPAREN (funcFParams)? RPAREN blockStmt
;
funcType
: INT
| FLOAT
| VOID
;
funcFParams
: funcFParam (COMMA funcFParam)*
;
funcFParam
: btype ID (LBRACK RBRACK (LBRACK exp RBRACK)*)?
;
blockStmt
@ -71,28 +149,89 @@ blockItem
;
stmt
: returnStmt
: lValue ASSIGN exp SEMICOLON
| (exp)? SEMICOLON
| blockStmt
| IF LPAREN cond RPAREN stmt (ELSE stmt)?
| WHILE LPAREN cond RPAREN stmt
| BREAK SEMICOLON
| CONTINUE SEMICOLON
| returnStmt
;
returnStmt
: RETURN exp SEMICOLON
: RETURN (exp)? SEMICOLON
;
exp
: LPAREN exp RPAREN # parenExp
| var # varExp
| number # numberExp
| exp ADD exp # additiveExp
: addExp
;
var
: ID
cond
: lOrExp
;
lValue
: ID
: ID (LBRACK exp RBRACK)*
;
primaryExp
: LPAREN exp RPAREN
| lValue
| number
;
number
: ILITERAL
| FLITERAL
;
unaryExp
: primaryExp
| ID LPAREN (funcRParams)? RPAREN
| unaryOp unaryExp
;
unaryOp
: ADD
| SUB
| NOT
;
funcRParams
: exp (COMMA exp)*
;
mulExp
: unaryExp
| mulExp (MUL | DIV | MOD) unaryExp
;
addExp
: mulExp
| addExp (ADD | SUB) mulExp
;
relExp
: addExp
| relExp (LT | GT | LE | GE) addExp
;
eqExp
: relExp
| eqExp (EQ | NE) relExp
;
lAndExp
: eqExp
| lAndExp AND eqExp
;
lOrExp
: lAndExp
| lOrExp OR lAndExp
;
constExp
: addExp
;

@ -0,0 +1,7 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#include "SysYBaseVisitor.h"

@ -0,0 +1,148 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
#include "SysYVisitor.h"
/**
* This class provides an empty implementation of SysYVisitor, which can be
* extended to create a visitor which only needs to handle a subset of the available methods.
*/
class SysYBaseVisitor : public SysYVisitor {
public:
virtual std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitDecl(SysYParser::DeclContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstDef(SysYParser::ConstDefContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstInitValue(SysYParser::ConstInitValueContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitBtype(SysYParser::BtypeContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitVarDef(SysYParser::VarDefContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitInitValue(SysYParser::InitValueContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncDef(SysYParser::FuncDefContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitBlockItem(SysYParser::BlockItemContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitStmt(SysYParser::StmtContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitExp(SysYParser::ExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitCond(SysYParser::CondContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitLValue(SysYParser::LValueContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitNumber(SysYParser::NumberContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitMulExp(SysYParser::MulExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitAddExp(SysYParser::AddExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitRelExp(SysYParser::RelExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitEqExp(SysYParser::EqExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstExp(SysYParser::ConstExpContext *ctx) override {
return visitChildren(ctx);
}
};

@ -0,0 +1,271 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#include "SysYLexer.h"
using namespace antlr4;
using namespace antlr4;
namespace {
struct SysYLexerStaticData final {
SysYLexerStaticData(std::vector<std::string> ruleNames,
std::vector<std::string> channelNames,
std::vector<std::string> modeNames,
std::vector<std::string> literalNames,
std::vector<std::string> symbolicNames)
: ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)),
modeNames(std::move(modeNames)), literalNames(std::move(literalNames)),
symbolicNames(std::move(symbolicNames)),
vocabulary(this->literalNames, this->symbolicNames) {}
SysYLexerStaticData(const SysYLexerStaticData&) = delete;
SysYLexerStaticData(SysYLexerStaticData&&) = delete;
SysYLexerStaticData& operator=(const SysYLexerStaticData&) = delete;
SysYLexerStaticData& operator=(SysYLexerStaticData&&) = delete;
std::vector<antlr4::dfa::DFA> decisionToDFA;
antlr4::atn::PredictionContextCache sharedContextCache;
const std::vector<std::string> ruleNames;
const std::vector<std::string> channelNames;
const std::vector<std::string> modeNames;
const std::vector<std::string> literalNames;
const std::vector<std::string> symbolicNames;
const antlr4::dfa::Vocabulary vocabulary;
antlr4::atn::SerializedATNView serializedATN;
std::unique_ptr<antlr4::atn::ATN> atn;
};
::antlr4::internal::OnceFlag sysylexerLexerOnceFlag;
#if ANTLR4_USE_THREAD_LOCAL_CACHE
static thread_local
#endif
std::unique_ptr<SysYLexerStaticData> sysylexerLexerStaticData = nullptr;
void sysylexerLexerInitialize() {
#if ANTLR4_USE_THREAD_LOCAL_CACHE
if (sysylexerLexerStaticData != nullptr) {
return;
}
#else
assert(sysylexerLexerStaticData == nullptr);
#endif
auto staticData = std::make_unique<SysYLexerStaticData>(
std::vector<std::string>{
"CONST", "INT", "FLOAT", "VOID", "IF", "ELSE", "WHILE", "BREAK", "CONTINUE",
"RETURN", "ASSIGN", "EQ", "NE", "LT", "GT", "LE", "GE", "ADD", "SUB",
"MUL", "DIV", "MOD", "NOT", "AND", "OR", "LPAREN", "RPAREN", "LBRACK",
"RBRACK", "LBRACE", "RBRACE", "COMMA", "SEMICOLON", "ID", "FLITERAL",
"ILITERAL", "DEC_INT", "OCT_INT", "HEX_INT", "DECIMAL_FLOAT", "HEX_FLOAT",
"EXP", "WS", "LINECOMMENT", "BLOCKCOMMENT"
},
std::vector<std::string>{
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
},
std::vector<std::string>{
"DEFAULT_MODE"
},
std::vector<std::string>{
"", "'const'", "'int'", "'float'", "'void'", "'if'", "'else'", "'while'",
"'break'", "'continue'", "'return'", "'='", "'=='", "'!='", "'<'",
"'>'", "'<='", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "'&&'",
"'||'", "'('", "')'", "'['", "']'", "'{'", "'}'", "','", "';'"
},
std::vector<std::string>{
"", "CONST", "INT", "FLOAT", "VOID", "IF", "ELSE", "WHILE", "BREAK",
"CONTINUE", "RETURN", "ASSIGN", "EQ", "NE", "LT", "GT", "LE", "GE",
"ADD", "SUB", "MUL", "DIV", "MOD", "NOT", "AND", "OR", "LPAREN", "RPAREN",
"LBRACK", "RBRACK", "LBRACE", "RBRACE", "COMMA", "SEMICOLON", "ID",
"FLITERAL", "ILITERAL", "WS", "LINECOMMENT", "BLOCKCOMMENT"
}
);
static const int32_t serializedATNSegment[] = {
4,0,39,353,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,
7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,
7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,
7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,
7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,
7,42,2,43,7,43,2,44,7,44,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,2,
1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,
5,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,
1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,11,1,11,1,11,
1,12,1,12,1,12,1,13,1,13,1,14,1,14,1,15,1,15,1,15,1,16,1,16,1,16,1,17,
1,17,1,18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,23,
1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,
1,30,1,31,1,31,1,32,1,32,1,33,1,33,5,33,203,8,33,10,33,12,33,206,9,33,
1,34,1,34,3,34,210,8,34,1,35,1,35,1,35,3,35,215,8,35,1,36,1,36,1,36,5,
36,220,8,36,10,36,12,36,223,9,36,3,36,225,8,36,1,37,1,37,4,37,229,8,37,
11,37,12,37,230,1,38,1,38,1,38,4,38,236,8,38,11,38,12,38,237,1,39,4,39,
241,8,39,11,39,12,39,242,1,39,1,39,5,39,247,8,39,10,39,12,39,250,9,39,
1,39,3,39,253,8,39,1,39,1,39,4,39,257,8,39,11,39,12,39,258,1,39,3,39,
262,8,39,1,39,4,39,265,8,39,11,39,12,39,266,1,39,3,39,270,8,39,1,40,1,
40,1,40,4,40,275,8,40,11,40,12,40,276,1,40,1,40,5,40,281,8,40,10,40,12,
40,284,9,40,3,40,286,8,40,1,40,1,40,3,40,290,8,40,1,40,4,40,293,8,40,
11,40,12,40,294,1,40,1,40,1,40,1,40,4,40,301,8,40,11,40,12,40,302,1,40,
1,40,3,40,307,8,40,1,40,4,40,310,8,40,11,40,12,40,311,3,40,314,8,40,1,
41,1,41,3,41,318,8,41,1,41,4,41,321,8,41,11,41,12,41,322,1,42,1,42,1,
42,1,42,1,43,1,43,1,43,1,43,5,43,333,8,43,10,43,12,43,336,9,43,1,43,1,
43,1,44,1,44,1,44,1,44,5,44,344,8,44,10,44,12,44,347,9,44,1,44,1,44,1,
44,1,44,1,44,1,345,0,45,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,
21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,
22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,
67,34,69,35,71,36,73,0,75,0,77,0,79,0,81,0,83,0,85,37,87,38,89,39,1,0,
12,3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,1,0,49,57,1,0,
48,57,1,0,48,55,2,0,88,88,120,120,3,0,48,57,65,70,97,102,2,0,80,80,112,
112,2,0,43,43,45,45,2,0,69,69,101,101,3,0,9,10,13,13,32,32,2,0,10,10,
13,13,375,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,
0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,
1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,
0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,
0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,
1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,
0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,85,1,0,0,0,
0,87,1,0,0,0,0,89,1,0,0,0,1,91,1,0,0,0,3,97,1,0,0,0,5,101,1,0,0,0,7,107,
1,0,0,0,9,112,1,0,0,0,11,115,1,0,0,0,13,120,1,0,0,0,15,126,1,0,0,0,17,
132,1,0,0,0,19,141,1,0,0,0,21,148,1,0,0,0,23,150,1,0,0,0,25,153,1,0,0,
0,27,156,1,0,0,0,29,158,1,0,0,0,31,160,1,0,0,0,33,163,1,0,0,0,35,166,
1,0,0,0,37,168,1,0,0,0,39,170,1,0,0,0,41,172,1,0,0,0,43,174,1,0,0,0,45,
176,1,0,0,0,47,178,1,0,0,0,49,181,1,0,0,0,51,184,1,0,0,0,53,186,1,0,0,
0,55,188,1,0,0,0,57,190,1,0,0,0,59,192,1,0,0,0,61,194,1,0,0,0,63,196,
1,0,0,0,65,198,1,0,0,0,67,200,1,0,0,0,69,209,1,0,0,0,71,214,1,0,0,0,73,
224,1,0,0,0,75,226,1,0,0,0,77,232,1,0,0,0,79,269,1,0,0,0,81,313,1,0,0,
0,83,315,1,0,0,0,85,324,1,0,0,0,87,328,1,0,0,0,89,339,1,0,0,0,91,92,5,
99,0,0,92,93,5,111,0,0,93,94,5,110,0,0,94,95,5,115,0,0,95,96,5,116,0,
0,96,2,1,0,0,0,97,98,5,105,0,0,98,99,5,110,0,0,99,100,5,116,0,0,100,4,
1,0,0,0,101,102,5,102,0,0,102,103,5,108,0,0,103,104,5,111,0,0,104,105,
5,97,0,0,105,106,5,116,0,0,106,6,1,0,0,0,107,108,5,118,0,0,108,109,5,
111,0,0,109,110,5,105,0,0,110,111,5,100,0,0,111,8,1,0,0,0,112,113,5,105,
0,0,113,114,5,102,0,0,114,10,1,0,0,0,115,116,5,101,0,0,116,117,5,108,
0,0,117,118,5,115,0,0,118,119,5,101,0,0,119,12,1,0,0,0,120,121,5,119,
0,0,121,122,5,104,0,0,122,123,5,105,0,0,123,124,5,108,0,0,124,125,5,101,
0,0,125,14,1,0,0,0,126,127,5,98,0,0,127,128,5,114,0,0,128,129,5,101,0,
0,129,130,5,97,0,0,130,131,5,107,0,0,131,16,1,0,0,0,132,133,5,99,0,0,
133,134,5,111,0,0,134,135,5,110,0,0,135,136,5,116,0,0,136,137,5,105,0,
0,137,138,5,110,0,0,138,139,5,117,0,0,139,140,5,101,0,0,140,18,1,0,0,
0,141,142,5,114,0,0,142,143,5,101,0,0,143,144,5,116,0,0,144,145,5,117,
0,0,145,146,5,114,0,0,146,147,5,110,0,0,147,20,1,0,0,0,148,149,5,61,0,
0,149,22,1,0,0,0,150,151,5,61,0,0,151,152,5,61,0,0,152,24,1,0,0,0,153,
154,5,33,0,0,154,155,5,61,0,0,155,26,1,0,0,0,156,157,5,60,0,0,157,28,
1,0,0,0,158,159,5,62,0,0,159,30,1,0,0,0,160,161,5,60,0,0,161,162,5,61,
0,0,162,32,1,0,0,0,163,164,5,62,0,0,164,165,5,61,0,0,165,34,1,0,0,0,166,
167,5,43,0,0,167,36,1,0,0,0,168,169,5,45,0,0,169,38,1,0,0,0,170,171,5,
42,0,0,171,40,1,0,0,0,172,173,5,47,0,0,173,42,1,0,0,0,174,175,5,37,0,
0,175,44,1,0,0,0,176,177,5,33,0,0,177,46,1,0,0,0,178,179,5,38,0,0,179,
180,5,38,0,0,180,48,1,0,0,0,181,182,5,124,0,0,182,183,5,124,0,0,183,50,
1,0,0,0,184,185,5,40,0,0,185,52,1,0,0,0,186,187,5,41,0,0,187,54,1,0,0,
0,188,189,5,91,0,0,189,56,1,0,0,0,190,191,5,93,0,0,191,58,1,0,0,0,192,
193,5,123,0,0,193,60,1,0,0,0,194,195,5,125,0,0,195,62,1,0,0,0,196,197,
5,44,0,0,197,64,1,0,0,0,198,199,5,59,0,0,199,66,1,0,0,0,200,204,7,0,0,
0,201,203,7,1,0,0,202,201,1,0,0,0,203,206,1,0,0,0,204,202,1,0,0,0,204,
205,1,0,0,0,205,68,1,0,0,0,206,204,1,0,0,0,207,210,3,79,39,0,208,210,
3,81,40,0,209,207,1,0,0,0,209,208,1,0,0,0,210,70,1,0,0,0,211,215,3,77,
38,0,212,215,3,75,37,0,213,215,3,73,36,0,214,211,1,0,0,0,214,212,1,0,
0,0,214,213,1,0,0,0,215,72,1,0,0,0,216,225,5,48,0,0,217,221,7,2,0,0,218,
220,7,3,0,0,219,218,1,0,0,0,220,223,1,0,0,0,221,219,1,0,0,0,221,222,1,
0,0,0,222,225,1,0,0,0,223,221,1,0,0,0,224,216,1,0,0,0,224,217,1,0,0,0,
225,74,1,0,0,0,226,228,5,48,0,0,227,229,7,4,0,0,228,227,1,0,0,0,229,230,
1,0,0,0,230,228,1,0,0,0,230,231,1,0,0,0,231,76,1,0,0,0,232,233,5,48,0,
0,233,235,7,5,0,0,234,236,7,6,0,0,235,234,1,0,0,0,236,237,1,0,0,0,237,
235,1,0,0,0,237,238,1,0,0,0,238,78,1,0,0,0,239,241,7,3,0,0,240,239,1,
0,0,0,241,242,1,0,0,0,242,240,1,0,0,0,242,243,1,0,0,0,243,244,1,0,0,0,
244,248,5,46,0,0,245,247,7,3,0,0,246,245,1,0,0,0,247,250,1,0,0,0,248,
246,1,0,0,0,248,249,1,0,0,0,249,252,1,0,0,0,250,248,1,0,0,0,251,253,3,
83,41,0,252,251,1,0,0,0,252,253,1,0,0,0,253,270,1,0,0,0,254,256,5,46,
0,0,255,257,7,3,0,0,256,255,1,0,0,0,257,258,1,0,0,0,258,256,1,0,0,0,258,
259,1,0,0,0,259,261,1,0,0,0,260,262,3,83,41,0,261,260,1,0,0,0,261,262,
1,0,0,0,262,270,1,0,0,0,263,265,7,3,0,0,264,263,1,0,0,0,265,266,1,0,0,
0,266,264,1,0,0,0,266,267,1,0,0,0,267,268,1,0,0,0,268,270,3,83,41,0,269,
240,1,0,0,0,269,254,1,0,0,0,269,264,1,0,0,0,270,80,1,0,0,0,271,272,5,
48,0,0,272,274,7,5,0,0,273,275,7,6,0,0,274,273,1,0,0,0,275,276,1,0,0,
0,276,274,1,0,0,0,276,277,1,0,0,0,277,285,1,0,0,0,278,282,5,46,0,0,279,
281,7,6,0,0,280,279,1,0,0,0,281,284,1,0,0,0,282,280,1,0,0,0,282,283,1,
0,0,0,283,286,1,0,0,0,284,282,1,0,0,0,285,278,1,0,0,0,285,286,1,0,0,0,
286,287,1,0,0,0,287,289,7,7,0,0,288,290,7,8,0,0,289,288,1,0,0,0,289,290,
1,0,0,0,290,292,1,0,0,0,291,293,7,3,0,0,292,291,1,0,0,0,293,294,1,0,0,
0,294,292,1,0,0,0,294,295,1,0,0,0,295,314,1,0,0,0,296,297,5,48,0,0,297,
298,7,5,0,0,298,300,5,46,0,0,299,301,7,6,0,0,300,299,1,0,0,0,301,302,
1,0,0,0,302,300,1,0,0,0,302,303,1,0,0,0,303,304,1,0,0,0,304,306,7,7,0,
0,305,307,7,8,0,0,306,305,1,0,0,0,306,307,1,0,0,0,307,309,1,0,0,0,308,
310,7,3,0,0,309,308,1,0,0,0,310,311,1,0,0,0,311,309,1,0,0,0,311,312,1,
0,0,0,312,314,1,0,0,0,313,271,1,0,0,0,313,296,1,0,0,0,314,82,1,0,0,0,
315,317,7,9,0,0,316,318,7,8,0,0,317,316,1,0,0,0,317,318,1,0,0,0,318,320,
1,0,0,0,319,321,7,3,0,0,320,319,1,0,0,0,321,322,1,0,0,0,322,320,1,0,0,
0,322,323,1,0,0,0,323,84,1,0,0,0,324,325,7,10,0,0,325,326,1,0,0,0,326,
327,6,42,0,0,327,86,1,0,0,0,328,329,5,47,0,0,329,330,5,47,0,0,330,334,
1,0,0,0,331,333,8,11,0,0,332,331,1,0,0,0,333,336,1,0,0,0,334,332,1,0,
0,0,334,335,1,0,0,0,335,337,1,0,0,0,336,334,1,0,0,0,337,338,6,43,0,0,
338,88,1,0,0,0,339,340,5,47,0,0,340,341,5,42,0,0,341,345,1,0,0,0,342,
344,9,0,0,0,343,342,1,0,0,0,344,347,1,0,0,0,345,346,1,0,0,0,345,343,1,
0,0,0,346,348,1,0,0,0,347,345,1,0,0,0,348,349,5,42,0,0,349,350,5,47,0,
0,350,351,1,0,0,0,351,352,6,44,0,0,352,90,1,0,0,0,28,0,204,209,214,221,
224,230,237,242,248,252,258,261,266,269,276,282,285,289,294,302,306,311,
313,317,322,334,345,1,6,0,0
};
staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0]));
antlr4::atn::ATNDeserializer deserializer;
staticData->atn = deserializer.deserialize(staticData->serializedATN);
const size_t count = staticData->atn->getNumberOfDecisions();
staticData->decisionToDFA.reserve(count);
for (size_t i = 0; i < count; i++) {
staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i);
}
sysylexerLexerStaticData = std::move(staticData);
}
}
SysYLexer::SysYLexer(CharStream *input) : Lexer(input) {
SysYLexer::initialize();
_interpreter = new atn::LexerATNSimulator(this, *sysylexerLexerStaticData->atn, sysylexerLexerStaticData->decisionToDFA, sysylexerLexerStaticData->sharedContextCache);
}
SysYLexer::~SysYLexer() {
delete _interpreter;
}
std::string SysYLexer::getGrammarFileName() const {
return "SysY.g4";
}
const std::vector<std::string>& SysYLexer::getRuleNames() const {
return sysylexerLexerStaticData->ruleNames;
}
const std::vector<std::string>& SysYLexer::getChannelNames() const {
return sysylexerLexerStaticData->channelNames;
}
const std::vector<std::string>& SysYLexer::getModeNames() const {
return sysylexerLexerStaticData->modeNames;
}
const dfa::Vocabulary& SysYLexer::getVocabulary() const {
return sysylexerLexerStaticData->vocabulary;
}
antlr4::atn::SerializedATNView SysYLexer::getSerializedATN() const {
return sysylexerLexerStaticData->serializedATN;
}
const atn::ATN& SysYLexer::getATN() const {
return *sysylexerLexerStaticData->atn;
}
void SysYLexer::initialize() {
#if ANTLR4_USE_THREAD_LOCAL_CACHE
sysylexerLexerInitialize();
#else
::antlr4::internal::call_once(sysylexerLexerOnceFlag, sysylexerLexerInitialize);
#endif
}

@ -0,0 +1,54 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
class SysYLexer : public antlr4::Lexer {
public:
enum {
CONST = 1, INT = 2, FLOAT = 3, VOID = 4, IF = 5, ELSE = 6, WHILE = 7,
BREAK = 8, CONTINUE = 9, RETURN = 10, ASSIGN = 11, EQ = 12, NE = 13,
LT = 14, GT = 15, LE = 16, GE = 17, ADD = 18, SUB = 19, MUL = 20, DIV = 21,
MOD = 22, NOT = 23, AND = 24, OR = 25, LPAREN = 26, RPAREN = 27, LBRACK = 28,
RBRACK = 29, LBRACE = 30, RBRACE = 31, COMMA = 32, SEMICOLON = 33, ID = 34,
FLITERAL = 35, ILITERAL = 36, WS = 37, LINECOMMENT = 38, BLOCKCOMMENT = 39
};
explicit SysYLexer(antlr4::CharStream *input);
~SysYLexer() override;
std::string getGrammarFileName() const override;
const std::vector<std::string>& getRuleNames() const override;
const std::vector<std::string>& getChannelNames() const override;
const std::vector<std::string>& getModeNames() const override;
const antlr4::dfa::Vocabulary& getVocabulary() const override;
antlr4::atn::SerializedATNView getSerializedATN() const override;
const antlr4::atn::ATN& getATN() const override;
// By default the static state used to implement the lexer is lazily initialized during the first
// call to the constructor. You can call this function if you wish to initialize the static state
// ahead of time.
static void initialize();
private:
// Individual action functions triggered by action() above.
// Individual semantic predicate functions triggered by sempred() above.
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,641 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
class SysYParser : public antlr4::Parser {
public:
enum {
CONST = 1, INT = 2, FLOAT = 3, VOID = 4, IF = 5, ELSE = 6, WHILE = 7,
BREAK = 8, CONTINUE = 9, RETURN = 10, ASSIGN = 11, EQ = 12, NE = 13,
LT = 14, GT = 15, LE = 16, GE = 17, ADD = 18, SUB = 19, MUL = 20, DIV = 21,
MOD = 22, NOT = 23, AND = 24, OR = 25, LPAREN = 26, RPAREN = 27, LBRACK = 28,
RBRACK = 29, LBRACE = 30, RBRACE = 31, COMMA = 32, SEMICOLON = 33, ID = 34,
FLITERAL = 35, ILITERAL = 36, WS = 37, LINECOMMENT = 38, BLOCKCOMMENT = 39
};
enum {
RuleCompUnit = 0, RuleDecl = 1, RuleConstDecl = 2, RuleConstDef = 3,
RuleConstInitValue = 4, RuleVarDecl = 5, RuleBtype = 6, RuleVarDef = 7,
RuleInitValue = 8, RuleFuncDef = 9, RuleFuncType = 10, RuleFuncFParams = 11,
RuleFuncFParam = 12, RuleBlockStmt = 13, RuleBlockItem = 14, RuleStmt = 15,
RuleReturnStmt = 16, RuleExp = 17, RuleCond = 18, RuleLValue = 19, RulePrimaryExp = 20,
RuleNumber = 21, RuleUnaryExp = 22, RuleUnaryOp = 23, RuleFuncRParams = 24,
RuleMulExp = 25, RuleAddExp = 26, RuleRelExp = 27, RuleEqExp = 28, RuleLAndExp = 29,
RuleLOrExp = 30, RuleConstExp = 31
};
explicit SysYParser(antlr4::TokenStream *input);
SysYParser(antlr4::TokenStream *input, const antlr4::atn::ParserATNSimulatorOptions &options);
~SysYParser() override;
std::string getGrammarFileName() const override;
const antlr4::atn::ATN& getATN() const override;
const std::vector<std::string>& getRuleNames() const override;
const antlr4::dfa::Vocabulary& getVocabulary() const override;
antlr4::atn::SerializedATNView getSerializedATN() const override;
class CompUnitContext;
class DeclContext;
class ConstDeclContext;
class ConstDefContext;
class ConstInitValueContext;
class VarDeclContext;
class BtypeContext;
class VarDefContext;
class InitValueContext;
class FuncDefContext;
class FuncTypeContext;
class FuncFParamsContext;
class FuncFParamContext;
class BlockStmtContext;
class BlockItemContext;
class StmtContext;
class ReturnStmtContext;
class ExpContext;
class CondContext;
class LValueContext;
class PrimaryExpContext;
class NumberContext;
class UnaryExpContext;
class UnaryOpContext;
class FuncRParamsContext;
class MulExpContext;
class AddExpContext;
class RelExpContext;
class EqExpContext;
class LAndExpContext;
class LOrExpContext;
class ConstExpContext;
class CompUnitContext : public antlr4::ParserRuleContext {
public:
CompUnitContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *EOF();
std::vector<DeclContext *> decl();
DeclContext* decl(size_t i);
std::vector<FuncDefContext *> funcDef();
FuncDefContext* funcDef(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
CompUnitContext* compUnit();
class DeclContext : public antlr4::ParserRuleContext {
public:
DeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
ConstDeclContext *constDecl();
VarDeclContext *varDecl();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
DeclContext* decl();
class ConstDeclContext : public antlr4::ParserRuleContext {
public:
ConstDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *CONST();
BtypeContext *btype();
std::vector<ConstDefContext *> constDef();
ConstDefContext* constDef(size_t i);
antlr4::tree::TerminalNode *SEMICOLON();
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstDeclContext* constDecl();
class ConstDefContext : public antlr4::ParserRuleContext {
public:
ConstDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *ID();
antlr4::tree::TerminalNode *ASSIGN();
ConstInitValueContext *constInitValue();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<ConstExpContext *> constExp();
ConstExpContext* constExp(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstDefContext* constDef();
class ConstInitValueContext : public antlr4::ParserRuleContext {
public:
ConstInitValueContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
ConstExpContext *constExp();
antlr4::tree::TerminalNode *LBRACE();
antlr4::tree::TerminalNode *RBRACE();
std::vector<ConstInitValueContext *> constInitValue();
ConstInitValueContext* constInitValue(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstInitValueContext* constInitValue();
class VarDeclContext : public antlr4::ParserRuleContext {
public:
VarDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
BtypeContext *btype();
std::vector<VarDefContext *> varDef();
VarDefContext* varDef(size_t i);
antlr4::tree::TerminalNode *SEMICOLON();
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
VarDeclContext* varDecl();
class BtypeContext : public antlr4::ParserRuleContext {
public:
BtypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *INT();
antlr4::tree::TerminalNode *FLOAT();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BtypeContext* btype();
class VarDefContext : public antlr4::ParserRuleContext {
public:
VarDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *ID();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<ConstExpContext *> constExp();
ConstExpContext* constExp(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
antlr4::tree::TerminalNode *ASSIGN();
InitValueContext *initValue();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
VarDefContext* varDef();
class InitValueContext : public antlr4::ParserRuleContext {
public:
InitValueContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
ExpContext *exp();
antlr4::tree::TerminalNode *LBRACE();
antlr4::tree::TerminalNode *RBRACE();
std::vector<InitValueContext *> initValue();
InitValueContext* initValue(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
InitValueContext* initValue();
class FuncDefContext : public antlr4::ParserRuleContext {
public:
FuncDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
FuncTypeContext *funcType();
antlr4::tree::TerminalNode *ID();
antlr4::tree::TerminalNode *LPAREN();
antlr4::tree::TerminalNode *RPAREN();
BlockStmtContext *blockStmt();
FuncFParamsContext *funcFParams();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncDefContext* funcDef();
class FuncTypeContext : public antlr4::ParserRuleContext {
public:
FuncTypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *INT();
antlr4::tree::TerminalNode *FLOAT();
antlr4::tree::TerminalNode *VOID();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncTypeContext* funcType();
class FuncFParamsContext : public antlr4::ParserRuleContext {
public:
FuncFParamsContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
std::vector<FuncFParamContext *> funcFParam();
FuncFParamContext* funcFParam(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncFParamsContext* funcFParams();
class FuncFParamContext : public antlr4::ParserRuleContext {
public:
FuncFParamContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
BtypeContext *btype();
antlr4::tree::TerminalNode *ID();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
std::vector<ExpContext *> exp();
ExpContext* exp(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncFParamContext* funcFParam();
class BlockStmtContext : public antlr4::ParserRuleContext {
public:
BlockStmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *LBRACE();
antlr4::tree::TerminalNode *RBRACE();
std::vector<BlockItemContext *> blockItem();
BlockItemContext* blockItem(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BlockStmtContext* blockStmt();
class BlockItemContext : public antlr4::ParserRuleContext {
public:
BlockItemContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
DeclContext *decl();
StmtContext *stmt();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BlockItemContext* blockItem();
class StmtContext : public antlr4::ParserRuleContext {
public:
StmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
LValueContext *lValue();
antlr4::tree::TerminalNode *ASSIGN();
ExpContext *exp();
antlr4::tree::TerminalNode *SEMICOLON();
BlockStmtContext *blockStmt();
antlr4::tree::TerminalNode *IF();
antlr4::tree::TerminalNode *LPAREN();
CondContext *cond();
antlr4::tree::TerminalNode *RPAREN();
std::vector<StmtContext *> stmt();
StmtContext* stmt(size_t i);
antlr4::tree::TerminalNode *ELSE();
antlr4::tree::TerminalNode *WHILE();
antlr4::tree::TerminalNode *BREAK();
antlr4::tree::TerminalNode *CONTINUE();
ReturnStmtContext *returnStmt();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
StmtContext* stmt();
class ReturnStmtContext : public antlr4::ParserRuleContext {
public:
ReturnStmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *RETURN();
antlr4::tree::TerminalNode *SEMICOLON();
ExpContext *exp();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ReturnStmtContext* returnStmt();
class ExpContext : public antlr4::ParserRuleContext {
public:
ExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
AddExpContext *addExp();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ExpContext* exp();
class CondContext : public antlr4::ParserRuleContext {
public:
CondContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
LOrExpContext *lOrExp();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
CondContext* cond();
class LValueContext : public antlr4::ParserRuleContext {
public:
LValueContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *ID();
std::vector<antlr4::tree::TerminalNode *> LBRACK();
antlr4::tree::TerminalNode* LBRACK(size_t i);
std::vector<ExpContext *> exp();
ExpContext* exp(size_t i);
std::vector<antlr4::tree::TerminalNode *> RBRACK();
antlr4::tree::TerminalNode* RBRACK(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
LValueContext* lValue();
class PrimaryExpContext : public antlr4::ParserRuleContext {
public:
PrimaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *LPAREN();
ExpContext *exp();
antlr4::tree::TerminalNode *RPAREN();
LValueContext *lValue();
NumberContext *number();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
PrimaryExpContext* primaryExp();
class NumberContext : public antlr4::ParserRuleContext {
public:
NumberContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *ILITERAL();
antlr4::tree::TerminalNode *FLITERAL();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
NumberContext* number();
class UnaryExpContext : public antlr4::ParserRuleContext {
public:
UnaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
PrimaryExpContext *primaryExp();
antlr4::tree::TerminalNode *ID();
antlr4::tree::TerminalNode *LPAREN();
antlr4::tree::TerminalNode *RPAREN();
FuncRParamsContext *funcRParams();
UnaryOpContext *unaryOp();
UnaryExpContext *unaryExp();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
UnaryExpContext* unaryExp();
class UnaryOpContext : public antlr4::ParserRuleContext {
public:
UnaryOpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *ADD();
antlr4::tree::TerminalNode *SUB();
antlr4::tree::TerminalNode *NOT();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
UnaryOpContext* unaryOp();
class FuncRParamsContext : public antlr4::ParserRuleContext {
public:
FuncRParamsContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
std::vector<ExpContext *> exp();
ExpContext* exp(size_t i);
std::vector<antlr4::tree::TerminalNode *> COMMA();
antlr4::tree::TerminalNode* COMMA(size_t i);
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncRParamsContext* funcRParams();
class MulExpContext : public antlr4::ParserRuleContext {
public:
MulExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
UnaryExpContext *unaryExp();
MulExpContext *mulExp();
antlr4::tree::TerminalNode *MUL();
antlr4::tree::TerminalNode *DIV();
antlr4::tree::TerminalNode *MOD();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
MulExpContext* mulExp();
MulExpContext* mulExp(int precedence);
class AddExpContext : public antlr4::ParserRuleContext {
public:
AddExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
MulExpContext *mulExp();
AddExpContext *addExp();
antlr4::tree::TerminalNode *ADD();
antlr4::tree::TerminalNode *SUB();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
AddExpContext* addExp();
AddExpContext* addExp(int precedence);
class RelExpContext : public antlr4::ParserRuleContext {
public:
RelExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
AddExpContext *addExp();
RelExpContext *relExp();
antlr4::tree::TerminalNode *LT();
antlr4::tree::TerminalNode *GT();
antlr4::tree::TerminalNode *LE();
antlr4::tree::TerminalNode *GE();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
RelExpContext* relExp();
RelExpContext* relExp(int precedence);
class EqExpContext : public antlr4::ParserRuleContext {
public:
EqExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
RelExpContext *relExp();
EqExpContext *eqExp();
antlr4::tree::TerminalNode *EQ();
antlr4::tree::TerminalNode *NE();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
EqExpContext* eqExp();
EqExpContext* eqExp(int precedence);
class LAndExpContext : public antlr4::ParserRuleContext {
public:
LAndExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
EqExpContext *eqExp();
LAndExpContext *lAndExp();
antlr4::tree::TerminalNode *AND();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
LAndExpContext* lAndExp();
LAndExpContext* lAndExp(int precedence);
class LOrExpContext : public antlr4::ParserRuleContext {
public:
LOrExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
LAndExpContext *lAndExp();
LOrExpContext *lOrExp();
antlr4::tree::TerminalNode *OR();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
LOrExpContext* lOrExp();
LOrExpContext* lOrExp(int precedence);
class ConstExpContext : public antlr4::ParserRuleContext {
public:
ConstExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
AddExpContext *addExp();
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstExpContext* constExp();
bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override;
bool mulExpSempred(MulExpContext *_localctx, size_t predicateIndex);
bool addExpSempred(AddExpContext *_localctx, size_t predicateIndex);
bool relExpSempred(RelExpContext *_localctx, size_t predicateIndex);
bool eqExpSempred(EqExpContext *_localctx, size_t predicateIndex);
bool lAndExpSempred(LAndExpContext *_localctx, size_t predicateIndex);
bool lOrExpSempred(LOrExpContext *_localctx, size_t predicateIndex);
// By default the static state used to implement the parser is lazily initialized during the first
// call to the constructor. You can call this function if you wish to initialize the static state
// ahead of time.
static void initialize();
private:
};

@ -0,0 +1,7 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#include "SysYVisitor.h"

@ -0,0 +1,88 @@
// Generated from SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
#include "SysYParser.h"
/**
* This class defines an abstract visitor for a parse tree
* produced by SysYParser.
*/
class SysYVisitor : public antlr4::tree::AbstractParseTreeVisitor {
public:
/**
* Visit parse trees produced by SysYParser.
*/
virtual std::any visitCompUnit(SysYParser::CompUnitContext *context) = 0;
virtual std::any visitDecl(SysYParser::DeclContext *context) = 0;
virtual std::any visitConstDecl(SysYParser::ConstDeclContext *context) = 0;
virtual std::any visitConstDef(SysYParser::ConstDefContext *context) = 0;
virtual std::any visitConstInitValue(SysYParser::ConstInitValueContext *context) = 0;
virtual std::any visitVarDecl(SysYParser::VarDeclContext *context) = 0;
virtual std::any visitBtype(SysYParser::BtypeContext *context) = 0;
virtual std::any visitVarDef(SysYParser::VarDefContext *context) = 0;
virtual std::any visitInitValue(SysYParser::InitValueContext *context) = 0;
virtual std::any visitFuncDef(SysYParser::FuncDefContext *context) = 0;
virtual std::any visitFuncType(SysYParser::FuncTypeContext *context) = 0;
virtual std::any visitFuncFParams(SysYParser::FuncFParamsContext *context) = 0;
virtual std::any visitFuncFParam(SysYParser::FuncFParamContext *context) = 0;
virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *context) = 0;
virtual std::any visitBlockItem(SysYParser::BlockItemContext *context) = 0;
virtual std::any visitStmt(SysYParser::StmtContext *context) = 0;
virtual std::any visitReturnStmt(SysYParser::ReturnStmtContext *context) = 0;
virtual std::any visitExp(SysYParser::ExpContext *context) = 0;
virtual std::any visitCond(SysYParser::CondContext *context) = 0;
virtual std::any visitLValue(SysYParser::LValueContext *context) = 0;
virtual std::any visitPrimaryExp(SysYParser::PrimaryExpContext *context) = 0;
virtual std::any visitNumber(SysYParser::NumberContext *context) = 0;
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *context) = 0;
virtual std::any visitUnaryOp(SysYParser::UnaryOpContext *context) = 0;
virtual std::any visitFuncRParams(SysYParser::FuncRParamsContext *context) = 0;
virtual std::any visitMulExp(SysYParser::MulExpContext *context) = 0;
virtual std::any visitAddExp(SysYParser::AddExpContext *context) = 0;
virtual std::any visitRelExp(SysYParser::RelExpContext *context) = 0;
virtual std::any visitEqExp(SysYParser::EqExpContext *context) = 0;
virtual std::any visitLAndExp(SysYParser::LAndExpContext *context) = 0;
virtual std::any visitLOrExp(SysYParser::LOrExpContext *context) = 0;
virtual std::any visitConstExp(SysYParser::ConstExpContext *context) = 0;
};

@ -6,8 +6,8 @@
#include <stdexcept>
#include <string>
#include "SysYLexer.h"
#include "SysYParser.h"
#include "antlr4/SysYLexer.h"
#include "antlr4/SysYParser.h"
#include "antlr4-runtime.h"
#include "utils/Log.h"

@ -8,9 +8,10 @@ target_link_libraries(frontend PUBLIC
${ANTLR4_RUNTIME_TARGET}
)
# Lexer/Parser
# Lexer/Parser src/antlr4
file(GLOB_RECURSE ANTLR4_GENERATED_SOURCES CONFIGURE_DEPENDS
"${ANTLR4_GENERATED_DIR}/*.cpp"
"${PROJECT_SOURCE_DIR}/src/antlr4/*.cpp"
)
if(ANTLR4_GENERATED_SOURCES)
target_sources(frontend PRIVATE ${ANTLR4_GENERATED_SOURCES})

@ -9,6 +9,7 @@
#include "ir/IR.h"
#include <algorithm>
#include <utility>
namespace ir {
@ -42,4 +43,26 @@ const std::vector<BasicBlock*>& BasicBlock::GetSuccessors() const {
return successors_;
}
void BasicBlock::AddPredecessor(BasicBlock* pred) {
if (!pred) {
return;
}
if (std::find(predecessors_.begin(), predecessors_.end(), pred) !=
predecessors_.end()) {
return;
}
predecessors_.push_back(pred);
}
void BasicBlock::AddSuccessor(BasicBlock* succ) {
if (!succ) {
return;
}
if (std::find(successors_.begin(), successors_.end(), succ) !=
successors_.end()) {
return;
}
successors_.push_back(succ);
}
} // namespace ir

@ -5,8 +5,10 @@
namespace ir {
Function::Function(std::string name, std::shared_ptr<Type> ret_type)
: Value(std::move(ret_type), std::move(name)) {
Function::Function(std::string name, std::shared_ptr<Type> ret_type,
std::vector<std::shared_ptr<Type>> param_types)
: Value(std::move(ret_type), std::move(name)),
param_types_(std::move(param_types)) {
entry_ = CreateBlock("entry");
}
@ -25,6 +27,12 @@ BasicBlock* Function::GetEntry() { return entry_; }
const BasicBlock* Function::GetEntry() const { return entry_; }
const std::vector<std::shared_ptr<Type>>& Function::GetParamTypes() const {
return param_types_;
}
size_t Function::GetNumParams() const { return param_types_.size(); }
const std::vector<std::unique_ptr<BasicBlock>>& Function::GetBlocks() const {
return blocks_;
}

@ -42,6 +42,39 @@ BinaryInst* IRBuilder::CreateAdd(Value* lhs, Value* rhs,
return CreateBinary(Opcode::Add, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateSub(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Sub, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateMul(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Mul, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateDiv(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Div, lhs, rhs, name);
}
BinaryInst* IRBuilder::CreateMod(Value* lhs, Value* rhs,
const std::string& name) {
return CreateBinary(Opcode::Mod, lhs, rhs, name);
}
CmpInst* IRBuilder::CreateCmp(CmpOp op, Value* lhs, Value* rhs,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!lhs || !rhs) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCmp 缺少操作数"));
}
return insert_block_->Append<CmpInst>(op, Type::GetInt32Type(), lhs, rhs,
name);
}
AllocaInst* IRBuilder::CreateAllocaI32(const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
@ -75,6 +108,43 @@ StoreInst* IRBuilder::CreateStore(Value* val, Value* ptr) {
return insert_block_->Append<StoreInst>(Type::GetVoidType(), val, ptr);
}
BranchInst* IRBuilder::CreateBr(BasicBlock* target) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!target) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateBr 缺少目标块"));
}
return insert_block_->Append<BranchInst>(Type::GetVoidType(), target);
}
CondBranchInst* IRBuilder::CreateCondBr(Value* cond, BasicBlock* true_bb,
BasicBlock* false_bb) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!cond || !true_bb || !false_bb) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCondBr 参数不完整"));
}
return insert_block_->Append<CondBranchInst>(Type::GetVoidType(), cond,
true_bb, false_bb);
}
CallInst* IRBuilder::CreateCall(Function* callee,
const std::vector<Value*>& args,
const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
}
if (!callee) {
throw std::runtime_error(
FormatError("ir", "IRBuilder::CreateCall 缺少被调函数"));
}
return insert_block_->Append<CallInst>(callee->GetType(), callee, args, name);
}
ReturnInst* IRBuilder::CreateRet(Value* v) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));

@ -32,6 +32,18 @@ static const char* OpcodeToString(Opcode op) {
return "sub";
case Opcode::Mul:
return "mul";
case Opcode::Div:
return "sdiv";
case Opcode::Mod:
return "srem";
case Opcode::Cmp:
return "icmp";
case Opcode::Br:
return "br";
case Opcode::CondBr:
return "br";
case Opcode::Call:
return "call";
case Opcode::Alloca:
return "alloca";
case Opcode::Load:
@ -44,17 +56,47 @@ static const char* OpcodeToString(Opcode op) {
return "?";
}
static const char* CmpOpToString(CmpOp op) {
switch (op) {
case CmpOp::Eq:
return "eq";
case CmpOp::Ne:
return "ne";
case CmpOp::Lt:
return "slt";
case CmpOp::Le:
return "sle";
case CmpOp::Gt:
return "sgt";
case CmpOp::Ge:
return "sge";
}
return "?";
}
static std::string ValueToString(const Value* v) {
if (auto* ci = dynamic_cast<const ConstantInt*>(v)) {
return std::to_string(ci->GetValue());
}
if (auto* func = dynamic_cast<const Function*>(v)) {
return "@" + func->GetName();
}
return v ? v->GetName() : "<null>";
}
void IRPrinter::Print(const Module& module, std::ostream& os) {
for (const auto& func : module.GetFunctions()) {
std::string params;
const auto& param_types = func->GetParamTypes();
for (size_t i = 0; i < param_types.size(); ++i) {
if (i != 0) {
params += ", ";
}
params += TypeToString(*param_types[i]);
params += " %arg" + std::to_string(i);
}
os << "define " << TypeToString(*func->GetType()) << " @" << func->GetName()
<< "() {\n";
<< "(" << params << ") {\n";
for (const auto& bb : func->GetBlocks()) {
if (!bb) {
continue;
@ -65,7 +107,9 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
switch (inst->GetOpcode()) {
case Opcode::Add:
case Opcode::Sub:
case Opcode::Mul: {
case Opcode::Mul:
case Opcode::Div:
case Opcode::Mod: {
auto* bin = static_cast<const BinaryInst*>(inst);
os << " " << bin->GetName() << " = "
<< OpcodeToString(bin->GetOpcode()) << " "
@ -74,6 +118,15 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
<< ValueToString(bin->GetRhs()) << "\n";
break;
}
case Opcode::Cmp: {
auto* cmp = static_cast<const CmpInst*>(inst);
os << " " << cmp->GetName() << " = " << OpcodeToString(cmp->GetOpcode())
<< " " << CmpOpToString(cmp->GetCmpOp()) << " "
<< TypeToString(*cmp->GetLhs()->GetType()) << " "
<< ValueToString(cmp->GetLhs()) << ", "
<< ValueToString(cmp->GetRhs()) << "\n";
break;
}
case Opcode::Alloca: {
auto* alloca = static_cast<const AllocaInst*>(inst);
os << " " << alloca->GetName() << " = alloca i32\n";
@ -91,6 +144,37 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
<< ", i32* " << ValueToString(store->GetPtr()) << "\n";
break;
}
case Opcode::Br: {
auto* br = static_cast<const BranchInst*>(inst);
os << " br label %" << br->GetTarget()->GetName() << "\n";
break;
}
case Opcode::CondBr: {
auto* cbr = static_cast<const CondBranchInst*>(inst);
os << " br i32 " << ValueToString(cbr->GetCond()) << ", label %"
<< cbr->GetTrueBlock()->GetName() << ", label %"
<< cbr->GetFalseBlock()->GetName() << "\n";
break;
}
case Opcode::Call: {
auto* call = static_cast<const CallInst*>(inst);
if (!call->GetType()->IsVoid()) {
os << " " << call->GetName() << " = ";
} else {
os << " ";
}
os << "call " << TypeToString(*call->GetType()) << " @"
<< call->GetCallee()->GetName() << "(";
for (size_t i = 0; i < call->GetNumArgs(); ++i) {
if (i != 0) {
os << ", ";
}
auto* arg = call->GetArg(i);
os << TypeToString(*arg->GetType()) << " " << ValueToString(arg);
}
os << ")\n";
break;
}
case Opcode::Ret: {
auto* ret = static_cast<const ReturnInst*>(inst);
os << " ret " << TypeToString(*ret->GetValue()->GetType()) << " "

@ -3,7 +3,9 @@
// - 指令操作数与结果类型管理,支持打印与优化
#include "ir/IR.h"
#include <algorithm>
#include <stdexcept>
#include <utility>
#include "utils/Log.h"
@ -52,17 +54,44 @@ Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
Opcode Instruction::GetOpcode() const { return opcode_; }
bool Instruction::IsTerminator() const { return opcode_ == Opcode::Ret; }
bool Instruction::IsTerminator() const {
return opcode_ == Opcode::Ret || opcode_ == Opcode::Br ||
opcode_ == Opcode::CondBr;
}
BasicBlock* Instruction::GetParent() const { return parent_; }
void Instruction::SetParent(BasicBlock* parent) { parent_ = parent; }
void Instruction::SetParent(BasicBlock* parent) {
parent_ = parent;
if (!parent_) {
return;
}
if (auto* br = dynamic_cast<BranchInst*>(this)) {
auto* target = br->GetTarget();
parent_->AddSuccessor(target);
target->AddPredecessor(parent_);
return;
}
if (auto* cbr = dynamic_cast<CondBranchInst*>(this)) {
auto* true_bb = cbr->GetTrueBlock();
auto* false_bb = cbr->GetFalseBlock();
parent_->AddSuccessor(true_bb);
true_bb->AddPredecessor(parent_);
parent_->AddSuccessor(false_bb);
false_bb->AddPredecessor(parent_);
}
}
static bool IsBinaryOpcode(Opcode op) {
return op == Opcode::Add || op == Opcode::Sub || op == Opcode::Mul ||
op == Opcode::Div || op == Opcode::Mod;
}
BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
Value* rhs, std::string name)
: Instruction(op, std::move(ty), std::move(name)) {
if (op != Opcode::Add) {
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 Add"));
if (!IsBinaryOpcode(op)) {
throw std::runtime_error(FormatError("ir", "BinaryInst 非法二元操作码"));
}
if (!lhs || !rhs) {
throw std::runtime_error(FormatError("ir", "BinaryInst 缺少操作数"));
@ -85,6 +114,31 @@ Value* BinaryInst::GetLhs() const { return GetOperand(0); }
Value* BinaryInst::GetRhs() const { return GetOperand(1); }
CmpInst::CmpInst(CmpOp op, std::shared_ptr<Type> ty, Value* lhs, Value* rhs,
std::string name)
: Instruction(Opcode::Cmp, std::move(ty), std::move(name)), cmp_op_(op) {
if (!lhs || !rhs) {
throw std::runtime_error(FormatError("ir", "CmpInst 缺少操作数"));
}
if (!type_ || !lhs->GetType() || !rhs->GetType()) {
throw std::runtime_error(FormatError("ir", "CmpInst 缺少类型信息"));
}
if (!type_->IsInt32()) {
throw std::runtime_error(FormatError("ir", "CmpInst 结果类型必须为 i32"));
}
if (!lhs->GetType()->IsInt32() || !rhs->GetType()->IsInt32()) {
throw std::runtime_error(FormatError("ir", "CmpInst 当前只支持 i32 比较"));
}
AddOperand(lhs);
AddOperand(rhs);
}
CmpOp CmpInst::GetCmpOp() const { return cmp_op_; }
Value* CmpInst::GetLhs() const { return GetOperand(0); }
Value* CmpInst::GetRhs() const { return GetOperand(1); }
ReturnInst::ReturnInst(std::shared_ptr<Type> void_ty, Value* val)
: Instruction(Opcode::Ret, std::move(void_ty), "") {
if (!val) {
@ -148,4 +202,87 @@ Value* StoreInst::GetValue() const { return GetOperand(0); }
Value* StoreInst::GetPtr() const { return GetOperand(1); }
BranchInst::BranchInst(std::shared_ptr<Type> void_ty, BasicBlock* target)
: Instruction(Opcode::Br, std::move(void_ty), "") {
if (!target) {
throw std::runtime_error(FormatError("ir", "BranchInst 缺少目标块"));
}
if (!type_ || !type_->IsVoid()) {
throw std::runtime_error(FormatError("ir", "BranchInst 返回类型必须为 void"));
}
AddOperand(target);
}
BasicBlock* BranchInst::GetTarget() const {
return static_cast<BasicBlock*>(GetOperand(0));
}
CondBranchInst::CondBranchInst(std::shared_ptr<Type> void_ty, Value* cond,
BasicBlock* true_bb, BasicBlock* false_bb)
: Instruction(Opcode::CondBr, std::move(void_ty), "") {
if (!cond || !true_bb || !false_bb) {
throw std::runtime_error(FormatError("ir", "CondBranchInst 参数不完整"));
}
if (!type_ || !type_->IsVoid()) {
throw std::runtime_error(
FormatError("ir", "CondBranchInst 返回类型必须为 void"));
}
if (!cond->GetType() || !cond->GetType()->IsInt32()) {
throw std::runtime_error(FormatError("ir", "CondBranchInst 条件必须为 i32"));
}
AddOperand(cond);
AddOperand(true_bb);
AddOperand(false_bb);
}
Value* CondBranchInst::GetCond() const { return GetOperand(0); }
BasicBlock* CondBranchInst::GetTrueBlock() const {
return static_cast<BasicBlock*>(GetOperand(1));
}
BasicBlock* CondBranchInst::GetFalseBlock() const {
return static_cast<BasicBlock*>(GetOperand(2));
}
CallInst::CallInst(std::shared_ptr<Type> ret_ty, Function* callee,
std::vector<Value*> args, std::string name)
: Instruction(Opcode::Call, std::move(ret_ty), std::move(name)) {
if (!callee) {
throw std::runtime_error(FormatError("ir", "CallInst 缺少被调函数"));
}
const auto& param_types = callee->GetParamTypes();
if (args.size() != param_types.size()) {
throw std::runtime_error(FormatError("ir", "CallInst 参数个数不匹配"));
}
if (!type_ || !callee->GetType() || type_->GetKind() != callee->GetType()->GetKind()) {
throw std::runtime_error(FormatError("ir", "CallInst 返回类型与函数签名不匹配"));
}
AddOperand(callee);
for (size_t i = 0; i < args.size(); ++i) {
auto* arg = args[i];
if (!arg || !arg->GetType()) {
throw std::runtime_error(FormatError("ir", "CallInst 存在非法参数"));
}
if (!param_types[i] || arg->GetType()->GetKind() != param_types[i]->GetKind()) {
throw std::runtime_error(FormatError("ir", "CallInst 参数类型不匹配"));
}
AddOperand(arg);
}
}
Function* CallInst::GetCallee() const {
return static_cast<Function*>(GetOperand(0));
}
size_t CallInst::GetNumArgs() const { return GetNumOperands() - 1; }
Value* CallInst::GetArg(size_t index) const {
if (index >= GetNumArgs()) {
throw std::out_of_range("CallInst arg index out of range");
}
return GetOperand(index + 1);
}
} // namespace ir

@ -9,8 +9,10 @@ Context& Module::GetContext() { return context_; }
const Context& Module::GetContext() const { return context_; }
Function* Module::CreateFunction(const std::string& name,
std::shared_ptr<Type> ret_type) {
functions_.push_back(std::make_unique<Function>(name, std::move(ret_type)));
std::shared_ptr<Type> ret_type,
std::vector<std::shared_ptr<Type>> param_types) {
functions_.push_back(std::make_unique<Function>(
name, std::move(ret_type), std::move(param_types)));
return functions_.back().get();
}

@ -2,7 +2,7 @@
#include <stdexcept>
#include "SysYParser.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
@ -21,6 +21,8 @@ std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
}
// 进入新作用域
scope_storage_.emplace_back();
for (auto* item : ctx->blockItem()) {
if (item) {
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
@ -29,6 +31,8 @@ std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
}
}
}
// 退出作用域
scope_storage_.pop_back();
return {};
}
@ -60,17 +64,46 @@ std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
// - const、数组、全局变量等不同声明形态
// - 更丰富的类型系统。
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
if (!ctx->varDecl()) {
// 当前先忽略 constDecl 与其它声明形态。
return {};
}
if (!in_function_) {
// 全局变量处理路径
for (auto* var_def : ctx->varDecl()->varDef()) {
if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
}
EmitGlobalVariable(var_def);
}
return {};
}
return ctx->varDecl()->accept(this);
}
std::any IRGenImpl::visitVarDecl(SysYParser::VarDeclContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
}
if (!ctx->btype() || !ctx->btype()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
throw std::runtime_error(FormatError("irgen", "当前仅支持 int 类型变量声明"));
}
auto* var_def = ctx->varDef();
if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
for (auto* var_def : ctx->varDef()) {
if (!var_def) {
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
}
if (in_function_) {
var_def->accept(this);
} else {
EmitGlobalVariable(var_def);
}
}
var_def->accept(this);
return {};
}
@ -83,15 +116,28 @@ std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少变量定义"));
}
if (!ctx->lValue()) {
if (!ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
}
GetLValueName(*ctx->lValue());
const std::string name = ctx->ID()->getText();
// 数组语义暂时不支持,先提示
if (!ctx->LBRACK().empty()) {
throw std::runtime_error(FormatError("irgen", "暂不支持数组声明和初始化"));
}
if (storage_map_.find(ctx) != storage_map_.end()) {
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
}
// const 变量在 Sema 中可扩展为常量折叠,当前暂时和普通变量一样处理
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
storage_map_[ctx] = slot;
// 添加到当前作用域
if (!scope_storage_.empty()) {
scope_storage_.back()[name] = slot;
}
named_storage_[name] = slot;
ir::Value* init = nullptr;
if (auto* init_value = ctx->initValue()) {

@ -2,7 +2,7 @@
#include <memory>
#include "SysYParser.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"

@ -2,7 +2,7 @@
#include <stdexcept>
#include "SysYParser.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
@ -24,21 +24,70 @@ ir::Value* IRGenImpl::EvalExpr(SysYParser::ExpContext& expr) {
return std::any_cast<ir::Value*>(expr.accept(this));
}
ir::Value* IRGenImpl::EvalCond(SysYParser::CondContext& cond) {
return std::any_cast<ir::Value*>(cond.accept(this));
}
ir::Value* IRGenImpl::ToBoolValue(ir::Value* v) {
if (!v) {
throw std::runtime_error(FormatError("irgen", "条件值为空"));
}
auto* zero = builder_.CreateConstInt(0);
return builder_.CreateCmp(ir::CmpOp::Ne, v, zero, module_.GetContext().NextTemp());
}
std::any IRGenImpl::visitParenExp(SysYParser::ParenExpContext* ctx) {
if (!ctx || !ctx->exp()) {
throw std::runtime_error(FormatError("irgen", "非法括号表达式"));
ir::Value* IRGenImpl::FindInScope(const std::string& name) {
for (auto it = scope_storage_.rbegin(); it != scope_storage_.rend(); ++it) {
auto found = it->find(name);
if (found != it->end()) return found->second;
}
return EvalExpr(*ctx->exp());
return nullptr;
}
std::string IRGenImpl::NextBlockName() {
std::string temp = module_.GetContext().NextTemp();
if (!temp.empty() && temp.front() == '%') {
return "bb" + temp.substr(1);
}
return "bb" + temp;
}
std::any IRGenImpl::visitNumberExp(SysYParser::NumberExpContext* ctx) {
if (!ctx || !ctx->number() || !ctx->number()->ILITERAL()) {
std::any IRGenImpl::visitExp(SysYParser::ExpContext* ctx) {
if (!ctx || !ctx->addExp()) {
throw std::runtime_error(FormatError("irgen", "非法表达式"));
}
return ctx->addExp()->accept(this);
}
std::any IRGenImpl::visitCond(SysYParser::CondContext* ctx) {
if (!ctx || !ctx->lOrExp()) {
throw std::runtime_error(FormatError("irgen", "非法条件表达式"));
}
return ctx->lOrExp()->accept(this);
}
std::any IRGenImpl::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法基本表达式"));
}
if (ctx->exp()) {
return EvalExpr(*ctx->exp());
}
if (ctx->number()) {
return ctx->number()->accept(this);
}
if (ctx->lValue()) {
return ctx->lValue()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "不支持的基本表达式"));
}
std::any IRGenImpl::visitNumber(SysYParser::NumberContext* ctx) {
if (!ctx || !ctx->ILITERAL()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量"));
}
return static_cast<ir::Value*>(
builder_.CreateConstInt(std::stoi(ctx->number()->getText())));
builder_.CreateConstInt(std::stoi(ctx->getText())));
}
// 变量使用的处理流程:
@ -47,34 +96,277 @@ std::any IRGenImpl::visitNumberExp(SysYParser::NumberExpContext* ctx) {
// 3. 最后生成 load把内存中的值读出来。
//
// 因此当前 IRGen 自己不再做名字查找,而是直接消费 Sema 的绑定结果。
std::any IRGenImpl::visitVarExp(SysYParser::VarExpContext* ctx) {
if (!ctx || !ctx->var() || !ctx->var()->ID()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持普通整型变量"));
}
auto* decl = sema_.ResolveVarUse(ctx->var());
if (!decl) {
throw std::runtime_error(
FormatError("irgen",
"变量使用缺少语义绑定: " + ctx->var()->ID()->getText()));
}
auto it = storage_map_.find(decl);
if (it == storage_map_.end()) {
throw std::runtime_error(
FormatError("irgen",
"变量声明缺少存储槽位: " + ctx->var()->ID()->getText()));
std::any IRGenImpl::visitLValue(SysYParser::LValueContext* ctx) {
auto* addr = ResolveLValueAddress(ctx);
if (!addr) {
throw std::runtime_error(FormatError("irgen", "变量地址解析失败"));
}
return static_cast<ir::Value*>(
builder_.CreateLoad(it->second, module_.GetContext().NextTemp()));
builder_.CreateLoad(addr, module_.GetContext().NextTemp()));
}
std::any IRGenImpl::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法一元表达式"));
}
if (ctx->primaryExp()) {
return ctx->primaryExp()->accept(this);
}
std::any IRGenImpl::visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) {
if (!ctx || !ctx->exp(0) || !ctx->exp(1)) {
if (ctx->ID() && ctx->LPAREN()) {
auto func_name = ctx->ID()->getText();
ir::Function* callee = FindFunctionByName(func_name);
if (!callee) {
throw std::runtime_error(FormatError("irgen", "函数未定义: " + func_name));
}
std::vector<ir::Value*> args;
if (ctx->funcRParams()) {
for (auto* exp : ctx->funcRParams()->exp()) {
if (!exp) {
throw std::runtime_error(FormatError("irgen", "函数参数缺失"));
}
args.push_back(EvalExpr(*exp));
}
}
auto* call = builder_.CreateCall(callee, args, module_.GetContext().NextTemp());
if (callee->GetType()->IsVoid()) {
// void 类型调用表达式在值上下文下暂时返回 0。
return static_cast<ir::Value*>(builder_.CreateConstInt(0));
}
return static_cast<ir::Value*>(call);
}
if (ctx->unaryOp() && ctx->unaryExp()) {
ir::Value* v = std::any_cast<ir::Value*>(ctx->unaryExp()->accept(this));
if (ctx->unaryOp()->SUB()) {
auto* zero = builder_.CreateConstInt(0);
return static_cast<ir::Value*>(builder_.CreateSub(
zero, v, module_.GetContext().NextTemp()));
}
if (ctx->unaryOp()->ADD()) {
return v;
}
if (ctx->unaryOp()->NOT()) {
auto* zero = builder_.CreateConstInt(0);
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Eq, v, zero, module_.GetContext().NextTemp()));
}
throw std::runtime_error(FormatError("irgen", "非法一元运算符"));
}
throw std::runtime_error(FormatError("irgen", "非法一元表达式"));
}
ir::Function* IRGenImpl::FindFunctionByName(const std::string& name) {
for (const auto& func : module_.GetFunctions()) {
if (func && func->GetName() == name) {
return func.get();
}
}
return nullptr;
}
std::any IRGenImpl::visitMulExp(SysYParser::MulExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法乘法表达式"));
}
if (ctx->mulExp()) {
if (!ctx->unaryExp()) {
throw std::runtime_error(FormatError("irgen", "非法乘法表达式"));
}
ir::Value* lhs = std::any_cast<ir::Value*>(ctx->mulExp()->accept(this));
ir::Value* rhs = std::any_cast<ir::Value*>(ctx->unaryExp()->accept(this));
if (ctx->MUL()) {
return static_cast<ir::Value*>(
builder_.CreateMul(lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->DIV()) {
return static_cast<ir::Value*>(
builder_.CreateDiv(lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->MOD()) {
return static_cast<ir::Value*>(
builder_.CreateMod(lhs, rhs, module_.GetContext().NextTemp()));
}
throw std::runtime_error(FormatError("irgen", "非法乘法表达式"));
}
if (ctx->unaryExp()) {
return ctx->unaryExp()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "非法乘法表达式"));
}
std::any IRGenImpl::visitAddExp(SysYParser::AddExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法加法表达式"));
}
if (ctx->addExp()) {
if (!ctx->mulExp()) {
throw std::runtime_error(FormatError("irgen", "非法加法表达式"));
}
ir::Value* lhs = std::any_cast<ir::Value*>(ctx->addExp()->accept(this));
ir::Value* rhs = std::any_cast<ir::Value*>(ctx->mulExp()->accept(this));
if (ctx->ADD()) {
return static_cast<ir::Value*>(
builder_.CreateAdd(lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->SUB()) {
return static_cast<ir::Value*>(
builder_.CreateSub(lhs, rhs, module_.GetContext().NextTemp()));
}
throw std::runtime_error(FormatError("irgen", "非法加法表达式"));
}
ir::Value* lhs = EvalExpr(*ctx->exp(0));
ir::Value* rhs = EvalExpr(*ctx->exp(1));
if (ctx->mulExp()) {
return ctx->mulExp()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "非法加法表达式"));
}
std::any IRGenImpl::visitRelExp(SysYParser::RelExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法关系表达式"));
}
if (ctx->relExp()) {
if (!ctx->addExp()) {
throw std::runtime_error(FormatError("irgen", "非法关系表达式"));
}
ir::Value* lhs = std::any_cast<ir::Value*>(ctx->relExp()->accept(this));
ir::Value* rhs = std::any_cast<ir::Value*>(ctx->addExp()->accept(this));
if (ctx->LT()) {
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Lt, lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->LE()) {
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Le, lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->GT()) {
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Gt, lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->GE()) {
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Ge, lhs, rhs, module_.GetContext().NextTemp()));
}
throw std::runtime_error(FormatError("irgen", "非法关系表达式"));
}
if (ctx->addExp()) {
return ctx->addExp()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "非法关系表达式"));
}
std::any IRGenImpl::visitEqExp(SysYParser::EqExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法相等表达式"));
}
if (ctx->eqExp()) {
if (!ctx->relExp()) {
throw std::runtime_error(FormatError("irgen", "非法相等表达式"));
}
ir::Value* lhs = std::any_cast<ir::Value*>(ctx->eqExp()->accept(this));
ir::Value* rhs = std::any_cast<ir::Value*>(ctx->relExp()->accept(this));
if (ctx->EQ()) {
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Eq, lhs, rhs, module_.GetContext().NextTemp()));
}
if (ctx->NE()) {
return static_cast<ir::Value*>(builder_.CreateCmp(
ir::CmpOp::Ne, lhs, rhs, module_.GetContext().NextTemp()));
}
throw std::runtime_error(FormatError("irgen", "非法相等表达式"));
}
if (ctx->relExp()) {
return ctx->relExp()->accept(this);
}
throw std::runtime_error(FormatError("irgen", "非法相等表达式"));
}
std::any IRGenImpl::visitLAndExp(SysYParser::LAndExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
}
if (!ctx->lAndExp()) {
if (ctx->eqExp()) {
return ToBoolValue(std::any_cast<ir::Value*>(ctx->eqExp()->accept(this)));
}
throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
}
if (!ctx->eqExp()) {
throw std::runtime_error(FormatError("irgen", "非法逻辑与表达式"));
}
auto* lhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
auto* result_slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
auto* rhs_bb = func_->CreateBlock(NextBlockName());
auto* false_bb = func_->CreateBlock(NextBlockName());
auto* merge_bb = func_->CreateBlock(NextBlockName());
builder_.CreateCondBr(lhs, rhs_bb, false_bb);
builder_.SetInsertPoint(rhs_bb);
auto* rhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->eqExp()->accept(this)));
builder_.CreateStore(rhs, result_slot);
if (!rhs_bb->HasTerminator()) {
builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(false_bb);
builder_.CreateStore(builder_.CreateConstInt(0), result_slot);
if (!false_bb->HasTerminator()) {
builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(merge_bb);
return static_cast<ir::Value*>(
builder_.CreateLoad(result_slot, module_.GetContext().NextTemp()));
}
std::any IRGenImpl::visitLOrExp(SysYParser::LOrExpContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
}
if (!ctx->lOrExp()) {
if (ctx->lAndExp()) {
return ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
}
throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
}
if (!ctx->lAndExp()) {
throw std::runtime_error(FormatError("irgen", "非法逻辑或表达式"));
}
auto* lhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->lOrExp()->accept(this)));
auto* result_slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
auto* true_bb = func_->CreateBlock(NextBlockName());
auto* rhs_bb = func_->CreateBlock(NextBlockName());
auto* merge_bb = func_->CreateBlock(NextBlockName());
builder_.CreateCondBr(lhs, true_bb, rhs_bb);
builder_.SetInsertPoint(true_bb);
builder_.CreateStore(builder_.CreateConstInt(1), result_slot);
if (!true_bb->HasTerminator()) {
builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(rhs_bb);
auto* rhs = ToBoolValue(std::any_cast<ir::Value*>(ctx->lAndExp()->accept(this)));
builder_.CreateStore(rhs, result_slot);
if (!rhs_bb->HasTerminator()) {
builder_.CreateBr(merge_bb);
}
builder_.SetInsertPoint(merge_bb);
return static_cast<ir::Value*>(
builder_.CreateBinary(ir::Opcode::Add, lhs, rhs,
module_.GetContext().NextTemp()));
builder_.CreateLoad(result_slot, module_.GetContext().NextTemp()));
}

@ -2,7 +2,7 @@
#include <stdexcept>
#include "SysYParser.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
@ -25,7 +25,10 @@ IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
: module_(module),
sema_(sema),
func_(nullptr),
builder_(module.GetContext(), nullptr) {}
builder_(module.GetContext(), nullptr) {
// 初始化作用域栈,至少有一个全局作用域(但当前未使用全局变量)
scope_storage_.emplace_back();
}
// 编译单元的 IR 生成当前只实现了最小功能:
// - Module 已在 GenerateIR 中创建,这里只负责继续生成其中的内容;
@ -38,11 +41,25 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
}
auto* func = ctx->funcDef();
if (!func) {
// 先处理全局变量声明
for (auto* decl : ctx->decl()) {
if (!decl) continue;
// 如果当前还未进入函数,则这些为全局变量声明
if (!in_function_) {
decl->accept(this);
}
}
// 再处理函数定义
if (ctx->funcDef().empty()) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
}
func->accept(this);
for (auto* func : ctx->funcDef()) {
if (func) {
func->accept(this);
}
}
return {};
}
@ -61,7 +78,7 @@ std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
// - 入口块中的参数初始化逻辑。
// ...
// 因此这里目前只支持最小的“参 int 函数”生成。
// 因此这里目前只支持最小的“参 int 函数”生成。
std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
@ -73,15 +90,66 @@ std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
}
if (!ctx->funcType() || !ctx->funcType()->INT()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持无参 int 函数"));
throw std::runtime_error(FormatError("irgen", "当前仅支持 int 返回类型函数"));
}
// 解析返回类型(当前仅 int
auto ret_type = ir::Type::GetInt32Type();
// 解析参数类型列表
std::vector<std::shared_ptr<ir::Type>> param_types;
std::vector<std::string> param_names;
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->btype() || !param->btype()->INT() || !param->ID()) {
throw std::runtime_error(FormatError("irgen", "当前仅支持 int 类型参数"));
}
param_types.push_back(ir::Type::GetInt32Type());
param_names.push_back(param->ID()->getText());
}
}
func_ = module_.CreateFunction(ctx->ID()->getText(), ir::Type::GetInt32Type());
in_function_ = true;
// 创建 IR 函数(假设 CreateFunction 支持参数类型列表)
func_ = module_.CreateFunction(ctx->ID()->getText(), ret_type, param_types);
builder_.SetInsertPoint(func_->GetEntry());
// 清空当前函数的状态
storage_map_.clear();
named_storage_.clear();
param_slots_.clear();
// 进入函数参数作用域
scope_storage_.emplace_back();
// 处理参数:为每个参数创建 alloca 并放入符号表
for (const auto& param_name : param_names) {
auto* alloca = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
param_slots_.push_back(alloca);
scope_storage_.back()[param_name] = alloca;
named_storage_[param_name] = alloca;
}
// 生成函数体
ctx->blockStmt()->accept(this);
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。
// 退出函数参数作用域
scope_storage_.pop_back();
in_function_ = false;
// 如果函数最后一个基本块没有终结指令,添加默认返回
const auto& blocks = func_->GetBlocks();
if (!blocks.empty()) {
auto* last_bb = blocks.back().get();
if (last_bb && !last_bb->HasTerminator()) {
builder_.SetInsertPoint(last_bb);
builder_.CreateRet(builder_.CreateConstInt(0));
}
}
// 校验函数结构
VerifyFunctionStructure(*func_);
return {};
}

@ -2,10 +2,20 @@
#include <stdexcept>
#include "SysYParser.h"
#include "antlr4/SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
static std::string FormatErrorCtx(antlr4::ParserRuleContext* ctx,
const std::string& msg) {
if (ctx && ctx->getStart()) {
return FormatErrorAt("irgen", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1, msg);
}
return FormatError("irgen", msg);
}
// 语句生成当前只实现了最小子集。
// 目前支持:
// - return <exp>;
@ -19,12 +29,125 @@ std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句"));
}
if (ctx->lValue() && ctx->ASSIGN() && ctx->exp()) {
if (!ctx->lValue()->ID()) {
throw std::runtime_error(FormatError("irgen", "赋值语句左值非法"));
}
ir::Value* dest = ResolveLValueAddress(ctx->lValue());
if (!dest) {
throw std::runtime_error(
FormatError("irgen", "赋值目标地址解析失败"));
}
ir::Value* rhs = EvalExpr(*ctx->exp());
builder_.CreateStore(rhs, dest);
return BlockFlow::Continue;
}
if (ctx->blockStmt()) {
ctx->blockStmt()->accept(this);
return builder_.GetInsertBlock() && builder_.GetInsertBlock()->HasTerminator()
? BlockFlow::Terminated
: BlockFlow::Continue;
}
if (ctx->IF()) {
if (!ctx->cond() || ctx->stmt().empty()) {
throw std::runtime_error(FormatError("irgen", "if 语句不完整"));
}
auto* then_bb = func_->CreateBlock(NextBlockName());
auto* merge_bb = func_->CreateBlock(NextBlockName());
auto* else_bb = ctx->ELSE() ? func_->CreateBlock(NextBlockName()) : merge_bb;
ir::Value* cond = ToBoolValue(EvalCond(*ctx->cond()));
builder_.CreateCondBr(cond, then_bb, else_bb);
builder_.SetInsertPoint(then_bb);
auto then_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
if (then_flow != BlockFlow::Terminated) {
builder_.CreateBr(merge_bb);
}
if (ctx->ELSE()) {
builder_.SetInsertPoint(else_bb);
auto else_flow = std::any_cast<BlockFlow>(ctx->stmt(1)->accept(this));
if (else_flow != BlockFlow::Terminated) {
builder_.CreateBr(merge_bb);
}
}
builder_.SetInsertPoint(merge_bb);
return BlockFlow::Continue;
}
if (ctx->WHILE()) {
if (!ctx->cond() || ctx->stmt().empty()) {
throw std::runtime_error(FormatError("irgen", "while 语句不完整"));
}
auto* cond_bb = func_->CreateBlock(NextBlockName());
auto* body_bb = func_->CreateBlock(NextBlockName());
auto* exit_bb = func_->CreateBlock(NextBlockName());
builder_.CreateBr(cond_bb);
builder_.SetInsertPoint(cond_bb);
ir::Value* cond = ToBoolValue(EvalCond(*ctx->cond()));
builder_.CreateCondBr(cond, body_bb, exit_bb);
loop_stack_.push_back({cond_bb, exit_bb});
builder_.SetInsertPoint(body_bb);
auto body_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
if (body_flow != BlockFlow::Terminated) {
builder_.CreateBr(cond_bb);
}
loop_stack_.pop_back();
builder_.SetInsertPoint(exit_bb);
return BlockFlow::Continue;
}
if (ctx->BREAK()) {
if (loop_stack_.empty()) {
throw std::runtime_error(FormatError("irgen", "break 不在循环中"));
}
builder_.CreateBr(loop_stack_.back().break_target);
return BlockFlow::Terminated;
}
if (ctx->CONTINUE()) {
if (loop_stack_.empty()) {
throw std::runtime_error(FormatError("irgen", "continue 不在循环中"));
}
builder_.CreateBr(loop_stack_.back().continue_target);
return BlockFlow::Terminated;
}
if (ctx->returnStmt()) {
return ctx->returnStmt()->accept(this);
}
if (ctx->exp()) {
EvalExpr(*ctx->exp());
return BlockFlow::Continue;
}
if (ctx->SEMICOLON()) {
return BlockFlow::Continue;
}
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
}
ir::Value* IRGenImpl::ResolveLValueAddress(SysYParser::LValueContext* ctx) {
if (!ctx || !ctx->ID()) {
throw std::runtime_error(FormatError("irgen", "非法左值"));
}
const std::string name = ctx->ID()->getText();
ir::Value* base = FindInScope(name);
if (!base) {
throw std::runtime_error(FormatError("irgen", "变量未声明: " + name));
}
if (ctx->LBRACK().empty()) {
return base;
}
// 到目前为止只支持一维数组,占位实现
if (ctx->exp().empty()) {
throw std::runtime_error(FormatError("irgen", "数组下标缺失"));
}
return EmitArrayIndex(base, ctx->exp(0));
}
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
if (!ctx) {
@ -37,3 +160,32 @@ std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
builder_.CreateRet(v);
return BlockFlow::Terminated;
}
ir::Value* IRGenImpl::EmitArrayIndex(ir::Value* base_ptr,
SysYParser::ExpContext* idx_expr) {
if (!base_ptr) {
throw std::runtime_error(FormatError("irgen", "数组基址为空"));
}
if (!idx_expr) {
throw std::runtime_error(FormatError("irgen", "缺少数组下标表达式"));
}
ir::Value* idx = EvalExpr(*idx_expr);
if (!idx) {
throw std::runtime_error(FormatError("irgen", "数组下标计算失败"));
}
// 当前 IR 仍只支持 i32 / i32*,还未实现真正的 GEP。
// 这里提供一个占位:直接将基址作为元素地址返回(仅用于结构化接口),
// 具体语义需在后续 IR 指令集扩展后完成。
// TODO: 实现指针加法/GEP以支持数组下标访问
(void)idx;
return base_ptr;
}
void IRGenImpl::EmitGlobalVariable(SysYParser::VarDefContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少全局变量定义"));
}
// GlobalValue 还未完成,暂时抛异常以提醒后续实现。
throw std::runtime_error(FormatError("irgen", "全局变量生成未实现"));
}

@ -1,200 +1,224 @@
#include "sem/Sema.h"
#include <any>
#include <stdexcept>
#include <string>
#include "SysYBaseVisitor.h"
#include "sem/SymbolTable.h"
#include "utils/Log.h"
namespace {
std::string GetLValueName(SysYParser::LValueContext& lvalue) {
if (!lvalue.ID()) {
throw std::runtime_error(FormatError("sema", "非法左值"));
SymbolType ParseType(const std::string& text) {
if (text == "int") {
return SymbolType::TYPE_INT;
}
return lvalue.ID()->getText();
}
class SemaVisitor final : public SysYBaseVisitor {
public:
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override {
if (!ctx) {
throw std::runtime_error(FormatError("sema", "缺少编译单元"));
}
auto* func = ctx->funcDef();
if (!func || !func->blockStmt()) {
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
}
if (!func->ID() || func->ID()->getText() != "main") {
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
}
func->accept(this);
if (!seen_return_) {
throw std::runtime_error(
FormatError("sema", "main 函数必须包含 return 语句"));
}
return {};
if (text == "float") {
return SymbolType::TYPE_FLOAT;
}
if (text == "void") {
return SymbolType::TYPE_VOID;
}
return SymbolType::TYPE_UNKNOWN;
}
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override {
if (!ctx || !ctx->blockStmt()) {
throw std::runtime_error(FormatError("sema", "缺少 main 函数定义"));
}
if (!ctx->funcType() || !ctx->funcType()->INT()) {
throw std::runtime_error(FormatError("sema", "当前仅支持 int main"));
}
const auto& items = ctx->blockStmt()->blockItem();
if (items.empty()) {
throw std::runtime_error(
FormatError("sema", "main 函数不能为空,且必须以 return 结束"));
}
ctx->blockStmt()->accept(this);
return {};
} // namespace
std::any SemaVisitor::visitCompUnit(SysYParser::CompUnitContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitDecl(SysYParser::DeclContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitConstDecl(SysYParser::ConstDeclContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitBtype(SysYParser::BtypeContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitConstDef(SysYParser::ConstDefContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitConstInitValue(SysYParser::ConstInitValueContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitVarDecl(SysYParser::VarDeclContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitVarDef(SysYParser::VarDefContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitInitValue(SysYParser::InitValueContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitFuncDef(SysYParser::FuncDefContext* ctx) {
SymbolType ret_type = SymbolType::TYPE_UNKNOWN;
if (ctx && ctx->funcType()) {
ret_type = ParseType(ctx->funcType()->getText());
}
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override {
if (!ctx) {
throw std::runtime_error(FormatError("sema", "缺少语句块"));
}
const auto& items = ctx->blockItem();
for (size_t i = 0; i < items.size(); ++i) {
auto* item = items[i];
if (!item) {
continue;
}
if (seen_return_) {
throw std::runtime_error(
FormatError("sema", "return 必须是 main 函数中的最后一条语句"));
}
current_item_index_ = i;
total_items_ = items.size();
item->accept(this);
}
ir_ctx_.SetCurrentFuncReturnType(ret_type);
return visitChildren(ctx);
}
std::any SemaVisitor::visitFuncType(SysYParser::FuncTypeContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitFuncFParams(SysYParser::FuncFParamsContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitFuncFParam(SysYParser::FuncFParamContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
ir_ctx_.EnterScope();
std::any result = visitChildren(ctx);
ir_ctx_.LeaveScope();
return result;
}
std::any SemaVisitor::visitBlockItem(SysYParser::BlockItemContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitStmt(SysYParser::StmtContext* ctx) {
if (!ctx) {
return {};
}
std::any visitBlockItem(SysYParser::BlockItemContext* ctx) override {
if (!ctx) {
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
}
if (ctx->decl()) {
ctx->decl()->accept(this);
return {};
}
if (ctx->stmt()) {
ctx->stmt()->accept(this);
return {};
}
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
if (ctx->WHILE()) {
ir_ctx_.EnterLoop();
std::any result = visitChildren(ctx);
ir_ctx_.ExitLoop();
return result;
}
std::any visitDecl(SysYParser::DeclContext* ctx) override {
if (!ctx) {
throw std::runtime_error(FormatError("sema", "非法变量声明"));
}
if (!ctx->btype() || !ctx->btype()->INT()) {
throw std::runtime_error(FormatError("sema", "当前仅支持局部 int 变量声明"));
}
auto* var_def = ctx->varDef();
if (!var_def || !var_def->lValue()) {
throw std::runtime_error(FormatError("sema", "非法变量声明"));
}
const std::string name = GetLValueName(*var_def->lValue());
if (table_.Contains(name)) {
throw std::runtime_error(FormatError("sema", "重复定义变量: " + name));
}
if (auto* init = var_def->initValue()) {
if (!init->exp()) {
throw std::runtime_error(FormatError("sema", "当前不支持聚合初始化"));
}
init->exp()->accept(this);
}
table_.Add(name, var_def);
return {};
if (ctx->BREAK() && !ir_ctx_.InLoop()) {
ir_ctx_.RecordError(
ErrorMsg("break 只能出现在循环语句中", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
}
std::any visitStmt(SysYParser::StmtContext* ctx) override {
if (!ctx || !ctx->returnStmt()) {
throw std::runtime_error(FormatError("sema", "暂不支持的语句或声明"));
}
ctx->returnStmt()->accept(this);
return {};
if (ctx->CONTINUE() && !ir_ctx_.InLoop()) {
ir_ctx_.RecordError(
ErrorMsg("continue 只能出现在循环语句中", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
}
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override {
if (!ctx || !ctx->exp()) {
throw std::runtime_error(FormatError("sema", "return 缺少表达式"));
}
ctx->exp()->accept(this);
seen_return_ = true;
if (current_item_index_ + 1 != total_items_) {
throw std::runtime_error(
FormatError("sema", "return 必须是 main 函数中的最后一条语句"));
}
return {};
}
return visitChildren(ctx);
}
std::any visitParenExp(SysYParser::ParenExpContext* ctx) override {
if (!ctx || !ctx->exp()) {
throw std::runtime_error(FormatError("sema", "非法括号表达式"));
}
ctx->exp()->accept(this);
std::any SemaVisitor::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
if (!ctx) {
return {};
}
std::any visitVarExp(SysYParser::VarExpContext* ctx) override {
if (!ctx || !ctx->var()) {
throw std::runtime_error(FormatError("sema", "非法变量表达式"));
}
ctx->var()->accept(this);
return {};
if (ctx->exp() && ir_ctx_.GetCurrentFuncReturnType() == SymbolType::TYPE_VOID) {
ir_ctx_.RecordError(
ErrorMsg("void 函数不应返回表达式", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
}
std::any visitNumberExp(SysYParser::NumberExpContext* ctx) override {
if (!ctx || !ctx->number() || !ctx->number()->ILITERAL()) {
throw std::runtime_error(FormatError("sema", "当前仅支持整数字面量"));
}
return {};
if (!ctx->exp() &&
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_VOID &&
ir_ctx_.GetCurrentFuncReturnType() != SymbolType::TYPE_UNKNOWN) {
ir_ctx_.RecordError(
ErrorMsg("非 void 函数 return 必须带表达式", ctx->getStart()->getLine(),
ctx->getStart()->getCharPositionInLine() + 1));
}
std::any visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) override {
if (!ctx || !ctx->exp(0) || !ctx->exp(1)) {
throw std::runtime_error(FormatError("sema", "暂不支持的表达式形式"));
}
ctx->exp(0)->accept(this);
ctx->exp(1)->accept(this);
return visitChildren(ctx);
}
std::any SemaVisitor::visitExp(SysYParser::ExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitCond(SysYParser::CondContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitLValue(SysYParser::LValueContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitNumber(SysYParser::NumberContext* ctx) {
if (!ctx) {
return {};
}
std::any visitVar(SysYParser::VarContext* ctx) override {
if (!ctx || !ctx->ID()) {
throw std::runtime_error(FormatError("sema", "非法变量引用"));
}
const std::string name = ctx->ID()->getText();
auto* decl = table_.Lookup(name);
if (!decl) {
throw std::runtime_error(FormatError("sema", "使用了未定义的变量: " + name));
}
sema_.BindVarUse(ctx, decl);
return {};
if (ctx->ILITERAL()) {
ir_ctx_.SetType(ctx, SymbolType::TYPE_INT);
ir_ctx_.SetConstVal(ctx, std::any(0L));
} else if (ctx->FLITERAL()) {
ir_ctx_.SetType(ctx, SymbolType::TYPE_FLOAT);
ir_ctx_.SetConstVal(ctx, std::any(0.0));
}
SemanticContext TakeSemanticContext() { return std::move(sema_); }
return {};
}
private:
SymbolTable table_;
SemanticContext sema_;
bool seen_return_ = false;
size_t current_item_index_ = 0;
size_t total_items_ = 0;
};
std::any SemaVisitor::visitUnaryExp(SysYParser::UnaryExpContext* ctx) {
return visitChildren(ctx);
}
} // namespace
std::any SemaVisitor::visitUnaryOp(SysYParser::UnaryOpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitFuncRParams(SysYParser::FuncRParamsContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitMulExp(SysYParser::MulExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitAddExp(SysYParser::AddExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitRelExp(SysYParser::RelExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitEqExp(SysYParser::EqExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitLAndExp(SysYParser::LAndExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitLOrExp(SysYParser::LOrExpContext* ctx) {
return visitChildren(ctx);
}
std::any SemaVisitor::visitConstExp(SysYParser::ConstExpContext* ctx) {
return visitChildren(ctx);
}
void RunSemanticAnalysis(SysYParser::CompUnitContext* ctx, IRGenContext& ir_ctx) {
if (!ctx) {
throw std::invalid_argument("CompUnitContext is null");
}
SemaVisitor visitor(ir_ctx);
visitor.visit(ctx);
}
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit) {
SemaVisitor visitor;
comp_unit.accept(&visitor);
return visitor.TakeSemanticContext();
IRGenContext ctx;
RunSemanticAnalysis(&comp_unit, ctx);
return SemanticContext();
}

@ -1,17 +1,164 @@
// 维护局部变量声明的注册与查找。
#include "../../include/sem/SymbolTable.h"
#include <stdexcept>
#include <string>
#include <iostream>
#include "sem/SymbolTable.h"
// 进入新作用域
void SymbolTable::EnterScope() {
scopes_.push(ScopeEntry());
}
// 离开当前作用域
void SymbolTable::LeaveScope() {
if (scopes_.empty()) {
throw std::runtime_error("SymbolTable Error: 作用域栈为空,无法退出");
}
scopes_.pop();
}
// 绑定变量到当前作用域
void SymbolTable::BindVar(const std::string& name, const VarInfo& info, void* decl_ctx) {
if (CurrentScopeHasVar(name)) {
throw std::runtime_error("变量'" + name + "'在当前作用域重复定义");
}
scopes_.top().var_symbols[name] = {info, decl_ctx};
}
// 绑定函数到当前作用域
void SymbolTable::BindFunc(const std::string& name, const FuncInfo& info, void* decl_ctx) {
if (CurrentScopeHasFunc(name)) {
throw std::runtime_error("函数'" + name + "'在当前作用域重复定义");
}
scopes_.top().func_symbols[name] = {info, decl_ctx};
}
// 查找变量(从当前作用域向上遍历)
bool SymbolTable::LookupVar(const std::string& name, VarInfo& out_info, void*& out_decl_ctx) const {
if (scopes_.empty()) {
return false;
}
auto temp_stack = scopes_;
while (!temp_stack.empty()) {
auto& scope = temp_stack.top();
auto it = scope.var_symbols.find(name);
if (it != scope.var_symbols.end()) {
out_info = it->second.first;
out_decl_ctx = it->second.second;
return true;
}
temp_stack.pop();
}
return false;
}
// 查找函数(从当前作用域向上遍历,通常函数在全局作用域)
bool SymbolTable::LookupFunc(const std::string& name, FuncInfo& out_info, void*& out_decl_ctx) const {
if (scopes_.empty()) {
return false;
}
auto temp_stack = scopes_;
while (!temp_stack.empty()) {
auto& scope = temp_stack.top();
auto it = scope.func_symbols.find(name);
if (it != scope.func_symbols.end()) {
out_info = it->second.first;
out_decl_ctx = it->second.second;
return true;
}
temp_stack.pop();
}
return false;
}
void SymbolTable::Add(const std::string& name,
SysYParser::VarDefContext* decl) {
table_[name] = decl;
// 检查当前作用域是否包含指定变量
bool SymbolTable::CurrentScopeHasVar(const std::string& name) const {
if (scopes_.empty()) {
return false;
}
return scopes_.top().var_symbols.count(name) > 0;
}
bool SymbolTable::Contains(const std::string& name) const {
return table_.find(name) != table_.end();
// 检查当前作用域是否包含指定函数
bool SymbolTable::CurrentScopeHasFunc(const std::string& name) const {
if (scopes_.empty()) {
return false;
}
return scopes_.top().func_symbols.count(name) > 0;
}
SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const {
auto it = table_.find(name);
return it == table_.end() ? nullptr : it->second;
// 进入循环
void SymbolTable::EnterLoop() {
loop_depth_++;
}
// 离开循环
void SymbolTable::ExitLoop() {
if (loop_depth_ > 0) loop_depth_--;
}
// 检查是否在循环内
bool SymbolTable::InLoop() const {
return loop_depth_ > 0;
}
// 清空所有作用域和状态
void SymbolTable::Clear() {
while (!scopes_.empty()) {
scopes_.pop();
}
loop_depth_ = 0;
}
// 获取当前作用域中所有变量名
std::vector<std::string> SymbolTable::GetCurrentScopeVarNames() const {
std::vector<std::string> names;
if (!scopes_.empty()) {
for (const auto& pair : scopes_.top().var_symbols) {
names.push_back(pair.first);
}
}
return names;
}
// 获取当前作用域中所有函数名
std::vector<std::string> SymbolTable::GetCurrentScopeFuncNames() const {
std::vector<std::string> names;
if (!scopes_.empty()) {
for (const auto& pair : scopes_.top().func_symbols) {
names.push_back(pair.first);
}
}
return names;
}
// 调试:打印符号表内容
void SymbolTable::Dump() const {
std::cout << "符号表内容 (作用域深度: " << scopes_.size() << "):\n";
int scope_idx = 0;
auto temp_stack = scopes_;
while (!temp_stack.empty()) {
std::cout << "\n作用域 " << scope_idx++ << ":\n";
auto& scope = temp_stack.top();
std::cout << " 变量:\n";
for (const auto& var_pair : scope.var_symbols) {
const VarInfo& info = var_pair.second.first;
std::cout << " " << var_pair.first << ": "
<< SymbolTypeToString(info.type)
<< (info.is_const ? " (const)" : "")
<< (info.IsArray() ? " [数组]" : "")
<< "\n";
}
std::cout << " 函数:\n";
for (const auto& func_pair : scope.func_symbols) {
const FuncInfo& info = func_pair.second.first;
std::cout << " " << func_pair.first << ": "
<< SymbolTypeToString(info.ret_type) << " ("
<< info.param_types.size() << " 个参数)\n";
}
temp_stack.pop();
}
}

@ -0,0 +1,187 @@
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32, i32 8
%t11 = alloca i32
%t12 = alloca i32, i32 8
%t21 = alloca i32, i32 8
%t38 = alloca i32, i32 8
%t58 = alloca i32, i32 8
br label %bbt0
bbt0:
%t3 = getelementptr i32, i32* %t2, i32 0
store i32 1, i32* %t3
%t4 = getelementptr i32, i32* %t2, i32 1
store i32 2, i32* %t4
%t5 = getelementptr i32, i32* %t2, i32 2
store i32 3, i32* %t5
%t6 = getelementptr i32, i32* %t2, i32 3
store i32 4, i32* %t6
%t7 = getelementptr i32, i32* %t2, i32 4
store i32 0, i32* %t7
%t8 = getelementptr i32, i32* %t2, i32 5
store i32 0, i32* %t8
%t9 = getelementptr i32, i32* %t2, i32 6
store i32 7, i32* %t9
%t10 = getelementptr i32, i32* %t2, i32 7
store i32 0, i32* %t10
store i32 3, i32* %t11
%t13 = getelementptr i32, i32* %t12, i32 0
store i32 0, i32* %t13
%t14 = getelementptr i32, i32* %t12, i32 1
store i32 0, i32* %t14
%t15 = getelementptr i32, i32* %t12, i32 2
store i32 0, i32* %t15
%t16 = getelementptr i32, i32* %t12, i32 3
store i32 0, i32* %t16
%t17 = getelementptr i32, i32* %t12, i32 4
store i32 0, i32* %t17
%t18 = getelementptr i32, i32* %t12, i32 5
store i32 0, i32* %t18
%t19 = getelementptr i32, i32* %t12, i32 6
store i32 0, i32* %t19
%t20 = getelementptr i32, i32* %t12, i32 7
store i32 0, i32* %t20
%t22 = getelementptr i32, i32* %t21, i32 0
store i32 0, i32* %t22
%t23 = getelementptr i32, i32* %t21, i32 1
store i32 0, i32* %t23
%t24 = getelementptr i32, i32* %t21, i32 2
store i32 0, i32* %t24
%t25 = getelementptr i32, i32* %t21, i32 3
store i32 0, i32* %t25
%t26 = getelementptr i32, i32* %t21, i32 4
store i32 0, i32* %t26
%t27 = getelementptr i32, i32* %t21, i32 5
store i32 0, i32* %t27
%t28 = getelementptr i32, i32* %t21, i32 6
store i32 0, i32* %t28
%t29 = getelementptr i32, i32* %t21, i32 7
store i32 0, i32* %t29
%t30 = getelementptr i32, i32* %t21, i32 0
store i32 1, i32* %t30
%t31 = getelementptr i32, i32* %t21, i32 1
store i32 2, i32* %t31
%t32 = getelementptr i32, i32* %t21, i32 2
store i32 3, i32* %t32
%t33 = getelementptr i32, i32* %t21, i32 3
store i32 4, i32* %t33
%t34 = getelementptr i32, i32* %t21, i32 4
store i32 5, i32* %t34
%t35 = getelementptr i32, i32* %t21, i32 5
store i32 6, i32* %t35
%t36 = getelementptr i32, i32* %t21, i32 6
store i32 7, i32* %t36
%t37 = getelementptr i32, i32* %t21, i32 7
store i32 8, i32* %t37
%t39 = getelementptr i32, i32* %t38, i32 0
store i32 0, i32* %t39
%t40 = getelementptr i32, i32* %t38, i32 1
store i32 0, i32* %t40
%t41 = getelementptr i32, i32* %t38, i32 2
store i32 0, i32* %t41
%t42 = getelementptr i32, i32* %t38, i32 3
store i32 0, i32* %t42
%t43 = getelementptr i32, i32* %t38, i32 4
store i32 0, i32* %t43
%t44 = getelementptr i32, i32* %t38, i32 5
store i32 0, i32* %t44
%t45 = getelementptr i32, i32* %t38, i32 6
store i32 0, i32* %t45
%t46 = getelementptr i32, i32* %t38, i32 7
store i32 0, i32* %t46
%t47 = mul i32 3, 2
%t48 = add i32 0, %t47
%t49 = add i32 %t48, 0
%t50 = getelementptr i32, i32* %t2, i32 %t49
%t51 = load i32, i32* %t50
%t52 = getelementptr i32, i32* %t38, i32 0
store i32 1, i32* %t52
%t53 = getelementptr i32, i32* %t38, i32 1
store i32 2, i32* %t53
%t54 = getelementptr i32, i32* %t38, i32 2
store i32 3, i32* %t54
%t55 = getelementptr i32, i32* %t38, i32 4
store i32 5, i32* %t55
%t56 = getelementptr i32, i32* %t38, i32 6
store i32 %t51, i32* %t56
%t57 = getelementptr i32, i32* %t38, i32 7
store i32 8, i32* %t57
%t59 = getelementptr i32, i32* %t58, i32 0
store i32 0, i32* %t59
%t60 = getelementptr i32, i32* %t58, i32 1
store i32 0, i32* %t60
%t61 = getelementptr i32, i32* %t58, i32 2
store i32 0, i32* %t61
%t62 = getelementptr i32, i32* %t58, i32 3
store i32 0, i32* %t62
%t63 = getelementptr i32, i32* %t58, i32 4
store i32 0, i32* %t63
%t64 = getelementptr i32, i32* %t58, i32 5
store i32 0, i32* %t64
%t65 = getelementptr i32, i32* %t58, i32 6
store i32 0, i32* %t65
%t66 = getelementptr i32, i32* %t58, i32 7
store i32 0, i32* %t66
%t67 = mul i32 2, 2
%t68 = add i32 0, %t67
%t69 = add i32 %t68, 1
%t70 = getelementptr i32, i32* %t38, i32 %t69
%t71 = load i32, i32* %t70
%t72 = mul i32 2, 2
%t73 = add i32 0, %t72
%t74 = add i32 %t73, 1
%t75 = getelementptr i32, i32* %t21, i32 %t74
%t76 = load i32, i32* %t75
%t77 = getelementptr i32, i32* %t58, i32 0
store i32 %t71, i32* %t77
%t78 = getelementptr i32, i32* %t58, i32 1
store i32 %t76, i32* %t78
%t79 = getelementptr i32, i32* %t58, i32 2
store i32 3, i32* %t79
%t80 = getelementptr i32, i32* %t58, i32 3
store i32 4, i32* %t80
%t81 = getelementptr i32, i32* %t58, i32 4
store i32 5, i32* %t81
%t82 = getelementptr i32, i32* %t58, i32 5
store i32 6, i32* %t82
%t83 = getelementptr i32, i32* %t58, i32 6
store i32 7, i32* %t83
%t84 = getelementptr i32, i32* %t58, i32 7
store i32 8, i32* %t84
%t85 = mul i32 3, 2
%t86 = add i32 0, %t85
%t87 = add i32 %t86, 1
%t88 = add i32 %t87, 0
%t89 = getelementptr i32, i32* %t58, i32 %t88
%t90 = load i32, i32* %t89
%t91 = mul i32 0, 2
%t92 = add i32 0, %t91
%t93 = add i32 %t92, 0
%t94 = add i32 %t93, 0
%t95 = getelementptr i32, i32* %t58, i32 %t94
%t96 = load i32, i32* %t95
%t97 = add i32 %t90, %t96
%t98 = mul i32 0, 2
%t99 = add i32 0, %t98
%t100 = add i32 %t99, 1
%t101 = add i32 %t100, 0
%t102 = getelementptr i32, i32* %t58, i32 %t101
%t103 = load i32, i32* %t102
%t104 = add i32 %t97, %t103
%t105 = mul i32 3, 2
%t106 = add i32 0, %t105
%t107 = add i32 %t106, 0
%t108 = getelementptr i32, i32* %t38, i32 %t107
%t109 = load i32, i32* %t108
%t110 = add i32 %t104, %t109
ret i32 %t110
}

@ -0,0 +1,37 @@
@a = global i32 0
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @func(i32 %arg0) {
entry:
%t1 = alloca i32
%t2 = alloca i32
br label %bbt0
bbt0:
store i32 %arg0, i32* %t1
%t3 = load i32, i32* %t1
%t4 = sub i32 %t3, 1
store i32 %t4, i32* %t1
%t5 = load i32, i32* %t1
ret i32 %t5
}
define i32 @main() {
entry:
%t7 = alloca i32
%t8 = alloca i32
br label %bbt6
bbt6:
store i32 0, i32* %t8
store i32 10, i32* @a
%t9 = load i32, i32* @a
%t10 = call i32 @func(i32 %t9)
store i32 %t10, i32* %t8
%t11 = load i32, i32* %t8
ret i32 %t11
}

@ -0,0 +1,25 @@
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32
%t3 = alloca i32
br label %bbt0
bbt0:
store i32 0, i32* %t2
store i32 0, i32* %t3
store i32 10, i32* %t2
%t4 = sub i32 0, 1
store i32 %t4, i32* %t3
%t5 = load i32, i32* %t2
%t6 = load i32, i32* %t3
%t7 = add i32 %t5, %t6
ret i32 %t7
}

@ -0,0 +1,23 @@
@a = global i32 10
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32
br label %bbt0
bbt0:
store i32 0, i32* %t2
store i32 2, i32* %t2
%t3 = load i32, i32* %t2
%t4 = load i32, i32* @a
%t5 = sub i32 %t3, %t4
ret i32 %t5
}

@ -0,0 +1,287 @@
@V = global i32 4
@space = global i32 32
@LF = global i32 10
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define void @printSolution(i32* %arg0) {
entry:
%t1 = alloca i32
%t2 = alloca i32
br label %bbt0
bbt0:
store i32 0, i32* %t2
br label %bbt3
bbt3:
%t6 = load i32, i32* %t2
%t7 = load i32, i32* @V
%t8 = icmp slt i32 %t6, %t7
br i1 %t8, label %bbt4, label %bbt5
bbt4:
%t9 = load i32, i32* %t2
%t10 = getelementptr i32, i32* %arg0, i32 %t9
%t11 = load i32, i32* %t10
call void @putint(i32 %t11)
%t12 = load i32, i32* @space
call void @putch(i32 %t12)
%t13 = load i32, i32* %t2
%t14 = add i32 %t13, 1
store i32 %t14, i32* %t2
br label %bbt3
bbt5:
%t15 = load i32, i32* @LF
call void @putch(i32 %t15)
ret void
}
define void @printMessage() {
entry:
%t17 = alloca i32
br label %bbt16
bbt16:
call void @putch(i32 78)
call void @putch(i32 111)
call void @putch(i32 116)
%t18 = load i32, i32* @space
call void @putch(i32 %t18)
call void @putch(i32 101)
call void @putch(i32 120)
call void @putch(i32 105)
call void @putch(i32 115)
call void @putch(i32 116)
ret void
}
define i32 @isSafe(i32* %arg0, i32* %arg1) {
entry:
%t20 = alloca i32
%t21 = alloca i32
%t28 = alloca i32
br label %bbt19
bbt19:
store i32 0, i32* %t21
br label %bbt22
bbt22:
%t25 = load i32, i32* %t21
%t26 = load i32, i32* @V
%t27 = icmp slt i32 %t25, %t26
br i1 %t27, label %bbt23, label %bbt24
bbt23:
%t29 = load i32, i32* %t21
%t30 = add i32 %t29, 1
store i32 %t30, i32* %t28
br label %bbt31
bbt24:
ret i32 1
bbt31:
%t34 = load i32, i32* %t28
%t35 = load i32, i32* @V
%t36 = icmp slt i32 %t34, %t35
br i1 %t36, label %bbt32, label %bbt33
bbt32:
store i32 0, i32* %t20
%t39 = load i32, i32* %t21
%t40 = mul i32 %t39, 4
%t41 = add i32 0, %t40
%t42 = load i32, i32* %t28
%t43 = add i32 %t41, %t42
%t44 = getelementptr i32, i32* %arg0, i32 %t43
%t45 = load i32, i32* %t44
%t46 = icmp ne i32 %t45, 0
br i1 %t46, label %bbt47, label %bbt49
bbt33:
%t61 = load i32, i32* %t21
%t62 = add i32 %t61, 1
store i32 %t62, i32* %t21
br label %bbt22
bbt37:
ret i32 0
bbt38:
%t59 = load i32, i32* %t28
%t60 = add i32 %t59, 1
store i32 %t60, i32* %t28
br label %bbt31
bbt47:
%t50 = load i32, i32* %t28
%t51 = getelementptr i32, i32* %arg1, i32 %t50
%t52 = load i32, i32* %t51
%t53 = load i32, i32* %t21
%t54 = getelementptr i32, i32* %arg1, i32 %t53
%t55 = load i32, i32* %t54
%t56 = icmp eq i32 %t52, %t55
br i1 %t56, label %bbt48, label %bbt49
bbt48:
store i32 1, i32* %t20
br label %bbt49
bbt49:
%t57 = load i32, i32* %t20
%t58 = icmp ne i32 %t57, 0
br i1 %t58, label %bbt37, label %bbt38
}
define i32 @graphColoring(i32* %arg0, i32 %arg1, i32 %arg2, i32* %arg3) {
entry:
%t64 = alloca i32
%t65 = alloca i32
%t66 = alloca i32
%t76 = alloca i32
br label %bbt63
bbt63:
store i32 %arg1, i32* %t64
store i32 %arg2, i32* %t65
%t69 = load i32, i32* %t65
%t70 = load i32, i32* @V
%t71 = icmp eq i32 %t69, %t70
br i1 %t71, label %bbt67, label %bbt68
bbt67:
%t74 = call i32 @isSafe(i32* %arg0, i32* %arg3)
%t75 = icmp ne i32 %t74, 0
br i1 %t75, label %bbt72, label %bbt73
bbt68:
store i32 1, i32* %t76
br label %bbt77
bbt72:
call void @printSolution(i32* %arg3)
ret i32 1
bbt73:
ret i32 0
bbt77:
%t80 = load i32, i32* %t76
%t81 = load i32, i32* %t64
%t82 = icmp sle i32 %t80, %t81
br i1 %t82, label %bbt78, label %bbt79
bbt78:
%t83 = load i32, i32* %t76
%t84 = load i32, i32* %t65
%t85 = getelementptr i32, i32* %arg3, i32 %t84
store i32 %t83, i32* %t85
%t88 = load i32, i32* %t64
%t89 = load i32, i32* %t65
%t90 = add i32 %t89, 1
%t91 = call i32 @graphColoring(i32* %arg0, i32 %t88, i32 %t90, i32* %arg3)
%t92 = icmp ne i32 %t91, 0
br i1 %t92, label %bbt86, label %bbt87
bbt79:
ret i32 0
bbt86:
ret i32 1
bbt87:
%t93 = load i32, i32* %t65
%t94 = getelementptr i32, i32* %arg3, i32 %t93
store i32 0, i32* %t94
%t95 = load i32, i32* %t76
%t96 = add i32 %t95, 1
store i32 %t96, i32* %t76
br label %bbt77
}
define i32 @main() {
entry:
%t98 = alloca i32
%t99 = alloca i32, i32 16
%t132 = alloca i32
%t133 = alloca i32, i32 4
%t138 = alloca i32
br label %bbt97
bbt97:
%t100 = getelementptr i32, i32* %t99, i32 0
store i32 0, i32* %t100
%t101 = getelementptr i32, i32* %t99, i32 1
store i32 0, i32* %t101
%t102 = getelementptr i32, i32* %t99, i32 2
store i32 0, i32* %t102
%t103 = getelementptr i32, i32* %t99, i32 3
store i32 0, i32* %t103
%t104 = getelementptr i32, i32* %t99, i32 4
store i32 0, i32* %t104
%t105 = getelementptr i32, i32* %t99, i32 5
store i32 0, i32* %t105
%t106 = getelementptr i32, i32* %t99, i32 6
store i32 0, i32* %t106
%t107 = getelementptr i32, i32* %t99, i32 7
store i32 0, i32* %t107
%t108 = getelementptr i32, i32* %t99, i32 8
store i32 0, i32* %t108
%t109 = getelementptr i32, i32* %t99, i32 9
store i32 0, i32* %t109
%t110 = getelementptr i32, i32* %t99, i32 10
store i32 0, i32* %t110
%t111 = getelementptr i32, i32* %t99, i32 11
store i32 0, i32* %t111
%t112 = getelementptr i32, i32* %t99, i32 12
store i32 0, i32* %t112
%t113 = getelementptr i32, i32* %t99, i32 13
store i32 0, i32* %t113
%t114 = getelementptr i32, i32* %t99, i32 14
store i32 0, i32* %t114
%t115 = getelementptr i32, i32* %t99, i32 15
store i32 0, i32* %t115
%t116 = getelementptr i32, i32* %t99, i32 0
store i32 0, i32* %t116
%t117 = getelementptr i32, i32* %t99, i32 1
store i32 1, i32* %t117
%t118 = getelementptr i32, i32* %t99, i32 2
store i32 1, i32* %t118
%t119 = getelementptr i32, i32* %t99, i32 3
store i32 1, i32* %t119
%t120 = getelementptr i32, i32* %t99, i32 4
store i32 1, i32* %t120
%t121 = getelementptr i32, i32* %t99, i32 5
store i32 0, i32* %t121
%t122 = getelementptr i32, i32* %t99, i32 6
store i32 1, i32* %t122
%t123 = getelementptr i32, i32* %t99, i32 7
store i32 0, i32* %t123
%t124 = getelementptr i32, i32* %t99, i32 8
store i32 1, i32* %t124
%t125 = getelementptr i32, i32* %t99, i32 9
store i32 1, i32* %t125
%t126 = getelementptr i32, i32* %t99, i32 10
store i32 0, i32* %t126
%t127 = getelementptr i32, i32* %t99, i32 11
store i32 1, i32* %t127
%t128 = getelementptr i32, i32* %t99, i32 12
store i32 1, i32* %t128
%t129 = getelementptr i32, i32* %t99, i32 13
store i32 0, i32* %t129
%t130 = getelementptr i32, i32* %t99, i32 14
store i32 1, i32* %t130
%t131 = getelementptr i32, i32* %t99, i32 15
store i32 0, i32* %t131
store i32 3, i32* %t132
%t134 = getelementptr i32, i32* %t133, i32 0
store i32 0, i32* %t134
%t135 = getelementptr i32, i32* %t133, i32 1
store i32 0, i32* %t135
%t136 = getelementptr i32, i32* %t133, i32 2
store i32 0, i32* %t136
%t137 = getelementptr i32, i32* %t133, i32 3
store i32 0, i32* %t137
store i32 0, i32* %t138
br label %bbt139
bbt139:
%t142 = load i32, i32* %t138
%t143 = load i32, i32* @V
%t144 = icmp slt i32 %t142, %t143
br i1 %t144, label %bbt140, label %bbt141
bbt140:
%t145 = load i32, i32* %t138
%t146 = getelementptr i32, i32* %t133, i32 %t145
store i32 0, i32* %t146
%t147 = load i32, i32* %t138
%t148 = add i32 %t147, 1
store i32 %t148, i32* %t138
br label %bbt139
bbt141:
%t151 = load i32, i32* %t132
%t152 = call i32 @graphColoring(i32* %t99, i32 %t151, i32 0, i32* %t133)
%t153 = icmp eq i32 %t152, 0
br i1 %t153, label %bbt149, label %bbt150
bbt149:
call void @printMessage()
br label %bbt150
bbt150:
ret i32 0
}

@ -0,0 +1,220 @@
@MAX_SIZE = global i32 100
@a = global [10000 x i32] zeroinitializer
@b = global [10000 x i32] zeroinitializer
@res = global [10000 x i32] zeroinitializer
@n1 = global i32 0
@m1 = global i32 0
@n2 = global i32 0
@m2 = global i32 0
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define void @matrix_multiply() {
entry:
%t1 = alloca i32
%t2 = alloca i32
%t9 = alloca i32
%t16 = alloca i32
br label %bbt0
bbt0:
store i32 0, i32* %t2
br label %bbt3
bbt3:
%t6 = load i32, i32* %t2
%t7 = load i32, i32* @m1
%t8 = icmp slt i32 %t6, %t7
br i1 %t8, label %bbt4, label %bbt5
bbt4:
store i32 0, i32* %t9
br label %bbt10
bbt5:
ret void
bbt10:
%t13 = load i32, i32* %t9
%t14 = load i32, i32* @n2
%t15 = icmp slt i32 %t13, %t14
br i1 %t15, label %bbt11, label %bbt12
bbt11:
store i32 0, i32* %t16
br label %bbt17
bbt12:
%t56 = load i32, i32* %t2
%t57 = add i32 %t56, 1
store i32 %t57, i32* %t2
br label %bbt3
bbt17:
%t20 = load i32, i32* %t16
%t21 = load i32, i32* @n1
%t22 = icmp slt i32 %t20, %t21
br i1 %t22, label %bbt18, label %bbt19
bbt18:
%t23 = load i32, i32* %t2
%t24 = mul i32 %t23, 100
%t25 = add i32 0, %t24
%t26 = load i32, i32* %t9
%t27 = add i32 %t25, %t26
%t28 = getelementptr [10000 x i32], [10000 x i32]* @res, i32 0, i32 %t27
%t29 = load i32, i32* %t28
%t30 = load i32, i32* %t2
%t31 = mul i32 %t30, 100
%t32 = add i32 0, %t31
%t33 = load i32, i32* %t16
%t34 = add i32 %t32, %t33
%t35 = getelementptr [10000 x i32], [10000 x i32]* @a, i32 0, i32 %t34
%t36 = load i32, i32* %t35
%t37 = load i32, i32* %t16
%t38 = mul i32 %t37, 100
%t39 = add i32 0, %t38
%t40 = load i32, i32* %t9
%t41 = add i32 %t39, %t40
%t42 = getelementptr [10000 x i32], [10000 x i32]* @b, i32 0, i32 %t41
%t43 = load i32, i32* %t42
%t44 = mul i32 %t36, %t43
%t45 = add i32 %t29, %t44
%t46 = load i32, i32* %t2
%t47 = mul i32 %t46, 100
%t48 = add i32 0, %t47
%t49 = load i32, i32* %t9
%t50 = add i32 %t48, %t49
%t51 = getelementptr [10000 x i32], [10000 x i32]* @res, i32 0, i32 %t50
store i32 %t45, i32* %t51
%t52 = load i32, i32* %t16
%t53 = add i32 %t52, 1
store i32 %t53, i32* %t16
br label %bbt17
bbt19:
%t54 = load i32, i32* %t9
%t55 = add i32 %t54, 1
store i32 %t55, i32* %t9
br label %bbt10
}
define i32 @main() {
entry:
%t59 = alloca i32
%t60 = alloca i32
%t61 = alloca i32
br label %bbt58
bbt58:
store i32 0, i32* %t60
store i32 0, i32* %t61
%t62 = call i32 @getint()
store i32 %t62, i32* @m1
%t63 = call i32 @getint()
store i32 %t63, i32* @n1
store i32 0, i32* %t60
br label %bbt64
bbt64:
%t67 = load i32, i32* %t60
%t68 = load i32, i32* @m1
%t69 = icmp slt i32 %t67, %t68
br i1 %t69, label %bbt65, label %bbt66
bbt65:
store i32 0, i32* %t61
br label %bbt70
bbt66:
%t87 = call i32 @getint()
store i32 %t87, i32* @m2
%t88 = call i32 @getint()
store i32 %t88, i32* @n2
store i32 0, i32* %t60
br label %bbt89
bbt70:
%t73 = load i32, i32* %t61
%t74 = load i32, i32* @n1
%t75 = icmp slt i32 %t73, %t74
br i1 %t75, label %bbt71, label %bbt72
bbt71:
%t76 = call i32 @getint()
%t77 = load i32, i32* %t60
%t78 = mul i32 %t77, 100
%t79 = add i32 0, %t78
%t80 = load i32, i32* %t61
%t81 = add i32 %t79, %t80
%t82 = getelementptr [10000 x i32], [10000 x i32]* @a, i32 0, i32 %t81
store i32 %t76, i32* %t82
%t83 = load i32, i32* %t61
%t84 = add i32 %t83, 1
store i32 %t84, i32* %t61
br label %bbt70
bbt72:
%t85 = load i32, i32* %t60
%t86 = add i32 %t85, 1
store i32 %t86, i32* %t60
br label %bbt64
bbt89:
%t92 = load i32, i32* %t60
%t93 = load i32, i32* @m2
%t94 = icmp slt i32 %t92, %t93
br i1 %t94, label %bbt90, label %bbt91
bbt90:
store i32 0, i32* %t61
br label %bbt95
bbt91:
call void @matrix_multiply()
store i32 0, i32* %t60
br label %bbt112
bbt95:
%t98 = load i32, i32* %t61
%t99 = load i32, i32* @n2
%t100 = icmp slt i32 %t98, %t99
br i1 %t100, label %bbt96, label %bbt97
bbt96:
%t101 = call i32 @getint()
%t102 = load i32, i32* %t60
%t103 = mul i32 %t102, 100
%t104 = add i32 0, %t103
%t105 = load i32, i32* %t61
%t106 = add i32 %t104, %t105
%t107 = getelementptr [10000 x i32], [10000 x i32]* @b, i32 0, i32 %t106
store i32 %t101, i32* %t107
%t108 = load i32, i32* %t61
%t109 = add i32 %t108, 1
store i32 %t109, i32* %t61
br label %bbt95
bbt97:
%t110 = load i32, i32* %t60
%t111 = add i32 %t110, 1
store i32 %t111, i32* %t60
br label %bbt89
bbt112:
%t115 = load i32, i32* %t60
%t116 = load i32, i32* @m1
%t117 = icmp slt i32 %t115, %t116
br i1 %t117, label %bbt113, label %bbt114
bbt113:
store i32 0, i32* %t61
br label %bbt118
bbt114:
ret i32 0
bbt118:
%t121 = load i32, i32* %t61
%t122 = load i32, i32* @n2
%t123 = icmp slt i32 %t121, %t122
br i1 %t123, label %bbt119, label %bbt120
bbt119:
%t124 = load i32, i32* %t60
%t125 = mul i32 %t124, 100
%t126 = add i32 0, %t125
%t127 = load i32, i32* %t61
%t128 = add i32 %t126, %t127
%t129 = getelementptr [10000 x i32], [10000 x i32]* @res, i32 0, i32 %t128
%t130 = load i32, i32* %t129
call void @putint(i32 %t130)
call void @putch(i32 32)
%t131 = load i32, i32* %t61
%t132 = add i32 %t131, 1
store i32 %t132, i32* %t61
br label %bbt118
bbt120:
call void @putch(i32 10)
%t133 = load i32, i32* %t60
%t134 = add i32 %t133, 1
store i32 %t134, i32* %t60
br label %bbt112
}

@ -0,0 +1,133 @@
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32
%t3 = alloca i32
%t6 = alloca i32
%t18 = alloca i32
%t34 = alloca i32
%t49 = alloca i32
%t54 = alloca i32
%t67 = alloca i32
br label %bbt0
bbt0:
call void @putch(i32 97)
call void @putch(i32 10)
store i32 1, i32* %t2
store i32 0, i32* %t3
%t4 = load i32, i32* %t2
%t5 = add i32 %t4, 2
store i32 %t5, i32* %t2
%t7 = load i32, i32* %t2
%t8 = add i32 %t7, 3
store i32 %t8, i32* %t6
%t9 = load i32, i32* %t6
%t10 = add i32 %t9, 4
store i32 %t10, i32* %t6
%t11 = load i32, i32* %t3
%t12 = load i32, i32* %t2
%t13 = add i32 %t11, %t12
%t14 = load i32, i32* %t6
%t15 = add i32 %t13, %t14
store i32 %t15, i32* %t3
%t16 = load i32, i32* %t6
%t17 = add i32 %t16, 5
store i32 %t17, i32* %t6
%t19 = load i32, i32* %t6
%t20 = add i32 %t19, 6
store i32 %t20, i32* %t18
%t21 = load i32, i32* %t2
%t22 = load i32, i32* %t18
%t23 = add i32 %t21, %t22
store i32 %t23, i32* %t2
%t24 = load i32, i32* %t3
%t25 = load i32, i32* %t2
%t26 = add i32 %t24, %t25
%t27 = load i32, i32* %t6
%t28 = add i32 %t26, %t27
%t29 = load i32, i32* %t18
%t30 = add i32 %t28, %t29
store i32 %t30, i32* %t3
%t31 = load i32, i32* %t6
%t32 = load i32, i32* %t2
%t33 = add i32 %t31, %t32
store i32 %t33, i32* %t6
%t35 = load i32, i32* %t18
%t36 = add i32 %t35, 7
store i32 %t36, i32* %t34
%t37 = load i32, i32* %t34
%t38 = add i32 %t37, 8
store i32 %t38, i32* %t34
%t39 = load i32, i32* %t3
%t40 = load i32, i32* %t34
%t41 = add i32 %t39, %t40
%t42 = load i32, i32* %t6
%t43 = add i32 %t41, %t42
%t44 = load i32, i32* %t18
%t45 = add i32 %t43, %t44
store i32 %t45, i32* %t3
%t46 = load i32, i32* %t6
%t47 = load i32, i32* %t34
%t48 = add i32 %t46, %t47
store i32 %t48, i32* %t6
%t50 = load i32, i32* %t18
%t51 = add i32 %t50, 9
store i32 %t51, i32* %t49
%t52 = load i32, i32* %t34
%t53 = add i32 %t52, 10
store i32 %t53, i32* %t34
store i32 11, i32* %t54
%t55 = load i32, i32* %t49
%t56 = add i32 %t55, 12
store i32 %t56, i32* %t49
%t57 = load i32, i32* %t3
%t58 = load i32, i32* %t54
%t59 = add i32 %t57, %t58
%t60 = load i32, i32* %t49
%t61 = add i32 %t59, %t60
%t62 = load i32, i32* %t18
%t63 = add i32 %t61, %t62
store i32 %t63, i32* %t3
%t64 = load i32, i32* %t18
%t65 = load i32, i32* %t49
%t66 = add i32 %t64, %t65
store i32 %t66, i32* %t18
%t68 = load i32, i32* %t49
%t69 = add i32 %t68, 13
store i32 %t69, i32* %t67
%t70 = load i32, i32* %t67
%t71 = load i32, i32* %t54
%t72 = add i32 %t70, %t71
store i32 %t72, i32* %t67
%t73 = load i32, i32* %t3
%t74 = load i32, i32* %t54
%t75 = add i32 %t73, %t74
%t76 = load i32, i32* %t49
%t77 = add i32 %t75, %t76
%t78 = load i32, i32* %t67
%t79 = add i32 %t77, %t78
store i32 %t79, i32* %t3
%t80 = load i32, i32* %t3
%t81 = load i32, i32* %t18
%t82 = sub i32 %t80, %t81
store i32 %t82, i32* %t3
%t83 = load i32, i32* %t3
%t84 = load i32, i32* %t6
%t85 = sub i32 %t83, %t84
store i32 %t85, i32* %t3
%t86 = load i32, i32* %t3
%t87 = load i32, i32* %t2
%t88 = sub i32 %t86, %t87
store i32 %t88, i32* %t3
%t89 = load i32, i32* %t3
%t90 = srem i32 %t89, 77
ret i32 %t90
}

@ -0,0 +1,43 @@
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32
%t3 = alloca i32
br label %bbt0
bbt0:
store i32 0, i32* %t2
store i32 0, i32* %t2
store i32 0, i32* %t3
store i32 0, i32* %t3
br label %bbt4
bbt4:
%t7 = load i32, i32* %t2
%t8 = icmp slt i32 %t7, 100
br i1 %t8, label %bbt5, label %bbt6
bbt5:
%t11 = load i32, i32* %t2
%t12 = icmp eq i32 %t11, 50
br i1 %t12, label %bbt9, label %bbt10
bbt6:
%t18 = load i32, i32* %t3
ret i32 %t18
bbt9:
br label %bbt6
bbt10:
%t13 = load i32, i32* %t3
%t14 = load i32, i32* %t2
%t15 = add i32 %t13, %t14
store i32 %t15, i32* %t3
%t16 = load i32, i32* %t2
%t17 = add i32 %t16, 1
store i32 %t17, i32* %t2
br label %bbt4
}

@ -0,0 +1,34 @@
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32
%t3 = alloca i32
%t4 = alloca i32
%t5 = alloca i32
br label %bbt0
bbt0:
store i32 0, i32* %t2
store i32 0, i32* %t3
store i32 0, i32* %t4
store i32 0, i32* %t5
store i32 10, i32* %t2
store i32 4, i32* %t3
store i32 2, i32* %t4
store i32 2, i32* %t5
%t6 = load i32, i32* %t4
%t7 = load i32, i32* %t2
%t8 = add i32 %t6, %t7
%t9 = load i32, i32* %t3
%t10 = load i32, i32* %t5
%t11 = sub i32 %t9, %t10
%t12 = mul i32 %t8, %t11
ret i32 %t12
}

@ -0,0 +1,280 @@
; ModuleID = '/tmp/nudt_float_fallback_EB5hgk.c'
source_filename = "/tmp/nudt_float_fallback_EB5hgk.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@RADIUS = dso_local constant float 5.500000e+00, align 4
@PI = dso_local constant float 0x400921FB60000000, align 4
@EPS = dso_local constant float 0x3EB0C6F7A0000000, align 4
@PI_HEX = dso_local constant float 0x400921FB60000000, align 4
@HEX2 = dso_local constant float 7.812500e-02, align 4
@FACT = dso_local constant float -3.300000e+04, align 4
@EVAL1 = dso_local constant float 0x4057C21FC0000000, align 4
@EVAL2 = dso_local constant float 0x4041475CE0000000, align 4
@EVAL3 = dso_local constant float 0x4041475CE0000000, align 4
@CONV1 = dso_local constant float 2.330000e+02, align 4
@CONV2 = dso_local constant float 4.095000e+03, align 4
@MAX = dso_local constant i32 1000000000, align 4
@TWO = dso_local constant i32 2, align 4
@THREE = dso_local constant i32 3, align 4
@FIVE = dso_local constant i32 5, align 4
; Function Attrs: noinline nounwind optnone uwtable
define dso_local float @float_abs(float noundef %0) #0 {
%2 = alloca float, align 4
%3 = alloca float, align 4
store float %0, ptr %3, align 4
%4 = load float, ptr %3, align 4
%5 = fcmp olt float %4, 0.000000e+00
br i1 %5, label %6, label %9
6: ; preds = %1
%7 = load float, ptr %3, align 4
%8 = fneg float %7
store float %8, ptr %2, align 4
br label %11
9: ; preds = %1
%10 = load float, ptr %3, align 4
store float %10, ptr %2, align 4
br label %11
11: ; preds = %9, %6
%12 = load float, ptr %2, align 4
ret float %12
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local float @circle_area(i32 noundef %0) #0 {
%2 = alloca i32, align 4
store i32 %0, ptr %2, align 4
%3 = load i32, ptr %2, align 4
%4 = sitofp i32 %3 to float
%5 = fmul float 0x400921FB60000000, %4
%6 = load i32, ptr %2, align 4
%7 = sitofp i32 %6 to float
%8 = load i32, ptr %2, align 4
%9 = load i32, ptr %2, align 4
%10 = mul nsw i32 %8, %9
%11 = sitofp i32 %10 to float
%12 = fmul float %11, 0x400921FB60000000
%13 = call float @llvm.fmuladd.f32(float %5, float %7, float %12)
%14 = fdiv float %13, 2.000000e+00
ret float %14
}
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare float @llvm.fmuladd.f32(float, float, float) #1
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @float_eq(float noundef %0, float noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca float, align 4
%5 = alloca float, align 4
store float %0, ptr %4, align 4
store float %1, ptr %5, align 4
%6 = load float, ptr %4, align 4
%7 = load float, ptr %5, align 4
%8 = fsub float %6, %7
%9 = call float @float_abs(float noundef %8)
%10 = fcmp olt float %9, 0x3EB0C6F7A0000000
br i1 %10, label %11, label %12
11: ; preds = %2
store i32 1, ptr %3, align 4
br label %13
12: ; preds = %2
store i32 0, ptr %3, align 4
br label %13
13: ; preds = %12, %11
%14 = load i32, ptr %3, align 4
ret i32 %14
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @error() #0 {
call void @putch(i32 noundef 101)
call void @putch(i32 noundef 114)
call void @putch(i32 noundef 114)
call void @putch(i32 noundef 111)
call void @putch(i32 noundef 114)
call void @putch(i32 noundef 10)
ret void
}
declare void @putch(i32 noundef) #2
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @ok() #0 {
call void @putch(i32 noundef 111)
call void @putch(i32 noundef 107)
call void @putch(i32 noundef 10)
ret void
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @assert(i32 noundef %0) #0 {
%2 = alloca i32, align 4
store i32 %0, ptr %2, align 4
%3 = load i32, ptr %2, align 4
%4 = icmp ne i32 %3, 0
br i1 %4, label %6, label %5
5: ; preds = %1
call void @error()
br label %7
6: ; preds = %1
call void @ok()
br label %7
7: ; preds = %6, %5
ret void
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @assert_not(i32 noundef %0) #0 {
%2 = alloca i32, align 4
store i32 %0, ptr %2, align 4
%3 = load i32, ptr %2, align 4
%4 = icmp ne i32 %3, 0
br i1 %4, label %5, label %6
5: ; preds = %1
call void @error()
br label %7
6: ; preds = %1
call void @ok()
br label %7
7: ; preds = %6, %5
ret void
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca [10 x float], align 16
%5 = alloca i32, align 4
%6 = alloca float, align 4
%7 = alloca float, align 4
%8 = alloca float, align 4
store i32 0, ptr %1, align 4
%9 = call i32 @float_eq(float noundef 7.812500e-02, float noundef -3.300000e+04)
call void @assert_not(i32 noundef %9)
%10 = call i32 @float_eq(float noundef 0x4057C21FC0000000, float noundef 0x4041475CE0000000)
call void @assert_not(i32 noundef %10)
%11 = call i32 @float_eq(float noundef 0x4041475CE0000000, float noundef 0x4041475CE0000000)
call void @assert(i32 noundef %11)
%12 = call float @circle_area(i32 noundef 5)
%13 = call float @circle_area(i32 noundef 5)
%14 = call i32 @float_eq(float noundef %12, float noundef %13)
call void @assert(i32 noundef %14)
%15 = call i32 @float_eq(float noundef 2.330000e+02, float noundef 4.095000e+03)
call void @assert_not(i32 noundef %15)
br i1 true, label %16, label %17
16: ; preds = %0
call void @ok()
br label %17
17: ; preds = %16, %0
call void @ok()
call void @ok()
store i32 1, ptr %2, align 4
store i32 0, ptr %3, align 4
call void @llvm.memset.p0.i64(ptr align 16 %4, i8 0, i64 40, i1 false)
%18 = getelementptr inbounds <{ float, float, [8 x float] }>, ptr %4, i32 0, i32 0
store float 1.000000e+00, ptr %18, align 16
%19 = getelementptr inbounds <{ float, float, [8 x float] }>, ptr %4, i32 0, i32 1
store float 2.000000e+00, ptr %19, align 4
%20 = getelementptr inbounds [10 x float], ptr %4, i64 0, i64 0
%21 = call i32 @getfarray(ptr noundef %20)
store i32 %21, ptr %5, align 4
br label %22
22: ; preds = %25, %17
%23 = load i32, ptr %2, align 4
%24 = icmp slt i32 %23, 1000000000
br i1 %24, label %25, label %52
25: ; preds = %22
%26 = call float @getfloat()
store float %26, ptr %6, align 4
%27 = load float, ptr %6, align 4
%28 = fmul float 0x400921FB60000000, %27
%29 = load float, ptr %6, align 4
%30 = fmul float %28, %29
store float %30, ptr %7, align 4
%31 = load float, ptr %6, align 4
%32 = fptosi float %31 to i32
%33 = call float @circle_area(i32 noundef %32)
store float %33, ptr %8, align 4
%34 = load i32, ptr %3, align 4
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds [10 x float], ptr %4, i64 0, i64 %35
%37 = load float, ptr %36, align 4
%38 = load float, ptr %6, align 4
%39 = fadd float %37, %38
%40 = load i32, ptr %3, align 4
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds [10 x float], ptr %4, i64 0, i64 %41
store float %39, ptr %42, align 4
%43 = load float, ptr %7, align 4
call void @putfloat(float noundef %43)
call void @putch(i32 noundef 32)
%44 = load float, ptr %8, align 4
%45 = fptosi float %44 to i32
call void @putint(i32 noundef %45)
call void @putch(i32 noundef 10)
%46 = load i32, ptr %2, align 4
%47 = sitofp i32 %46 to double
%48 = fmul double %47, 1.000000e+01
%49 = fptosi double %48 to i32
store i32 %49, ptr %2, align 4
%50 = load i32, ptr %3, align 4
%51 = add nsw i32 %50, 1
store i32 %51, ptr %3, align 4
br label %22, !llvm.loop !6
52: ; preds = %22
%53 = load i32, ptr %5, align 4
%54 = getelementptr inbounds [10 x float], ptr %4, i64 0, i64 0
call void @putfarray(i32 noundef %53, ptr noundef %54)
ret i32 0
}
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #3
declare i32 @getfarray(ptr noundef) #2
declare float @getfloat() #2
declare void @putfloat(float noundef) #2
declare void @putint(i32 noundef) #2
declare void @putfarray(i32 noundef, ptr noundef) #2
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #2 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"Ubuntu clang version 18.1.3 (1ubuntu1)"}
!6 = distinct !{!6, !7}
!7 = !{!"llvm.loop.mustprogress"}

@ -0,0 +1,22 @@
declare i32 @getint()
declare i32 @getch()
declare void @putint(i32)
declare void @putch(i32)
declare i32 @getarray(i32*)
declare void @putarray(i32, i32*)
declare void @starttime()
declare void @stoptime()
define i32 @main() {
entry:
%t1 = alloca i32
%t2 = alloca i32
%t3 = alloca i32
br label %bbt0
bbt0:
store i32 1, i32* %t2
store i32 2, i32* %t3
%t4 = load i32, i32* %t2
%t5 = load i32, i32* %t3
%t6 = add i32 %t4, %t5
ret i32 %t6
}
Loading…
Cancel
Save