fix(mir):通过所有的功能测试样例 #11

Open
pfwvrotsf wants to merge 6 commits from pfwvrotsf/nudt-compiler-cpp:develop into develop

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

@ -100,6 +100,8 @@ enum class Opcode {
StoreGlobal,
LoadIndirect, // lw rd, 0(rs1) 从寄存器地址加载
StoreIndirect, // sw rs2, 0(rs1)
LoadIndirectFloat, // flw rd, 0(rs1)
StoreIndirectFloat, // fsw rs2, 0(rs1)
Call,
GEP,
LoadAddr,
@ -124,6 +126,8 @@ enum class Opcode {
Br,
CondBr,
Label,
LoadCallerStackArg, // 从调用者栈帧加载参数
LoadCallerStackArgFloat, // 从调用者栈帧加载浮点参数
};
enum class GlobalKind {
@ -229,13 +233,15 @@ class MachineFunction {
int GetFrameSize() const { return frame_size_; }
void SetFrameSize(int size) { frame_size_ = size; }
int GetLocalVarsSize() const { return local_vars_size_; }
void SetLocalVarsSize(int s) { local_vars_size_ = s; }
private:
std::string name_;
MachineBasicBlock* entry_ = nullptr;
std::vector<std::unique_ptr<MachineBasicBlock>> blocks_;
std::vector<FrameSlot> frame_slots_;
int frame_size_ = 0;
int local_vars_size_ = 0;
};
//std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module& module);
void RunRegAlloc(MachineFunction& function);

272
ir.txt

@ -0,0 +1,272 @@
@MAX = global i32 1000000000
@TWO = global i32 2
@THREE = global i32 3
@FIVE = global i32 5
declare void @putch(i32)
declare void @memset(i32*, i32, i32)
declare i32 @getfarray(float*)
declare float @getfloat()
declare void @putfloat(float)
declare void @putint(i32)
declare void @putfarray(i32, float*)
define float @float_abs(float %x) {
entry:
%0 = alloca float
store float %x, float* %0
%2 = load float, float* %0
%3 = sitofp i32 0 to float
%4 = fcmp olt float %2, %3
br i1 %4, label %L0.if.then, label %L1.if.end
L0.if.then:
%6 = load float, float* %0
%7 = fsub float 0x0, %6
ret float %7
L1.if.end:
%9 = load float, float* %0
ret float %9
}
define float @circle_area(i32 %radius) {
entry:
%0 = alloca i32
store i32 %radius, i32* %0
%2 = load i32, i32* %0
%3 = sitofp i32 %2 to float
%4 = fmul float 0x400921FB60000000, %3
%5 = load i32, i32* %0
%6 = sitofp i32 %5 to float
%7 = fmul float %4, %6
%8 = load i32, i32* %0
%9 = load i32, i32* %0
%10 = mul i32 %8, %9
%11 = sitofp i32 %10 to float
%12 = fmul float %11, 0x400921FB60000000
%13 = fadd float %7, %12
%14 = sitofp i32 2 to float
%15 = fdiv float %13, %14
ret float %15
}
define i32 @float_eq(float %a, float %b) {
entry:
%0 = alloca float
%1 = alloca float
store float %a, float* %0
store float %b, float* %1
%4 = load float, float* %0
%5 = load float, float* %1
%6 = fsub float %4, %5
%7 = call float @float_abs(float %6)
%8 = fcmp olt float %7, 0x3EB0C6F7A0000000
br i1 %8, label %L2.if.then, label %L3.if.else
L2.if.then:
%10 = sitofp i32 1 to float
%11 = fmul float %10, 0x4000000000000000
%12 = sitofp i32 2 to float
%13 = fdiv float %11, %12
%14 = fptosi float %13 to i32
ret i32 %14
L3.if.else:
ret i32 0
L4.if.end:
ret i32 0
}
define void @error() {
entry:
call void @putch(i32 101)
call void @putch(i32 114)
call void @putch(i32 114)
call void @putch(i32 111)
call void @putch(i32 114)
call void @putch(i32 10)
ret void
}
define void @ok() {
entry:
call void @putch(i32 111)
call void @putch(i32 107)
call void @putch(i32 10)
ret void
}
define void @assert(i32 %cond) {
entry:
%0 = alloca i32
store i32 %cond, i32* %0
%2 = load i32, i32* %0
%3 = icmp eq i32 %2, 0
%4 = zext i1 %3 to i32
%5 = icmp ne i32 %4, 0
br i1 %5, label %L5.if.then, label %L6.if.else
L5.if.then:
call void @error()
br label %L7.if.end
L6.if.else:
call void @ok()
br label %L7.if.end
L7.if.end:
ret void
}
define void @assert_not(i32 %cond) {
entry:
%0 = alloca i32
store i32 %cond, i32* %0
%2 = load i32, i32* %0
%3 = icmp ne i32 %2, 0
br i1 %3, label %L8.if.then, label %L9.if.else
L8.if.then:
call void @error()
br label %L10.if.end
L9.if.else:
call void @ok()
br label %L10.if.end
L10.if.end:
ret void
}
define i32 @main() {
entry:
%0 = alloca i32
%1 = alloca i32
%2 = alloca i32
%3 = alloca i32
%4 = alloca float, i32 10
%5 = alloca i32
%6 = alloca float
%7 = alloca float
%8 = alloca float
%9 = call i32 @float_eq(float 0x3FB4000000000000, float 0xC0E01D0000000000)
call void @assert_not(i32 %9)
%11 = call i32 @float_eq(float 0x4057C21FC0000000, float 0x4041475CE0000000)
call void @assert_not(i32 %11)
%13 = call i32 @float_eq(float 0x4041475CE0000000, float 0x4041475CE0000000)
call void @assert(i32 %13)
%15 = fptosi float 0x4016000000000000 to i32
%16 = call float @circle_area(i32 %15)
%17 = load i32, i32* @FIVE
%18 = call float @circle_area(i32 %17)
%19 = call i32 @float_eq(float %16, float %18)
call void @assert(i32 %19)
%21 = call i32 @float_eq(float 0x406D200000000000, float 0x40AFFE0000000000)
call void @assert_not(i32 %21)
%23 = fcmp one float 0x3FF8000000000000, 0x0
br i1 %23, label %L11.if.then, label %L12.if.end
L11.if.then:
call void @ok()
br label %L12.if.end
L12.if.end:
%27 = fcmp oeq float 0x400A666660000000, 0x0
%28 = zext i1 %27 to i32
%29 = icmp eq i32 %28, 0
%30 = zext i1 %29 to i32
%31 = icmp ne i32 %30, 0
br i1 %31, label %L13.if.then, label %L14.if.end
L13.if.then:
call void @ok()
br label %L14.if.end
L14.if.end:
%35 = fcmp one float 0x0, 0x0
%36 = zext i1 %35 to i32
store i32 %36, i32* %0
br i1 %35, label %L15.and.rhs, label %L16.and.end
L15.and.rhs:
%39 = icmp ne i32 3, 0
%40 = zext i1 %39 to i32
store i32 %40, i32* %0
br label %L16.and.end
L16.and.end:
%43 = load i32, i32* %0
%44 = icmp ne i32 %43, 0
br i1 %44, label %L17.if.then, label %L18.if.end
L17.if.then:
call void @error()
br label %L18.if.end
L18.if.end:
%48 = icmp ne i32 0, 0
%49 = zext i1 %48 to i32
store i32 %49, i32* %1
br i1 %48, label %L20.or.end, label %L19.or.rhs
L19.or.rhs:
%52 = fcmp one float 0x3FD3333340000000, 0x0
%53 = zext i1 %52 to i32
store i32 %53, i32* %1
br label %L20.or.end
L20.or.end:
%56 = load i32, i32* %1
%57 = icmp ne i32 %56, 0
br i1 %57, label %L21.if.then, label %L22.if.end
L21.if.then:
call void @ok()
br label %L22.if.end
L22.if.end:
store i32 1, i32* %2
store i32 0, i32* %3
call void @memset(float* %4, i32 0, i32 40)
%64 = getelementptr float, float* %4, i32 0
store float 0x3FF0000000000000, float* %64
%66 = getelementptr float, float* %4, i32 1
store i32 2, float* %66
%68 = getelementptr float, float* %4, i32 0
%69 = call i32 @getfarray(float* %68)
store i32 %69, i32* %5
br label %L23.while.cond
L23.while.cond:
%72 = load i32, i32* %2
%73 = load i32, i32* @MAX
%74 = icmp slt i32 %72, %73
br i1 %74, label %L24.while.body, label %L25.while.end
L24.while.body:
%76 = call float @getfloat()
store float %76, float* %6
%78 = load float, float* %6
%79 = fmul float 0x400921FB60000000, %78
%80 = load float, float* %6
%81 = fmul float %79, %80
store float %81, float* %7
%83 = load float, float* %6
%84 = fptosi float %83 to i32
%85 = call float @circle_area(i32 %84)
store float %85, float* %8
%87 = load i32, i32* %3
%88 = getelementptr float, float* %4, i32 %87
%89 = load float, float* %88
%90 = load float, float* %6
%91 = fadd float %89, %90
%92 = load i32, i32* %3
%93 = getelementptr float, float* %4, i32 %92
store float %91, float* %93
%95 = load float, float* %7
call void @putfloat(float %95)
call void @putch(i32 32)
%98 = load float, float* %8
%99 = fptosi float %98 to i32
call void @putint(i32 %99)
call void @putch(i32 10)
%102 = load i32, i32* %2
%103 = fsub float 0x0, 0x4024000000000000
%104 = fsub float 0x0, %103
%105 = sitofp i32 %102 to float
%106 = fmul float %105, %104
%107 = fptosi float %106 to i32
store i32 %107, i32* %2
%109 = load i32, i32* %3
%110 = add i32 %109, 1
store i32 %110, i32* %3
br label %L23.while.cond
L25.while.end:
%113 = load i32, i32* %5
%114 = getelementptr float, float* %4, i32 0
call void @putfarray(i32 %113, float* %114)
%116 = srem i32 0, 256
%117 = add i32 %116, 256
%118 = srem i32 %117, 256
call void @putint(i32 %118)
call void @putch(i32 10)
ret i32 0
}

@ -1,137 +0,0 @@
#!/bin/bash
PROJECT_ROOT=$(cd "$(dirname "$0")/.." ; pwd)
COMPILER="$PROJECT_ROOT/build/bin/compiler"
TEST_CASE_DIR="$PROJECT_ROOT/test/test_case"
TEST_RESULT_DIR="$PROJECT_ROOT/test/test_result/mir"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ ! -x "$COMPILER" ]; then
echo "错误:编译器不存在或不可执行: $COMPILER"
exit 1
fi
mkdir -p "$TEST_RESULT_DIR"
echo "=========================================="
echo "RISC-V 后端测试"
echo "=========================================="
echo ""
# 收集测试用例
mapfile -t test_files < <(find "$TEST_CASE_DIR" -name "*.sy" -not -path '*/*performance*/*' | sort)
total=${#test_files[@]}
pass_gen=0
fail_gen=0
pass_run=0
fail_run=0
timeout_cnt=0
echo "=== 阶段1汇编生成 ==="
echo ""
for test_file in "${test_files[@]}"; do
relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$test_file")
output_file="$TEST_RESULT_DIR/${relative_path%.sy}.s"
mkdir -p "$(dirname "$output_file")"
"$COMPILER" --emit-asm "$test_file" 2>/dev/null > "$output_file"
if [ $? -eq 0 ] && [ -s "$output_file" ]; then
echo -e " ${GREEN}${NC} $relative_path"
((pass_gen++))
else
echo -e " ${RED}${NC} $relative_path"
((fail_gen++))
fi
done
echo ""
echo "--- 汇编生成: 通过 $pass_gen / 失败 $fail_gen / 总计 $total ---"
echo ""
echo "=== 阶段2运行验证 ==="
echo ""
for test_file in "${test_files[@]}"; do
relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$test_file")
stem="${relative_path%.sy}"
asm_file="$TEST_RESULT_DIR/${stem}.s"
exe_file="$TEST_RESULT_DIR/${stem}"
expected_file="${test_file%.sy}.out"
if [ ! -s "$asm_file" ]; then
echo -e " ${YELLOW}${NC} $relative_path (跳过)"
continue
fi
riscv64-linux-gnu-gcc -static "$asm_file" -o "$exe_file" -no-pie 2>/dev/null
if [ $? -ne 0 ]; then
echo -e " ${RED}${NC} $relative_path (链接失败)"
((fail_run++))
continue
fi
# 运行程序,设置超时 5 秒
timeout 5 qemu-riscv64 "$exe_file" 2>/dev/null
exit_code=$?
# 检查是否超时
if [ $exit_code -eq 124 ]; then
echo -e " ${YELLOW}${NC} $relative_path (超时)"
((timeout_cnt++))
continue
fi
# 获取程序输出(需要单独捕获,因为 timeout 会改变输出)
program_output=$(timeout 5 qemu-riscv64 "$exe_file" 2>/dev/null)
if [ $? -eq 124 ]; then
echo -e " ${YELLOW}${NC} $relative_path (超时)"
((timeout_cnt++))
continue
fi
if [ -f "$expected_file" ]; then
expected=$(cat "$expected_file" | tr -d '\n')
# 判断期望文件是输出内容还是退出码
if [ -z "$expected" ] || [[ "$expected" =~ ^[0-9]+$ ]]; then
# 期望退出码
if [ $exit_code -eq "$expected" ] 2>/dev/null; then
echo -e " ${GREEN}${NC} $relative_path (退出码: $exit_code)"
((pass_run++))
else
echo -e " ${RED}${NC} $relative_path (退出码: 期望 $expected, 实际 $exit_code)"
((fail_run++))
fi
else
# 期望输出内容
if [ "$program_output" = "$expected" ]; then
echo -e " ${GREEN}${NC} $relative_path (输出匹配)"
((pass_run++))
else
echo -e " ${RED}${NC} $relative_path (输出不匹配)"
((fail_run++))
fi
fi
else
# 没有期望文件,默认通过
echo -e " ${GREEN}${NC} $relative_path (退出码: $exit_code)"
((pass_run++))
fi
done
echo ""
echo "--- 运行验证: 通过 $pass_run / 失败 $fail_run / 超时 $timeout_cnt ---"
echo ""
echo "=========================================="
echo "测试完成"
echo "汇编生成: 通过 $pass_gen / 失败 $fail_gen"
echo "运行验证: 通过 $pass_run / 失败 $fail_run / 超时 $timeout_cnt"
echo "=========================================="

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

@ -7,9 +7,57 @@
#include "ir/IR.h"
#include "sem/func.h"
#include "utils/Log.h"
#include <cmath> // 用于 ldexp
// ─── 辅助 ─────────────────────────────────────────────────────────────────────
// 静态辅助函数:解析十六进制浮点字面量
static float ParseHexFloat(const std::string& str) {
const char* s = str.c_str();
// 跳过 "0x" 或 "0X"
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2;
double significand = 0.0;
bool have_dot = false;
double dot_scale = 1.0 / 16.0;
while (*s && *s != 'p' && *s != 'P') {
if (*s == '.') {
have_dot = true;
++s;
continue;
}
int digit = -1;
if (*s >= '0' && *s <= '9') digit = *s - '0';
else if (*s >= 'a' && *s <= 'f') digit = *s - 'a' + 10;
else if (*s >= 'A' && *s <= 'F') digit = *s - 'A' + 10;
if (digit >= 0) {
if (have_dot) {
significand += digit * dot_scale;
dot_scale /= 16.0;
} else {
significand = significand * 16 + digit;
}
}
++s;
}
int exponent = 0;
if (*s == 'p' || *s == 'P') {
++s;
int sign = 1;
if (*s == '-') { sign = -1; ++s; }
else if (*s == '+') { ++s; }
exponent = 0;
while (*s >= '0' && *s <= '9') {
exponent = exponent * 10 + (*s - '0');
++s;
}
exponent *= sign;
}
return static_cast<float>(ldexp(significand, exponent));
}
// 把 i32/float 值转成 i1
ir::Value* IRGenImpl::ToI1(ir::Value* v) {
if (!v) throw std::runtime_error(FormatError("irgen", "ToI1: null value"));
@ -571,11 +619,15 @@ std::any IRGenImpl::visitNumber(SysYParser::NumberContext* ctx) {
if (ctx->FloatConst()) {
std::string text = ctx->FloatConst()->getText();
float val = 0.0f;
try {
val = std::stof(text);
} catch (...) {
throw std::runtime_error(
FormatError("irgen", "浮点字面量解析失败: " + text));
if (text.size() >= 2 && (text[1] == 'x' || text[1] == 'X')) {
val = ParseHexFloat(text);
} else {
try {
val = std::stof(text);
} catch (...) {
throw std::runtime_error(
FormatError("irgen", "浮点字面量解析失败: " + text));
}
}
return static_cast<ir::Value*>(builder_.CreateConstFloat(val));
}

@ -24,7 +24,7 @@ const FrameSlot& GetFrameSlot(const MachineFunction& function,
}
// 32位整数加载/存储
void EmitStackLoad(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::SP) {
void EmitStackLoad(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
os << " lw " << PhysRegName(dst) << ", " << offset << "(" << PhysRegName(base) << ")\n";
} else {
@ -34,7 +34,7 @@ void EmitStackLoad(std::ostream& os, PhysReg dst, int offset, PhysReg base = Phy
}
}
void EmitStackStore(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::SP) {
void EmitStackStore(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
os << " sw " << PhysRegName(src) << ", " << offset << "(" << PhysRegName(base) << ")\n";
} else {
@ -45,7 +45,7 @@ void EmitStackStore(std::ostream& os, PhysReg src, int offset, PhysReg base = Ph
}
// 64位指针加载/存储
void EmitStackLoad64(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::SP) {
void EmitStackLoad64(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
os << " ld " << PhysRegName(dst) << ", " << offset << "(" << PhysRegName(base) << ")\n";
} else {
@ -55,7 +55,7 @@ void EmitStackLoad64(std::ostream& os, PhysReg dst, int offset, PhysReg base = P
}
}
void EmitStackStore64(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::SP) {
void EmitStackStore64(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
os << " sd " << PhysRegName(src) << ", " << offset << "(" << PhysRegName(base) << ")\n";
} else {
@ -66,7 +66,7 @@ void EmitStackStore64(std::ostream& os, PhysReg src, int offset, PhysReg base =
}
// 浮点加载/存储保持32位
void EmitStackLoadFloat(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::SP) {
void EmitStackLoadFloat(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
os << " flw " << PhysRegName(dst) << ", " << offset << "(" << PhysRegName(base) << ")\n";
} else {
@ -76,7 +76,7 @@ void EmitStackLoadFloat(std::ostream& os, PhysReg dst, int offset, PhysReg base
}
}
void EmitStackStoreFloat(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::SP) {
void EmitStackStoreFloat(std::ostream& os, PhysReg src, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
os << " fsw " << PhysRegName(src) << ", " << offset << "(" << PhysRegName(base) << ")\n";
} else {
@ -95,7 +95,8 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
}
int frame_size = function.GetFrameSize(); // 局部变量区大小(正数)
int total_frame_size = frame_size + 16; // +16 用于保存 ra(8) 和 s0(8)
int local_vars = function.GetLocalVarsSize();
int total_frame = local_vars + 16 ;
bool prologue_done = false;
for (const auto& block_ptr : function.GetBlocks()) {
@ -111,19 +112,19 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
// 在入口块的第一条指令前输出序言
if (!prologue_done && block.GetName() == "entry") {
// 分配栈帧sp -= total_frame_size
if (total_frame_size <= 2047) {
os << " addi sp, sp, -" << total_frame_size << "\n";
// 分配栈帧sp -= total_frame
if (total_frame <= 2047) {
os << " addi sp, sp, -" << total_frame << "\n";
} else {
os << " li t4, -" << total_frame_size << "\n";
os << " li t4, -" << total_frame << "\n";
os << " add sp, sp, t4\n";
}
// 保存 ra 和 s0在局部变量区之后即 sp + frame_size 处)
// ra 保存在 sp + frame_size
// s0 保存在 sp + frame_size + 8
int ra_offset = frame_size;
int s0_offset = frame_size + 8;
int ra_offset = local_vars;
int s0_offset = local_vars + 8;
if (ra_offset <= 2047) {
os << " sd ra, " << ra_offset << "(sp)\n";
@ -140,7 +141,7 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
os << " add t4, sp, t4\n";
os << " sd s0, 0(t4)\n";
}
os << " mv s0, sp\n";
prologue_done = true;
}
@ -155,47 +156,94 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
break;
case Opcode::Load: {
if (ops.size() == 2 && ops.at(1).GetKind() == Operand::Kind::Reg) {
// 寄存器间接寻址 - 使用 ld64位
os << " ld " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
} else {
int frame_idx = ops.at(1).GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
// 根据槽大小决定加载宽度
if (slot.size == 8) {
EmitStackLoad64(os, ops.at(0).GetReg(), slot.offset);
} else {
EmitStackLoad(os, ops.at(0).GetReg(), slot.offset);
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " ld " << PhysRegName(ops[0].GetReg()) << ", 0(" << PhysRegName(ops[1].GetReg()) << ")\n";
} /*else if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Imm) {
// 用于调用者 outgoing 存储的占位偏移(将在 Outgoing 中修正)
int offset = ops[1].GetImm(); // 实际偏移 = local_vars + 16 + offset
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << offset << "(sp)\n";*/
else {
int frame_idx = ops[1].GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
if (slot.size == 8) EmitStackLoad64(os, ops[0].GetReg(), slot.offset);
else EmitStackLoad(os, ops[0].GetReg(), slot.offset);
}
}
break;
break;
}
case Opcode::Store: {
if (ops.size() == 2 && ops.at(1).GetKind() == Operand::Kind::Reg) {
// 寄存器间接寻址 - 使用 sd64位
os << " sd " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
} else {
int frame_idx = ops.at(1).GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
// 根据槽大小决定存储宽度
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " sd " << PhysRegName(ops[0].GetReg()) << ", 0(" << PhysRegName(ops[1].GetReg()) << ")\n";
} /*else if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Imm) {
int offset = ops[1].GetImm();
// 实际偏移需在 AsmPrinter 中加上 local_vars+16这里简单先直接用 offset动态修正稍复杂
// 临时方案:直接生成 sw t0, offset(sp),但 offset 应为 local_vars+16=?
// 由于 AsmPrinter 中可访问 function.GetLocalVarsSize(),我们计算:
int actual_offset = function.GetLocalVarsSize() + 16 + offset;
if (actual_offset <= 2047) os << " sd " << PhysRegName(ops[0].GetReg()) << ", " << actual_offset << "(sp)\n";
else { }*/
else {
int frame_idx = ops[1].GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
if (slot.size == 8) EmitStackStore64(os, ops[0].GetReg(), slot.offset);
else EmitStackStore(os, ops[0].GetReg(), slot.offset);
}
break;
}
case Opcode::LoadCallerStackArg: {
// ops: [0] dst (T0), [1] dstFrameIndex, [2] argvIndex (Imm)
int argv_index = ops[2].GetImm();
int dst_slot = ops[1].GetFrameIndex();
int total_frame = function.GetFrameSize();
// 调用者栈参数位于 sp + total_frame + argv_index*8
int caller_offset = total_frame + argv_index * 8;
// 加载到 T0
if (caller_offset <= 2047) {
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << caller_offset << "(s0)\n";
} else {
os << " li t4, " << caller_offset << "\n";
os << " add t4, s0, t4\n";
os << " ld " << PhysRegName(ops[0].GetReg()) << ", 0(t4)\n";
}
// 再存入本地槽
const auto& slot = function.GetFrameSlot(dst_slot);
if (slot.size == 8) {
EmitStackStore64(os, ops.at(0).GetReg(), slot.offset);
EmitStackStore64(os, ops[0].GetReg(), slot.offset);
} else {
EmitStackStore(os, ops.at(0).GetReg(), slot.offset);
EmitStackStore(os, ops[0].GetReg(), slot.offset);
}
break;
}
case Opcode::LoadCallerStackArgFloat: {
int argv_index = ops.at(2).GetImm();
int dst_slot = ops.at(1).GetFrameIndex();
int total_frame = function.GetFrameSize();
int caller_offset = total_frame + argv_index * 8;
// 使用 s0 保证稳定
if (caller_offset <= 2047) {
os << " flw " << PhysRegName(ops.at(0).GetReg()) << ", " << caller_offset << "(s0)\n";
} else {
os << " li t4, " << caller_offset << "\n";
os << " add t4, s0, t4\n";
os << " flw " << PhysRegName(ops.at(0).GetReg()) << ", 0(t4)\n";
}
const auto& slot = function.GetFrameSlot(dst_slot);
EmitStackStoreFloat(os, ops.at(0).GetReg(), slot.offset);
break;
}
}
case Opcode::Add:
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::Addi:
os << " addi " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< ops[2].GetImm() << "\n";
break;
case Opcode::Sub:
os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
@ -284,7 +332,10 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
os << " lw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
break;
case Opcode::LoadIndirectFloat:
os << " flw " << PhysRegName(ops[0].GetReg()) << ", 0("
<< PhysRegName(ops[1].GetReg()) << ")\n";
break;
case Opcode::Call: {
std::string func_name = "memset"; // 默认值
if (!ops.empty() && ops[0].GetKind() == Operand::Kind::Func) {
@ -299,10 +350,10 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
const auto& slot = function.GetFrameSlot(frame_idx);
// 计算地址64 位offset 是正数
if (slot.offset <= 2047) {
os << " addi " << PhysRegName(ops.at(0).GetReg()) << ", sp, " << slot.offset << "\n";
os << " addi " << PhysRegName(ops.at(0).GetReg()) << ", s0, " << slot.offset << "\n";
} else {
os << " li " << PhysRegName(ops.at(0).GetReg()) << ", " << slot.offset << "\n";
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", sp, "
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", s0, "
<< PhysRegName(ops.at(0).GetReg()) << "\n";
}
break;
@ -319,35 +370,39 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
break;
case Opcode::StoreIndirectFloat:
os << " fsw " << PhysRegName(ops[0].GetReg()) << ", 0("
<< PhysRegName(ops[1].GetReg()) << ")\n";
break;
case Opcode::Ret:{
// 恢复 ra 和 s0
int ra_offset = frame_size;
int s0_offset = frame_size + 8;
int ra_offset = local_vars;
int s0_offset = local_vars + 8;
if (ra_offset <= 2047) {
os << " ld ra, " << ra_offset << "(sp)\n";
os << " ld ra, " << ra_offset << "(s0)\n";
} else {
os << " li t3, " << ra_offset << "\n";
os << " add t3, sp, t3\n";
os << " add t3, s0, t3\n";
os << " ld ra, 0(t3)\n";
}
// 恢复 sp
if (total_frame <= 2047) {
os << " addi sp, s0, " << total_frame << "\n";
} else {
os << " li t3, " << total_frame << "\n";
os << " add sp, s0, t3\n";
}
if (s0_offset <= 2047) {
os << " ld s0, " << s0_offset << "(sp)\n";
os << " ld s0, " << s0_offset << "(s0)\n";
} else {
os << " li t3, " << s0_offset << "\n";
os << " add t3, sp, t3\n";
os << " add t3, s0, t3\n";
os << " ld s0, 0(t3)\n";
}
// 恢复 sp
if (total_frame_size <= 2047) {
os << " addi sp, sp, " << total_frame_size << "\n";
} else {
os << " li t3, " << total_frame_size << "\n";
os << " add sp, sp, t3\n";
}
os << " ret\n";
break;
@ -360,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;
}
// 浮点运算
@ -438,7 +498,7 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
case Opcode::FPToSI:
os << " fcvt.w.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
<< PhysRegName(ops[1].GetReg()) << ", rtz\n";
break;
case Opcode::LoadFloat:
@ -477,73 +537,97 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
// 输出多个函数的汇编
void PrintAsm(const std::vector<std::unique_ptr<MachineFunction>>& functions, std::ostream& os) {
// ========== 输出全局变量 ==========
// 输出 .data 段(已初始化的全局变量)
// .data 段:非常量变量
bool hasData = false;
for (const auto& gv : g_globalVars) {
if (!gv.isConst) {
if (!hasData) {
os << ".data\n";
hasData = true;
}
os << " .global " << gv.name << "\n";
os << " .type " << gv.name << ", @object\n";
if (gv.isArray && gv.arraySize > 1) {
int totalSize = gv.arraySize * 4;
os << " .size " << gv.name << ", " << totalSize << "\n";
os << gv.name << ":\n";
if (!gv.arrayValues.empty()) {
for (int val : gv.arrayValues) {
os << " .word " << val << "\n";
if (gv.isConst) continue; // 常量到 .rodata
if (!hasData) {
os << ".data\n";
hasData = true;
}
os << " .global " << gv.name << "\n";
os << " .type " << gv.name << ", @object\n";
if (gv.isArray && gv.arraySize > 1) {
int totalSize = gv.arraySize * 4;
os << " .size " << gv.name << ", " << totalSize << "\n";
os << gv.name << ":\n";
if (gv.isFloat) {
if (!gv.arrayValuesF.empty()) {
for (float val : gv.arrayValuesF) {
union { float f; uint32_t i; } u;
u.f = val;
os << " .word " << u.i << "\n";
}
} else {
for (int i = 0; i < gv.arraySize; i++) {
os << " .word 0\n";
}
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
}
} else {
if (!gv.arrayValues.empty()) {
for (int val : gv.arrayValues) os << " .word " << val << "\n";
} else {
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
}
}
} else {
os << " .size " << gv.name << ", 4\n";
os << gv.name << ":\n";
if (gv.isFloat) {
union { float f; uint32_t i; } u;
u.f = gv.valueF;
os << " .word " << u.i << "\n";
} else {
os << " .size " << gv.name << ", 4\n";
os << gv.name << ":\n";
os << " .word " << gv.value << "\n";
}
}
}
// 输出 .rodata 段(只读常量)
// .rodata 段:只读常量
bool hasRodata = false;
for (const auto& gv : g_globalVars) {
if (gv.isConst) {
if (!hasRodata) {
os << ".section .rodata\n";
hasRodata = true;
}
os << " .global " << gv.name << "\n";
os << " .type " << gv.name << ", @object\n";
if (gv.isArray && gv.arraySize > 1) {
int totalSize = gv.arraySize * 4;
os << " .size " << gv.name << ", " << totalSize << "\n";
os << gv.name << ":\n";
if (!gv.arrayValues.empty()) {
for (int val : gv.arrayValues) {
os << " .word " << val << "\n";
if (!gv.isConst) continue;
if (!hasRodata) {
os << ".section .rodata\n";
hasRodata = true;
}
os << " .global " << gv.name << "\n";
os << " .type " << gv.name << ", @object\n";
if (gv.isArray && gv.arraySize > 1) {
int totalSize = gv.arraySize * 4;
os << " .size " << gv.name << ", " << totalSize << "\n";
os << gv.name << ":\n";
if (gv.isFloat) {
if (!gv.arrayValuesF.empty()) {
for (float val : gv.arrayValuesF) {
union { float f; uint32_t i; } u;
u.f = val;
os << " .word " << u.i << "\n";
}
} else {
for (int i = 0; i < gv.arraySize; i++) {
os << " .word 0\n";
}
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
}
} else {
if (!gv.arrayValues.empty()) {
for (int val : gv.arrayValues) os << " .word " << val << "\n";
} else {
for (int i = 0; i < gv.arraySize; i++) os << " .word 0\n";
}
}
} else {
os << " .size " << gv.name << ", 4\n";
os << gv.name << ":\n";
if (gv.isFloat) {
union { float f; uint32_t i; } u;
u.f = gv.valueF;
os << " .word " << u.i << "\n";
} else {
os << " .size " << gv.name << ", 4\n";
os << gv.name << ":\n";
os << " .word " << gv.value << "\n";
}
}
}
// ========== 输出代码段 ==========
os << ".text\n";

@ -18,19 +18,22 @@ void RunFrameLowering(MachineFunction& function) {
int cursor = 0;
const auto& slots = function.GetFrameSlots();
// 为每个栈槽分配偏移:正偏移,表示相对于 sp 的偏移量
// 栈向下增长sp 减小后,局部变量在 sp 上方(正偏移)
// 为每个栈槽分配偏移
for (const auto& slot : slots) {
int align = slot.size; // 自然对齐4 或 8 字节)
cursor = AlignTo(cursor, align); // 对齐到所需边界
function.GetFrameSlot(slot.index).offset = cursor; // 正偏移
cursor += slot.size; // 分配空间
int align = slot.size;
cursor = AlignTo(cursor, align);
function.GetFrameSlot(slot.index).offset = cursor;
cursor += slot.size;
}
// 栈帧总大小(局部变量区域)按 16 字节对齐
function.SetFrameSize(AlignTo(cursor, 16));
// 局部变量区按 16 字节对齐
int local_vars_size = AlignTo(cursor, 16);
function.SetLocalVarsSize(local_vars_size);
// 在入口块插入 Prologue/Epilogue 占位符
// 总帧大小 = 局部变量区 + 16保存 ra 和 s0
function.SetFrameSize(local_vars_size + 16);
// 插入 Prologue/Epilogue 占位符(原逻辑)
auto& insts = function.GetEntry()->GetInstructions();
std::vector<MachineInstr> lowered;
lowered.emplace_back(Opcode::Prologue);

@ -27,6 +27,7 @@ static bool IsFloatReg(PhysReg reg) {
using ValueSlotMap = std::unordered_map<const ir::Value*, int>;
static std::unordered_map<const ir::BasicBlock*, MachineBasicBlock*> block_map;
MachineBasicBlock* GetOrCreateBlock(const ir::BasicBlock* ir_block,
MachineFunction& function) {
auto it = block_map.find(ir_block);
@ -45,14 +46,20 @@ MachineBasicBlock* GetOrCreateBlock(const ir::BasicBlock* ir_block,
void EmitValueToReg(const ir::Value* value, PhysReg target,
const ValueSlotMap& slots, MachineBasicBlock& block,
bool for_address = false) {
MachineFunction& function, bool for_address = false){
// 处理参数Argument
if (auto* arg = dynamic_cast<const ir::Argument*>(value)) {
auto it = slots.find(arg);
if (it != slots.end()) {
bool src_is_float = value->GetType()->IsFloat32();
bool dst_is_float = IsFloatReg(target);
if (src_is_float && !dst_is_float) {
if (src_is_float == dst_is_float) {
// 同类型 → 直接加载,不转换
if (src_is_float)
block.Append(Opcode::LoadFloat, {Operand::Reg(target), Operand::FrameIndex(it->second)});
else
block.Append(Opcode::Load, {Operand::Reg(target), Operand::FrameIndex(it->second)});
} else if (src_is_float && !dst_is_float) {
// 浮点 -> 整数
block.Append(Opcode::LoadFloat,
{Operand::Reg(PhysReg::FT0), Operand::FrameIndex(it->second)});
@ -62,16 +69,7 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
block.Append(Opcode::Load,
{Operand::Reg(PhysReg::T0), Operand::FrameIndex(it->second)});
block.Append(Opcode::SIToFP, {Operand::Reg(target), Operand::Reg(PhysReg::T0)});
} else {
// 同类型直接加载
if (src_is_float) {
block.Append(Opcode::LoadFloat,
{Operand::Reg(target), Operand::FrameIndex(it->second)});
} else {
block.Append(Opcode::Load,
{Operand::Reg(target), Operand::FrameIndex(it->second)});
}
}
}
return;
}
}
@ -84,27 +82,32 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
return;
}
// 处理浮点常量
// 处理浮点常量
if (auto* fconstant = dynamic_cast<const ir::ConstantFloat*>(value)) {
float val = fconstant->GetValue();
// 直接使用标准的 double -> float 转换,无需特殊分支
float fval = static_cast<float>(fconstant->GetValue());
uint32_t bits;
memcpy(&bits, &val, sizeof(val));
bool target_is_fp = IsFloatReg(target);
if (target_is_fp) {
block.Append(Opcode::MovImm,
{Operand::Reg(PhysReg::T0), Operand::Imm(static_cast<int>(bits))});
block.Append(Opcode::FMovWX, {Operand::Reg(target), Operand::Reg(PhysReg::T0)});
std::memcpy(&bits, &fval, sizeof(fval));
int32_t imm = static_cast<int32_t>(bits);
if (IsFloatReg(target)) {
// 通过栈槽加载以保证浮点寄存器符合 NaNboxing 要求
int tmp_slot = function.CreateFrameIndex(4);
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(imm)});
block.Append(Opcode::Store, {Operand::Reg(PhysReg::T4),
Operand::FrameIndex(tmp_slot)});
block.Append(Opcode::LoadFloat, {Operand::Reg(target),
Operand::FrameIndex(tmp_slot)});
} else {
block.Append(Opcode::MovImm,
{Operand::Reg(target), Operand::Imm(static_cast<int>(bits))});
block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(imm)});
}
return;
}
// 处理 GEP 指令
if (auto* gep = dynamic_cast<const ir::GepInst*>(value)) {
EmitValueToReg(gep->GetBasePtr(), target, slots, block, true);
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block);
EmitValueToReg(gep->GetBasePtr(), target, slots, block,function, true);
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block,function);
block.Append(Opcode::Slli, {Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T1),
Operand::Imm(2)});
@ -140,7 +143,7 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
return;
}
// 处理一般栈槽中的值
// 处理一般栈槽中的值
auto it = slots.find(value);
if (it != slots.end()) {
bool src_is_float = value->GetType()->IsFloat32();
@ -202,25 +205,54 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
case ir::Opcode::Store: {
auto& store = static_cast<const ir::StoreInst&>(inst);
if (dynamic_cast<const ir::GepInst*>(store.GetPtr())) {
EmitValueToReg(store.GetValue(), PhysReg::T2, slots, block);
EmitValueToReg(store.GetPtr(), PhysReg::T0, slots, block, true);
block.Append(Opcode::StoreIndirect,
{Operand::Reg(PhysReg::T2), Operand::Reg(PhysReg::T0)});
// 如果指针是 GEP手动生成地址并 store避免额外计算
if (auto* gep = dynamic_cast<const ir::GepInst*>(store.GetPtr())) {
// 判断值的类型是否为浮点
bool val_is_float = store.GetValue()->GetType()->IsFloat32();
if (val_is_float) {
// 将浮点值加载到 FT0
EmitValueToReg(store.GetValue(), PhysReg::FT0, slots, block, function);
} else {
// 整数值加载到 T2
EmitValueToReg(store.GetValue(), PhysReg::T2, slots, block, function);
}
// 计算基址 + 索引*4
EmitValueToReg(gep->GetBasePtr(), PhysReg::T0, slots, block, function, true);
auto idx_it = slots.find(gep->GetIndex());
if (idx_it != slots.end()) {
block.Append(Opcode::Load, {Operand::Reg(PhysReg::T1), Operand::FrameIndex(idx_it->second)});
} else {
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block, function);
}
block.Append(Opcode::Slli, {Operand::Reg(PhysReg::T1), Operand::Reg(PhysReg::T1), Operand::Imm(2)});
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T1)});
// 使用正确的间接存储操作码
if (val_is_float) {
block.Append(Opcode::StoreIndirectFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T0)});
} else {
block.Append(Opcode::StoreIndirect, {Operand::Reg(PhysReg::T2), Operand::Reg(PhysReg::T0)});
}
return;
}
if (auto* global = dynamic_cast<const ir::GlobalVariable*>(store.GetPtr())) {
EmitValueToReg(store.GetValue(), PhysReg::T0, slots, block);
EmitValueToReg(store.GetValue(), PhysReg::T0, slots, block, function);
std::string global_name = global->GetName();
block.Append(Opcode::StoreGlobal,
{Operand::Reg(PhysReg::T0), Operand::Global(global_name)});
block.Append(Opcode::StoreGlobal, {Operand::Reg(PhysReg::T0), Operand::Global(global_name)});
return;
}
auto dst = slots.find(store.GetPtr());
if (dst != slots.end()) {
EmitValueToReg(store.GetValue(), PhysReg::T0, slots, block);
StoreRegToSlot(PhysReg::T0, dst->second, block);
bool val_is_float = store.GetValue()->GetType()->IsFloat32();
if (val_is_float) {
EmitValueToReg(store.GetValue(), PhysReg::FT0, slots, block, function);
StoreRegToSlot(PhysReg::FT0, dst->second, block, true);
} else {
EmitValueToReg(store.GetValue(), PhysReg::T0, slots, block, function);
StoreRegToSlot(PhysReg::T0, dst->second, block, false);
}
return;
}
throw std::runtime_error(FormatError("mir", "Store: 无法处理的指针类型"));
@ -228,9 +260,36 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
case ir::Opcode::Load: {
auto& load = static_cast<const ir::LoadInst&>(inst);
if (auto* gep = dynamic_cast<const ir::GepInst*>(load.GetPtr())) {
// 计算地址到 T0
EmitValueToReg(gep->GetBasePtr(), PhysReg::T0, slots, block, function, true);
auto idx_it = slots.find(gep->GetIndex());
if (idx_it != slots.end()) {
block.Append(Opcode::Load, {Operand::Reg(PhysReg::T1), Operand::FrameIndex(idx_it->second)});
} else {
EmitValueToReg(gep->GetIndex(), PhysReg::T1, slots, block, function);
}
block.Append(Opcode::Slli, {Operand::Reg(PhysReg::T1), Operand::Reg(PhysReg::T1), Operand::Imm(2)});
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T1)});
bool load_is_float = load.GetType()->IsFloat32();
int dst_slot = function.CreateFrameIndex(4);
if (load_is_float) {
// 浮点加载FT0 = [T0]
block.Append(Opcode::LoadIndirectFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T0)});
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
} else {
// 整数加载
block.Append(Opcode::LoadIndirect, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0)});
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
}
slots.emplace(&inst, dst_slot);
return;
}
if (dynamic_cast<const ir::GepInst*>(load.GetPtr())) {
EmitValueToReg(load.GetPtr(), PhysReg::T0, slots, block, true);
EmitValueToReg(load.GetPtr(), PhysReg::T0, slots, block, function, true);
block.Append(Opcode::LoadIndirect,
{Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T0)});
int dst_slot = function.CreateFrameIndex(4);
@ -294,8 +353,8 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
int dst_slot = function.CreateFrameIndex(4);
if (result_is_float) {
EmitValueToReg(bin.GetLhs(), PhysReg::FT0, slots, block);
EmitValueToReg(bin.GetRhs(), PhysReg::FT1, slots, block);
EmitValueToReg(bin.GetLhs(), PhysReg::FT0, slots, block, function);
EmitValueToReg(bin.GetRhs(), PhysReg::FT1, slots, block, function);
Opcode op;
switch (inst.GetOpcode()) {
@ -310,8 +369,8 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
Operand::Reg(PhysReg::FT1)});
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
} else {
EmitValueToReg(bin.GetLhs(), PhysReg::T0, slots, block);
EmitValueToReg(bin.GetRhs(), PhysReg::T1, slots, block);
EmitValueToReg(bin.GetLhs(), PhysReg::T0, slots, block, function);
EmitValueToReg(bin.GetRhs(), PhysReg::T1, slots, block, function);
Opcode op;
switch (inst.GetOpcode()) {
@ -338,39 +397,124 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
}
case ir::Opcode::Call: {
auto& call = static_cast<const ir::CallInst&>(inst);
for (size_t i = 0; i < call.GetNumArgs() && i < 8; i++) {
// 根据参数的实际类型决定使用浮点还是整数寄存器
bool arg_is_float = call.GetArg(i)->GetType()->IsFloat32();
if (arg_is_float) {
PhysReg floatArgReg = static_cast<PhysReg>(static_cast<int>(PhysReg::FA0) + i);
EmitValueToReg(call.GetArg(i), floatArgReg, slots, block);
} else {
PhysReg intArgReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + i);
EmitValueToReg(call.GetArg(i), intArgReg, slots, block);
auto& call = static_cast<const ir::CallInst&>(inst);
int numArgs = static_cast<int>(call.GetNumArgs());
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)});
}
}
}
}
std::string func_name = call.GetCalleeName();
block.Append(Opcode::Call, {Operand::Func(func_name)});
if (!call.GetType()->IsVoid()) {
int dst_slot = function.CreateFrameIndex();
bool ret_is_float = call.GetType()->IsFloat32();
if (ret_is_float) {
StoreRegToSlot(PhysReg::FA0, dst_slot, block, true);
} else {
StoreRegToSlot(PhysReg::A0, dst_slot, block, false);
int stackArgs = static_cast<int>(stack_args.size());
if (stackArgs > 0) {
int stackSpace = (stackArgs * 8 + 15) & ~15;
// sp -= stackSpace
if (stackSpace <= 2047) {
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
Operand::Imm(-stackSpace)});
} 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)});
}
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)});
}
}
}
slots.emplace(&inst, dst_slot);
}
return;
// 调用目标
std::string func_name = call.GetCalleeName();
block.Append(Opcode::Call, {Operand::Func(func_name)});
// 恢复 sp
if (stackArgs > 0) {
int stackSpace = (stackArgs * 8 + 15) & ~15;
if (stackSpace <= 2047) {
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
Operand::Imm(stackSpace)});
} 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)});
}
}
// 返回值处理(原有代码保持不变)
if (!call.GetType()->IsVoid()) {
int dst_slot = function.CreateFrameIndex();
bool ret_is_float = call.GetType()->IsFloat32();
if (ret_is_float) {
StoreRegToSlot(PhysReg::FA0, dst_slot, block, true);
} else {
StoreRegToSlot(PhysReg::A0, dst_slot, block, false);
}
slots.emplace(&inst, dst_slot);
}
return;
}
case ir::Opcode::ICmp: {
auto& icmp = static_cast<const ir::ICmpInst&>(inst);
int dst_slot = function.CreateFrameIndex();
EmitValueToReg(icmp.GetLhs(), PhysReg::T0, slots, block);
EmitValueToReg(icmp.GetRhs(), PhysReg::T1, slots, block);
EmitValueToReg(icmp.GetLhs(), PhysReg::T0, slots, block, function);
EmitValueToReg(icmp.GetRhs(), PhysReg::T1, slots, block, function);
ir::ICmpPredicate pred = icmp.GetPredicate();
@ -401,26 +545,29 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T1)});
break;
case ir::ICmpPredicate::SLE:
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T0)});
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T1),
Operand::Imm(1)});
break;
case ir::ICmpPredicate::SGT:
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T0)});
break;
case ir::ICmpPredicate::SGE:
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T0)});
// lhs >= rhs 等价于 !(lhs < rhs)
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T1)});
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T1),
Operand::Imm(1)});
Operand::Reg(PhysReg::T0),
Operand::Imm(1)});
break;
case ir::ICmpPredicate::SLE:
// lhs <= rhs 等价于 !(rhs < lhs)
block.Append(Opcode::Slt, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T1),
Operand::Reg(PhysReg::T0)}); // 注意操作数顺序rhs < lhs
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T0),
Operand::Imm(1)});
break;
}
@ -432,7 +579,7 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
auto& zext = static_cast<const ir::ZExtInst&>(inst);
int dst_slot = function.CreateFrameIndex(4);
EmitValueToReg(zext.GetSrc(), PhysReg::T0, slots, block);
EmitValueToReg(zext.GetSrc(), PhysReg::T0, slots, block, function);
StoreRegToSlot(PhysReg::T0, dst_slot, block);
slots.emplace(&inst, dst_slot);
return;
@ -442,36 +589,51 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
auto& fcmp = static_cast<const ir::FCmpInst&>(inst);
int dst_slot = function.CreateFrameIndex(4);
EmitValueToReg(fcmp.GetLhs(), PhysReg::FT0, slots, block);
EmitValueToReg(fcmp.GetRhs(), PhysReg::FT1, slots, block);
EmitValueToReg(fcmp.GetLhs(), PhysReg::FT0, slots, block, function);
EmitValueToReg(fcmp.GetRhs(), PhysReg::FT1, slots, block, function);
ir::FCmpPredicate pred = fcmp.GetPredicate();
switch (pred) {
case ir::FCmpPredicate::OEQ:
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::FT0),
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0),
Operand::Reg(PhysReg::FT1)});
break;
case ir::FCmpPredicate::ONE:
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0),
Operand::Reg(PhysReg::FT1)});
block.Append(Opcode::Xori, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::T0),
Operand::Imm(1)});
break;
case ir::FCmpPredicate::OLT:
block.Append(Opcode::FLt, {Operand::Reg(PhysReg::FT0),
block.Append(Opcode::FLt, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0),
Operand::Reg(PhysReg::FT1)});
break;
case ir::FCmpPredicate::OGT:
block.Append(Opcode::FLt, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT1),
Operand::Reg(PhysReg::FT0)});
break;
case ir::FCmpPredicate::OLE:
block.Append(Opcode::FLe, {Operand::Reg(PhysReg::FT0),
block.Append(Opcode::FLe, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0),
Operand::Reg(PhysReg::FT1)});
break;
case ir::FCmpPredicate::OGE:
block.Append(Opcode::FLe, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT1),
Operand::Reg(PhysReg::FT0)});
break;
default:
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::FT0),
block.Append(Opcode::FEq, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0),
Operand::Reg(PhysReg::FT1)});
break;
}
block.Append(Opcode::FMov, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0)});
StoreRegToSlot(PhysReg::T0, dst_slot, block);
slots.emplace(&inst, dst_slot);
return;
@ -481,13 +643,8 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
auto& conv = static_cast<const ir::SIToFPInst&>(inst);
int dst_slot = function.CreateFrameIndex(4);
auto src_it = slots.find(conv.GetSrc());
if (src_it == slots.end()) {
throw std::runtime_error(FormatError("mir", "SIToFP: 找不到源操作数的栈槽"));
}
block.Append(Opcode::Load,
{Operand::Reg(PhysReg::T0), Operand::FrameIndex(src_it->second)});
// 直接加载源操作数到 T0不依赖 slots 中是否存在
EmitValueToReg(conv.GetSrc(), PhysReg::T0, slots, block, function);
block.Append(Opcode::SIToFP, {Operand::Reg(PhysReg::FT0),
Operand::Reg(PhysReg::T0)});
StoreRegToSlot(PhysReg::FT0, dst_slot, block, true);
@ -499,13 +656,8 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
auto& conv = static_cast<const ir::FPToSIInst&>(inst);
int dst_slot = function.CreateFrameIndex(4);
auto src_it = slots.find(conv.GetSrc());
if (src_it == slots.end()) {
throw std::runtime_error(FormatError("mir", "FPToSI: 找不到源操作数的栈槽"));
}
block.Append(Opcode::LoadFloat,
{Operand::Reg(PhysReg::FT0), Operand::FrameIndex(src_it->second)});
// 直接加载源操作数到 FT0不依赖 slots
EmitValueToReg(conv.GetSrc(), PhysReg::FT0, slots, block, function);
block.Append(Opcode::FPToSI, {Operand::Reg(PhysReg::T0),
Operand::Reg(PhysReg::FT0)});
StoreRegToSlot(PhysReg::T0, dst_slot, block, false);
@ -526,7 +678,7 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
auto* true_bb = condbr.GetTrueBB();
auto* false_bb = condbr.GetFalseBB();
EmitValueToReg(condbr.GetCond(), PhysReg::T0, slots, block);
EmitValueToReg(condbr.GetCond(), PhysReg::T0, slots, block, function);
MachineBasicBlock* true_block = GetOrCreateBlock(true_bb, function);
MachineBasicBlock* false_block = GetOrCreateBlock(false_bb, function);
@ -541,9 +693,9 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
if (ret.GetValue()) {
auto val = ret.GetValue();
if (val->GetType()->IsFloat32()) {
EmitValueToReg(val, PhysReg::FA0, slots, block);
EmitValueToReg(val, PhysReg::FA0, slots, block, function);
} else {
EmitValueToReg(val, PhysReg::A0, slots, block);
EmitValueToReg(val, PhysReg::A0, slots, block, function);
}
} else {
block.Append(Opcode::MovImm,
@ -565,32 +717,41 @@ 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 = 4;
if (arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32()) {
size = 8; // 指针在 RV64 上是 8 字节
}
int slot = machine_func->CreateFrameIndex(size);
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + i);
MachineBasicBlock* entry = machine_func->GetEntry();
// 存储参数到栈槽
if (arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32()) {
// 指针类型:使用 64 位存储注意Store 在 MIR 层会根据 slot.size 决定用 sw 还是 sd
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
} else if (arg->GetType()->IsInt32()) {
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
} else if (arg->GetType()->IsFloat32()) {
entry->Append(Opcode::StoreFloat, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
}
slots[arg] = slot;
ir::Argument* arg = func.GetArgument(i);
int size = (arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32()) ? 8 : 4;
int slot = machine_func->CreateFrameIndex(size);
MachineBasicBlock* entry = machine_func->GetEntry();
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 {
entry->Append(Opcode::LoadCallerStackArgFloat, {
Operand::Reg(PhysReg::FT0),
Operand::FrameIndex(slot),
Operand::Imm(stack_idx)
});
stack_idx++;
}
} else {
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(stack_idx)
});
stack_idx++;
}
}
slots[arg] = slot;
}
// 第一遍:创建所有 IR 基本块对应的 MIR 基本块

