fix(mir):修复浮点数的问题

develop
cy 3 days ago
parent f4658ec3fa
commit 6b6de49fcf

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
}

@ -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));
}

@ -158,11 +158,11 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
case Opcode::Load: {
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) {
} /*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 {
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);
@ -174,16 +174,15 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
case Opcode::Store: {
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) {
// outgoing 存储:偏移 = local_vars + 16 + ops[1].GetImm()
} /*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 {
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);
@ -201,7 +200,7 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
int caller_offset = total_frame + argv_index * 8;
// 加载到 T0
if (caller_offset <= 2047) {
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << caller_offset << "(sp)\n";
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << caller_offset << "(s0)\n";
} else {
os << " li t4, " << caller_offset << "\n";
os << " add t4, s0, t4\n";
@ -216,6 +215,24 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
}
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()) << ", "
@ -476,7 +493,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:
@ -515,73 +532,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 {
os << " .size " << gv.name << ", 4\n";
os << gv.name << ":\n";
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 << " .word " << gv.value << "\n";
}
}
}
// ========== 输出代码段 ==========
os << ".text\n";

@ -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();
@ -203,25 +206,25 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
case ir::Opcode::Store: {
auto& store = static_cast<const ir::StoreInst&>(inst);
// 如果指针是 GEP手动生成地址并 store避免额外计算
if (auto* gep = dynamic_cast<const ir::GepInst*>(store.GetPtr())) {
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);
EmitValueToReg(store.GetValue(), PhysReg::FT0, slots, block, function);
} else {
// 整数值加载到 T2
EmitValueToReg(store.GetValue(), PhysReg::T2, slots, block);
EmitValueToReg(store.GetValue(), PhysReg::T2, slots, block, function);
}
// 计算基址 + 索引*4
EmitValueToReg(gep->GetBasePtr(), PhysReg::T0, slots, block, true);
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);
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)});
@ -235,15 +238,21 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
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)});
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: 无法处理的指针类型"));
@ -253,13 +262,13 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
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, true);
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);
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)});
@ -280,7 +289,7 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
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);
@ -344,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()) {
@ -360,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()) {
@ -414,23 +423,22 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
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);
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);
EmitValueToReg(call.GetArg(i), ireg, slots, block, function);
}
}
// 栈参数:存入 sp + offset 处
for (int i = regArgs; i < numArgs; i++) {
EmitValueToReg(call.GetArg(i), PhysReg::T0, slots, block);
bool arg_is_float = call.GetArg(i)->GetType()->IsFloat32();
int offset = (i - regArgs) * 8;
// 计算 sp+offset 到 t4
// 计算栈地址到 t4sp + offset
if (offset == 0) {
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::T4), Operand::Imm(0)}); // t4=0
block.Append(Opcode::Add, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
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),
@ -438,11 +446,21 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
} 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::SP),
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)});
}
// Store T0 -> [t4]
block.Append(Opcode::Store, {Operand::Reg(PhysReg::T0), Operand::Reg(PhysReg::T4)});
}
std::string func_name = call.GetCalleeName();
@ -481,8 +499,8 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
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();
@ -547,7 +565,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;
@ -557,36 +575,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;
@ -596,13 +629,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);
@ -614,13 +642,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);
@ -641,7 +664,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);
@ -656,9 +679,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,
@ -703,11 +726,19 @@ std::unique_ptr<MachineFunction> LowerFunctionToMIR(const ir::Function& func) {
} else {
// 栈参数:从调用者的动态栈帧加载到本地栈槽
// 使用 LoadCallerStackArg 特殊指令,参数索引 = i - 8
entry->Append(Opcode::LoadCallerStackArg, {
Operand::Reg(PhysReg::T0), // 临时寄存器
Operand::FrameIndex(slot), // 目标本地栈槽
Operand::Imm(static_cast<int>(i - 8)) // 栈参数索引
});
if (arg->GetType()->IsFloat32()) {
entry->Append(Opcode::LoadCallerStackArgFloat, {
Operand::Reg(PhysReg::FT0), // 临时浮点寄存器
Operand::FrameIndex(slot), // 目标本地栈槽
Operand::Imm(static_cast<int>(i - 8)) // 栈参数索引
});
} else {
entry->Append(Opcode::LoadCallerStackArg, {
Operand::Reg(PhysReg::T0),
Operand::FrameIndex(slot),
Operand::Imm(static_cast<int>(i - 8))
});
}
}
slots[arg] = slot;

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