fix(mir):通过了所有功能测试样例

develop
cy 1 day ago
parent 6b6de49fcf
commit e26b9f8a43

5745
30.txt

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,65 +0,0 @@
#!/bin/bash
PROJECT_ROOT=$(cd "$(dirname "$0")/.." ; pwd)
COMPILER="$PROJECT_ROOT/build/bin/compiler"
TEST_DIR="$PROJECT_ROOT/test/test_case/basic"
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
if [ ! -f "$COMPILER" ]; then
echo "错误: 编译器不存在: $COMPILER"
exit 1
fi
echo "=========================================="
echo "RISC-V 浮点转换测试"
echo "=========================================="
TESTS="
float_conv:3
float_add:13
float_mul:30
"
PASS=0
FAIL=0
for test in $TESTS; do
name=$(echo $test | cut -d: -f1)
expected=$(echo $test | cut -d: -f2)
echo -n "测试 $name (期望 $expected) ... "
"$COMPILER" "$TEST_DIR/$name.sy" --emit-asm > /tmp/test_$name.s 2>&1
if [ $? -ne 0 ]; then
echo -e "${RED}失败 (汇编错误)${NC}"
cat /tmp/test_$name.s | head -3
FAIL=$((FAIL + 1))
continue
fi
riscv64-linux-gnu-gcc -static /tmp/test_$name.s -o /tmp/test_$name -no-pie 2>/dev/null
if [ $? -ne 0 ]; then
echo -e "${RED}失败 (链接错误)${NC}"
FAIL=$((FAIL + 1))
continue
fi
qemu-riscv64 /tmp/test_$name > /dev/null 2>&1
exit_code=$?
if [ $exit_code -eq $expected ]; then
echo -e "${GREEN}通过${NC}"
PASS=$((PASS + 1))
else
echo -e "${RED}失败 (实际 $exit_code)${NC}"
FAIL=$((FAIL + 1))
fi
done
echo "=========================================="
echo -e "测试结果: ${GREEN}通过 $PASS${NC} / ${RED}失败 $FAIL${NC}"
echo "=========================================="

@ -1,85 +0,0 @@
#!/bin/bash
# 获取项目根目录
PROJECT_ROOT=$(cd "$(dirname "$0")/.." ; pwd)
COMPILER="$PROJECT_ROOT/build/bin/compiler"
TEST_DIR="$PROJECT_ROOT/test/test_case/basic"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# 检查编译器
if [ ! -f "$COMPILER" ]; then
echo "错误: 编译器不存在: $COMPILER"
exit 1
fi
# 检查工具链
if ! command -v riscv64-linux-gnu-gcc >/dev/null 2>&1; then
echo "错误: 未找到 riscv64-linux-gnu-gcc"
exit 1
fi
if ! command -v qemu-riscv64 >/dev/null 2>&1; then
echo "错误: 未找到 qemu-riscv64"
exit 1
fi
echo "=========================================="
echo "RISC-V 基础功能测试"
echo "=========================================="
# 定义测试用例
TESTS="arith:50 add:30 sub:7 mul:50 div:25 mod:2 var:43"
PASS=0
FAIL=0
for test in $TESTS; do
name=$(echo $test | cut -d: -f1)
expected=$(echo $test | cut -d: -f2)
echo -n "测试 $name (期望 $expected) ... "
# 生成汇编
"$COMPILER" "$TEST_DIR/$name.sy" --emit-asm > /tmp/test_$name.s 2>&1
if [ $? -ne 0 ]; then
echo -e "${RED}失败 (汇编错误)${NC}"
FAIL=$((FAIL + 1))
continue
fi
# 链接
riscv64-linux-gnu-gcc -static /tmp/test_$name.s -o /tmp/test_$name -no-pie 2>/dev/null
if [ $? -ne 0 ]; then
echo -e "${RED}失败 (链接错误)${NC}"
FAIL=$((FAIL + 1))
continue
fi
# 运行
qemu-riscv64 /tmp/test_$name > /dev/null 2>&1
exit_code=$?
if [ $exit_code -eq $expected ]; then
echo -e "${GREEN}通过${NC}"
PASS=$((PASS + 1))
else
echo -e "${RED}失败 (实际 $exit_code)${NC}"
FAIL=$((FAIL + 1))
fi
done
echo "=========================================="
echo -e "测试结果: ${GREEN}通过 $PASS${NC} / ${RED}失败 $FAIL${NC}"
echo "=========================================="
if [ $FAIL -eq 0 ]; then
echo -e "${GREEN}✓ 所有基础测试通过!${NC}"
exit 0
else
echo -e "${RED}✗ 有 $FAIL 个测试失败${NC}"
exit 1
fi