@ -5,6 +5,58 @@
#include <string>
#include "utils/Log.h"
#include <cmath> // 提供 ldexp
namespace {
// 解析十六进制浮点字面量,支持 0xH.Hp±E 格式
double ParseHexFloat(const std::string& str) {
const char* s = str.c_str();
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2;
double significand = 0.0;
bool have_dot = false;
double dot_scale = 1.0 / 16.0;
while (*s && *s != 'p' && *s != 'P') {
if (*s == '.') {
have_dot = true;
++s;
continue;
}
int digit = -1;
if (*s >= '0' && *s <= '9') digit = *s - '0';
else if (*s >= 'a' && *s <= 'f') digit = *s - 'a' + 10;
else if (*s >= 'A' && *s <= 'F') digit = *s - 'A' + 10;
if (digit >= 0) {
if (have_dot) {
significand += digit * dot_scale;
dot_scale /= 16.0;
} else {
significand = significand * 16 + digit;
}
}
++s;
}
int exponent = 0;
if (*s == 'p' || *s == 'P') {
++s;
int sign = 1;
if (*s == '-') { sign = -1; ++s; }
else if (*s == '+') { ++s; }
exponent = 0;
while (*s >= '0' && *s <= '9') {
exponent = exponent * 10 + (*s - '0');
++s;
}
exponent *= sign;
}
return ldexp(significand, exponent);
}
} // anonymous namespace
namespace sem {
@ -156,7 +208,12 @@ ConstValue EvaluatePrimaryExp(SysYParser::PrimaryExpContext& ctx) {
val.float_val = static_cast<double>(val.int_val);
} else if (float_const) {
val.is_int = false;
val.float_val = ToFloat32(std::stod(float_const->getText()));
std::string text = float_const->getText();
if (text.size() >= 2 && (text[1] == 'x' || text[1] == 'X')) {
val.float_val = ToFloat32(ParseHexFloat(text));
} else {
val.float_val = ToFloat32(std::stod(text));
}
val.int_val = static_cast<long long>(val.float_val);
} else {
throw std::runtime_error(FormatError("sema", "非法数字字面量"));

Loading…
Cancel
Save