From 8ba3b01271da0e62110b2c7ce713aca555a80f91 Mon Sep 17 00:00:00 2001
From: lc <18783417278@163.com>
Date: Mon, 30 Mar 2026 20:57:41 +0800
Subject: [PATCH] =?UTF-8?q?"IRGen=E9=83=A8=E5=88=86=E5=AE=9E=E7=8E=B0?=
=?UTF-8?q?=EF=BC=8C=E4=BB=BB=E5=8A=A11=E5=AE=8C=E6=88=90"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doc/lab2剩余任务分工.md | 51 +++++-
scripts/test_lab2_ir1.sh | 157 ++++++++++++++++++
scripts/test_lab2_sema.sh | 0
test/test_case/irgen_lab1_4/01_simple_add.out | 1 +
test/test_case/irgen_lab1_4/01_simple_add.sy | 6 +
test/test_case/irgen_lab1_4/02_sub_mul.out | 1 +
test/test_case/irgen_lab1_4/02_sub_mul.sy | 8 +
test/test_case/irgen_lab1_4/03_div_mod.out | 1 +
test/test_case/irgen_lab1_4/03_div_mod.sy | 8 +
test/test_case/irgen_lab1_4/04_unary.out | 1 +
test/test_case/irgen_lab1_4/04_unary.sy | 7 +
test/test_case/irgen_lab1_4/05_assign.out | 1 +
test/test_case/irgen_lab1_4/05_assign.sy | 7 +
test/test_case/irgen_lab1_4/06_multi_decl.out | 1 +
test/test_case/irgen_lab1_4/06_multi_decl.sy | 5 +
.../irgen_lab1_4/07_comprehensive.out | 1 +
.../irgen_lab1_4/07_comprehensive.sy | 14 ++
17 files changed, 269 insertions(+), 1 deletion(-)
create mode 100755 scripts/test_lab2_ir1.sh
mode change 100644 => 100755 scripts/test_lab2_sema.sh
create mode 100644 test/test_case/irgen_lab1_4/01_simple_add.out
create mode 100644 test/test_case/irgen_lab1_4/01_simple_add.sy
create mode 100644 test/test_case/irgen_lab1_4/02_sub_mul.out
create mode 100644 test/test_case/irgen_lab1_4/02_sub_mul.sy
create mode 100644 test/test_case/irgen_lab1_4/03_div_mod.out
create mode 100644 test/test_case/irgen_lab1_4/03_div_mod.sy
create mode 100644 test/test_case/irgen_lab1_4/04_unary.out
create mode 100644 test/test_case/irgen_lab1_4/04_unary.sy
create mode 100644 test/test_case/irgen_lab1_4/05_assign.out
create mode 100644 test/test_case/irgen_lab1_4/05_assign.sy
create mode 100644 test/test_case/irgen_lab1_4/06_multi_decl.out
create mode 100644 test/test_case/irgen_lab1_4/06_multi_decl.sy
create mode 100644 test/test_case/irgen_lab1_4/07_comprehensive.out
create mode 100644 test/test_case/irgen_lab1_4/07_comprehensive.sy
diff --git a/doc/lab2剩余任务分工.md b/doc/lab2剩余任务分工.md
index 9ba8abb..70e63de 100644
--- a/doc/lab2剩余任务分工.md
+++ b/doc/lab2剩余任务分工.md
@@ -1,4 +1,4 @@
-### 人员 1:基础表达式与赋值支持(lc)
+### 人员 1:基础表达式与赋值支持(lc,已完成)
- 任务 1.1:支持更多二元运算符(Sub, Mul, Div, Mod)
- 任务 1.2:支持一元运算符(正负号)
@@ -19,3 +19,52 @@
- 任务 3.3:支持函数调用生成
- 任务 3.4:支持 const 常量声明
+
+
+
+
+## 人员 1 完成情况详细说明(更新于 2026-03-30)
+
+### ✅ 已完成任务
+
+人员 1 已完整实现 Lab2 IR 生成的基础功能模块,包括:
+
+1. **二元运算符**(任务 1.1)
+ - 实现 `Sub`, `Mul`, `Div`, `Mod` 四种运算符
+ - 修改文件:`include/ir/IR.h`, `src/ir/IRBuilder.cpp`, `src/ir/IRPrinter.cpp`, `src/irgen/IRGenExp.cpp`
+2. **一元运算符**(任务 1.2)
+ - 实现正负号运算符(`+`, `-`)
+ - 新增 `UnaryInst` 类支持一元指令
+ - 负号生成 `sub 0, x` 指令(LLVM IR 标准形式)
+3. **赋值表达式**(任务 1.3)
+ - 实现变量赋值语句的 IR 生成
+ - 修改文件:`src/irgen/IRGenStmt.cpp`
+4. **多变量声明**(任务 1.4)
+ - 支持逗号分隔的变量声明(如 `int a, b, c;`)
+ - 支持带初始化的多变量声明(如 `int a = 1, b = 2;`)
+
+### 🧪 测试验证
+
+- **Lab1 语法分析**:✅ 通过(10/11 functional 测试,1 个数组测试超出范围)
+- **Lab2 语义分析**:✅ 通过(6 正例 + 4 反例)
+- **IR 生成测试**:✅ 通过(7/7 自定义测试用例)
+ - 测试脚本:`./scripts/test_lab2_ir1.sh`
+ - 测试用例目录:`test/test_case/irgen_lab1_4/`
+
+### 📝 代码质量
+
+- 所有修改已通过编译测试
+- 未影响原有 Lab1 和 Lab2 Sema 功能
+- 代码风格与项目保持一致
+- 关键函数添加了注释说明
+
+### 🔄 协作接口
+
+人员 1 的实现为后续任务提供了以下接口:
+
+- **表达式生成**:`visitAddExp`, `visitMulExp`, `visitUnaryExp`
+- **语句生成**:`visitStmt`(支持赋值和 return)
+- **变量管理**:`storage_map_` 维护变量名到栈槽位的映射
+- **IR 构建**:`IRBuilder::CreateBinary`, `IRBuilder::CreateNeg`, `IRBuilder::CreateStore`
+
+后续人员可以在此基础上扩展更复杂的功能(控制流、函数调用等)。
diff --git a/scripts/test_lab2_ir1.sh b/scripts/test_lab2_ir1.sh
new file mode 100755
index 0000000..65f9c3f
--- /dev/null
+++ b/scripts/test_lab2_ir1.sh
@@ -0,0 +1,157 @@
+#!/usr/bin/env bash
+# 测试 Lab2 IR 生成 - 人员 1 的任务
+# 测试内容:
+# - 任务 1.1: 支持更多二元运算符(Sub, Mul, Div, Mod)
+# - 任务 1.2: 支持一元运算符(正负号)
+# - 任务 1.3: 支持赋值表达式
+# - 任务 1.4: 支持逗号分隔的多个变量声明
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
+COMPILER="$PROJECT_ROOT/build/bin/compiler"
+TEST_DIR="$PROJECT_ROOT/test/test_case/irgen_lab1_4"
+RESULT_DIR="$PROJECT_ROOT/test/test_result/lab2_ir1"
+
+# 颜色输出
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+echo "========================================="
+echo "Lab2 IR 生成测试 - 部分任务验证"
+echo "========================================="
+echo ""
+
+# 检查编译器是否存在
+if [[ ! -x "$COMPILER" ]]; then
+ echo -e "${RED}错误:编译器不存在或不可执行:$COMPILER${NC}"
+ echo "请先运行:cmake --build build"
+ exit 1
+fi
+
+# 检查测试目录是否存在
+if [[ ! -d "$TEST_DIR" ]]; then
+ echo -e "${RED}错误:测试目录不存在:$TEST_DIR${NC}"
+ exit 1
+fi
+
+# 创建结果目录
+mkdir -p "$RESULT_DIR"
+
+# 统计
+total=0
+passed=0
+failed=0
+
+# 测试函数
+run_test() {
+ local input=$1
+ local basename=$(basename "$input" .sy)
+ local expected_out="$TEST_DIR/$basename.out"
+ local actual_out="$RESULT_DIR/$basename.actual.out"
+ local ll_file="$RESULT_DIR/$basename.ll"
+
+ ((total++)) || true
+
+ echo -n "测试 $basename ... "
+
+ # 生成 IR
+ if ! "$COMPILER" --emit-ir "$input" > "$ll_file" 2>&1; then
+ echo -e "${RED}IR 生成失败${NC}"
+ ((failed++)) || true
+ return 1
+ fi
+
+ # 如果需要运行并比对输出
+ if [[ -f "$expected_out" ]]; then
+ # 编译并运行
+ local exe_file="$RESULT_DIR/$basename"
+ if ! llc -O0 -filetype=obj "$ll_file" -o "$RESULT_DIR/$basename.o" 2>/dev/null; then
+ echo -e "${YELLOW}LLVM 编译失败 (llc)${NC}"
+ cat "$ll_file"
+ ((failed++)) || true
+ return 1
+ fi
+
+ if ! clang "$RESULT_DIR/$basename.o" -o "$exe_file" 2>/dev/null; then
+ echo -e "${YELLOW}链接失败 (clang)${NC}"
+ ((failed++)) || true
+ return 1
+ fi
+
+ # 运行程序,捕获返回值(低 8 位)
+ local exit_code=0
+ "$exe_file" > "$actual_out" 2>&1 || exit_code=$?
+
+ # 处理返回值(LLVM/AArch64 返回的是 8 位无符号整数)
+ if [[ $exit_code -gt 127 ]]; then
+ # 转换为有符号整数
+ exit_code=$((exit_code - 256))
+ fi
+ echo "$exit_code" > "$actual_out"
+
+ # 比对输出
+ if diff -q "$expected_out" "$actual_out" > /dev/null 2>&1; then
+ echo -e "${GREEN}✓ 通过${NC}"
+ ((passed++)) || true
+ return 0
+ else
+ echo -e "${RED}✗ 输出不匹配${NC}"
+ echo " 期望:$(cat "$expected_out")"
+ echo " 实际:$(cat "$actual_out")"
+ ((failed++)) || true
+ return 1
+ fi
+ else
+ # 没有期望输出,只检查 IR 生成
+ echo -e "${GREEN}✓ IR 生成成功${NC}"
+ ((passed++)) || true
+ return 0
+ fi
+}
+
+# 查找所有测试用例
+test_files=()
+while IFS= read -r -d '' file; do
+ test_files+=("$file")
+done < <(find "$TEST_DIR" -name "*.sy" -type f -print0 | sort -z)
+
+if [[ ${#test_files[@]} -eq 0 ]]; then
+ echo -e "${RED}未找到测试用例:$TEST_DIR${NC}"
+ exit 1
+fi
+
+echo "找到 ${#test_files[@]} 个测试用例"
+echo ""
+
+# 运行所有测试
+for test_file in "${test_files[@]}"; do
+ run_test "$test_file" || true
+done
+
+# 输出统计
+echo ""
+echo "========================================="
+echo "测试结果统计"
+echo "========================================="
+echo -e "总数:$total"
+echo -e "通过:${GREEN}$passed${NC}"
+echo -e "失败:${RED}$failed${NC}"
+echo ""
+
+if [[ $failed -eq 0 ]]; then
+ echo -e "${GREEN}✓ 所有测试通过!${NC}"
+ echo ""
+ echo "测试覆盖:"
+ echo " ✓ 任务 1.1: 二元运算符(Sub, Mul, Div, Mod)"
+ echo " ✓ 任务 1.2: 一元运算符(正负号)"
+ echo " ✓ 任务 1.3: 赋值表达式"
+ echo " ✓ 任务 1.4: 逗号分隔的多变量声明"
+ exit 0
+else
+ echo -e "${RED}✗ 有 $failed 个测试失败${NC}"
+ exit 1
+fi
diff --git a/scripts/test_lab2_sema.sh b/scripts/test_lab2_sema.sh
old mode 100644
new mode 100755
diff --git a/test/test_case/irgen_lab1_4/01_simple_add.out b/test/test_case/irgen_lab1_4/01_simple_add.out
new file mode 100644
index 0000000..00750ed
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/01_simple_add.out
@@ -0,0 +1 @@
+3
diff --git a/test/test_case/irgen_lab1_4/01_simple_add.sy b/test/test_case/irgen_lab1_4/01_simple_add.sy
new file mode 100644
index 0000000..8b5f091
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/01_simple_add.sy
@@ -0,0 +1,6 @@
+// 测试:简单加法
+int main() {
+ int a = 1;
+ int b = 2;
+ return a + b;
+}
diff --git a/test/test_case/irgen_lab1_4/02_sub_mul.out b/test/test_case/irgen_lab1_4/02_sub_mul.out
new file mode 100644
index 0000000..81b5c5d
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/02_sub_mul.out
@@ -0,0 +1 @@
+37
diff --git a/test/test_case/irgen_lab1_4/02_sub_mul.sy b/test/test_case/irgen_lab1_4/02_sub_mul.sy
new file mode 100644
index 0000000..8ddeca9
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/02_sub_mul.sy
@@ -0,0 +1,8 @@
+// 测试:减法和乘法
+int main() {
+ int a = 10;
+ int b = 3;
+ int c = a - b;
+ int d = a * b;
+ return c + d;
+}
diff --git a/test/test_case/irgen_lab1_4/03_div_mod.out b/test/test_case/irgen_lab1_4/03_div_mod.out
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/03_div_mod.out
@@ -0,0 +1 @@
+5
diff --git a/test/test_case/irgen_lab1_4/03_div_mod.sy b/test/test_case/irgen_lab1_4/03_div_mod.sy
new file mode 100644
index 0000000..beefc9e
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/03_div_mod.sy
@@ -0,0 +1,8 @@
+// 测试:除法和取模
+int main() {
+ int a = 20;
+ int b = 6;
+ int c = a / b;
+ int d = a % b;
+ return c + d;
+}
diff --git a/test/test_case/irgen_lab1_4/04_unary.out b/test/test_case/irgen_lab1_4/04_unary.out
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/04_unary.out
@@ -0,0 +1 @@
+5
diff --git a/test/test_case/irgen_lab1_4/04_unary.sy b/test/test_case/irgen_lab1_4/04_unary.sy
new file mode 100644
index 0000000..c36c5e1
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/04_unary.sy
@@ -0,0 +1,7 @@
+// 测试:一元运算符(正负号)
+int main() {
+ int a = 5;
+ int b = -a;
+ int c = +10;
+ return b + c;
+}
diff --git a/test/test_case/irgen_lab1_4/05_assign.out b/test/test_case/irgen_lab1_4/05_assign.out
new file mode 100644
index 0000000..209e3ef
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/05_assign.out
@@ -0,0 +1 @@
+20
diff --git a/test/test_case/irgen_lab1_4/05_assign.sy b/test/test_case/irgen_lab1_4/05_assign.sy
new file mode 100644
index 0000000..5e1eae2
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/05_assign.sy
@@ -0,0 +1,7 @@
+// 测试:赋值表达式
+int main() {
+ int a = 10;
+ int b = 20;
+ a = b;
+ return a;
+}
diff --git a/test/test_case/irgen_lab1_4/06_multi_decl.out b/test/test_case/irgen_lab1_4/06_multi_decl.out
new file mode 100644
index 0000000..1e8b314
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/06_multi_decl.out
@@ -0,0 +1 @@
+6
diff --git a/test/test_case/irgen_lab1_4/06_multi_decl.sy b/test/test_case/irgen_lab1_4/06_multi_decl.sy
new file mode 100644
index 0000000..fa95159
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/06_multi_decl.sy
@@ -0,0 +1,5 @@
+// 测试:逗号分隔的多变量声明
+int main() {
+ int a = 1, b = 2, c = 3;
+ return a + b + c;
+}
diff --git a/test/test_case/irgen_lab1_4/07_comprehensive.out b/test/test_case/irgen_lab1_4/07_comprehensive.out
new file mode 100644
index 0000000..81b5c5d
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/07_comprehensive.out
@@ -0,0 +1 @@
+37
diff --git a/test/test_case/irgen_lab1_4/07_comprehensive.sy b/test/test_case/irgen_lab1_4/07_comprehensive.sy
new file mode 100644
index 0000000..753aeae
--- /dev/null
+++ b/test/test_case/irgen_lab1_4/07_comprehensive.sy
@@ -0,0 +1,14 @@
+// 测试:综合测试(所有功能)
+int main() {
+ int a = 10, b = 5;
+ int c = a + b;
+ int d = a - b;
+ int e = a * 2;
+ int f = a / b;
+ int g = a % b;
+ int h = -c;
+ int i = +d;
+ a = b + c;
+ b = d + e;
+ return a + b + f + g + h + i;
+}