"IRGen部分实现,任务1完成"

lc 1 week ago committed by olivame
parent 8e12df10bb
commit 1cc632e42b

@ -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 常量声明
<br />
<br />
## 人员 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`
后续人员可以在此基础上扩展更复杂的功能(控制流、函数调用等)。

@ -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

@ -0,0 +1,6 @@
// 测试:简单加法
int main() {
int a = 1;
int b = 2;
return a + b;
}

@ -0,0 +1,8 @@
// 测试:减法和乘法
int main() {
int a = 10;
int b = 3;
int c = a - b;
int d = a * b;
return c + d;
}

@ -0,0 +1,8 @@
// 测试:除法和取模
int main() {
int a = 20;
int b = 6;
int c = a / b;
int d = a % b;
return c + d;
}

@ -0,0 +1,7 @@
// 测试:一元运算符(正负号)
int main() {
int a = 5;
int b = -a;
int c = +10;
return b + c;
}

@ -0,0 +1,7 @@
// 测试:赋值表达式
int main() {
int a = 10;
int b = 20;
a = b;
return a;
}

@ -0,0 +1,5 @@
// 测试:逗号分隔的多变量声明
int main() {
int a = 1, b = 2, c = 3;
return a + b + c;
}

@ -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;
}
Loading…
Cancel
Save