@ -415,17 +415,22 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
}
case Opcode::CondBr: {
auto* true_target = reinterpret_cast<MachineBasicBlock*>(ops[1].GetImm64());
auto* false_target = reinterpret_cast<MachineBasicBlock*>(ops[2].GetImm64());
auto true_it = block_names.find(true_target);
auto false_it = block_names.find(false_target);
if (true_it == block_names.end() || false_it == block_names.end()) {
throw std::runtime_error(FormatError("mir", "CondBr: 找不到基本块名称"));
}
os << " bnez " << PhysRegName(ops[0].GetReg()) << ", "
<< true_it->second << "\n";
os << " j " << false_it->second << "\n";
break;
auto* true_target = reinterpret_cast<MachineBasicBlock*>(ops[1].GetImm64());
auto* false_target = reinterpret_cast<MachineBasicBlock*>(ops[2].GetImm64());
auto true_it = block_names.find(true_target);
auto false_it = block_names.find(false_target);
if (true_it == block_names.end() || false_it == block_names.end()) {
throw std::runtime_error(FormatError("mir", "CondBr: 找不到基本块名称"));
}
// 生成一个唯一的本地标签作为跳板
static int condbr_id = 0;
std::string temp_label = ".L_condbr_" + std::to_string(condbr_id++);
os << " bnez " << PhysRegName(ops[0].GetReg()) << ", " << temp_label << "\n";
os << " j " << false_it->second << "\n";
os << temp_label << ":\n";
os << " j " << true_it->second << "\n";
break;
}
// 浮点运算

@ -399,12 +399,34 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
case ir::Opcode::Call: {
auto& call = static_cast<const ir::CallInst&>(inst);
int numArgs = static_cast<int>(call.GetNumArgs());
int regArgs = std::min(numArgs, 8);
int stackArgs = numArgs - regArgs;
// 调用者动态扩展栈以容纳栈参数
int ireg = 0, freg = 0;
std::vector<std::pair<bool, ir::Value*>> stack_args; // (is_float, value)
for (int i = 0; i < numArgs; ++i) {
bool arg_is_float = call.GetArg(i)->GetType()->IsFloat32();
if (arg_is_float) {
if (freg < 8) {
PhysReg fregnum = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + freg);
EmitValueToReg(call.GetArg(i), fregnum, slots, block, function);
freg++;
} else {
stack_args.push_back({true, call.GetArg(i)});
}
} else { // integer or pointer
if (ireg < 8) {
PhysReg iregnum = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + ireg);
EmitValueToReg(call.GetArg(i), iregnum, slots, block, function);
ireg++;
} else {
stack_args.push_back({false, call.GetArg(i)});
}
}
}
int stackArgs = static_cast<int>(stack_args.size());
if (stackArgs > 0) {
int stackSpace = stackArgs * 8;
int stackSpace = (stackArgs * 8 + 15) & ~15;
// sp -= stackSpace
if (stackSpace <= 2047) {
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
@ -413,62 +435,54 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
} else {
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(-stackSpace)});
block.Append(Opcode::Add, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::T4)});
}
}
// 寄存器参数 (前 8 个)
for (int i = 0; i < regArgs; i++) {
bool arg_is_float = call.GetArg(i)->GetType()->IsFloat32();
if (arg_is_float) {
PhysReg freg = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + i);
EmitValueToReg(call.GetArg(i), freg, slots, block, function);
} else {
PhysReg ireg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + i);
EmitValueToReg(call.GetArg(i), ireg, slots, block, function);
}
}
// 栈参数:存入 sp + offset 处
for (int i = regArgs; i < numArgs; i++) {
bool arg_is_float = call.GetArg(i)->GetType()->IsFloat32();
int offset = (i - regArgs) * 8;
// 计算栈地址到 t4sp + offset
if (offset == 0) {
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::ZERO)});
} else if (offset <= 2047) {
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Imm(offset)});
} else {
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(offset)});
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::T4)});
Operand::Reg(PhysReg::T4)});
}
if (arg_is_float) {
// 浮点参数存入栈:使用现有的 StoreFloat 指令(会生成 fsw
EmitValueToReg(call.GetArg(i), PhysReg::FT0, slots, block, function);
block.Append(Opcode::StoreFloat,
{Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T4)});
} else {
// 整数/指针参数存入栈:使用现有的 Store 指令(会生成 sd
EmitValueToReg(call.GetArg(i), PhysReg::T0, slots, block, function);
block.Append(Opcode::Store,
{Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T4)});
for (int idx = 0; idx < stackArgs; ++idx) {
bool is_float = stack_args[idx].first;
ir::Value* val = stack_args[idx].second;
int offset = idx * 8;
// 1. 先加载值
if (is_float) {
EmitValueToReg(val, PhysReg::FT0, slots, block, function);
} else {
EmitValueToReg(val, PhysReg::T0, slots, block, function);
}
// 2. 再计算栈地址到 T4
if (offset == 0) {
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::ZERO)});
} else if (offset <= 2047) {
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Imm(offset)});
} else {
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(offset)});
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::T4)});
}
// 3. 存储
if (is_float) {
block.Append(Opcode::StoreFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T4)});
} else {
block.Append(Opcode::Store, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T4)});
}
}
}
// 调用目标
std::string func_name = call.GetCalleeName();
block.Append(Opcode::Call, {Operand::Func(func_name)});
// 恢复 sp
if (stackArgs > 0) {
int stackSpace = stackArgs * 8;
int stackSpace = (stackArgs * 8 + 15) & ~15;
if (stackSpace <= 2047) {
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
@ -476,12 +490,12 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
} else {
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(stackSpace)});
block.Append(Opcode::Add, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::T4)});
Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::T4)});
}
}
// 返回值处理(保持不变)
// 返回值处理(原有代码保持不变)
if (!call.GetType()->IsVoid()) {
int dst_slot = function.CreateFrameIndex();
bool ret_is_float = call.GetType()->IsFloat32();
@ -703,44 +717,40 @@ std::unique_ptr<MachineFunction> LowerFunctionToMIR(const ir::Function& func) {
auto machine_func = std::make_unique<MachineFunction>(func.GetName());
ValueSlotMap slots;
// 计算局部变量大小
int ireg = 0, freg = 0, stack_idx = 0;
for (size_t i = 0; i < func.GetNumArgs(); i++) {
ir::Argument* arg = func.GetArgument(i);
// 指针类型分配 8 字节,其他 4 字节(槽大小)
int size = (arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32()) ? 8 : 4;
int slot = machine_func->CreateFrameIndex(size);
MachineBasicBlock* entry = machine_func->GetEntry();
if (i < 8) {
// 寄存器参数:从 A0..A7 / FA0..FA7 保存到本地栈槽
PhysReg argReg;
if (arg->GetType()->IsFloat32()) {
argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + i);
if (arg->GetType()->IsFloat32()) {
if (freg < 8) {
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + freg);
entry->Append(Opcode::StoreFloat, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
freg++;
} else {
argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + i);
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
entry->Append(Opcode::LoadCallerStackArgFloat, {
Operand::Reg(PhysReg::FT0),
Operand::FrameIndex(slot),
Operand::Imm(stack_idx)
});
stack_idx++;
}
} else {
// 栈参数:从调用者的动态栈帧加载到本地栈槽
// 使用 LoadCallerStackArg 特殊指令,参数索引 = i - 8
if (arg->GetType()->IsFloat32()) {
entry->Append(Opcode::LoadCallerStackArgFloat, {
Operand::Reg(PhysReg::FT0), // 临时浮点寄存器
Operand::FrameIndex(slot), // 目标本地栈槽
Operand::Imm(static_cast<int>(i - 8)) // 栈参数索引
});
if (ireg < 8) {
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + ireg);
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
ireg++;
} else {
entry->Append(Opcode::LoadCallerStackArg, {
Operand::Reg(PhysReg::T0),
Operand::FrameIndex(slot),
Operand::Imm(static_cast<int>(i - 8))
});
entry->Append(Opcode::LoadCallerStackArg, {
Operand::Reg(PhysReg::T0),
Operand::FrameIndex(slot),
Operand::Imm(stack_idx)
});
stack_idx++;
}
}
slots[arg] = slot;
}

Loading…
Cancel
Save