You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
1.7 KiB

#include "irgen/IRGen.h"
#include <stdexcept>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
ir::Value* IRGenImpl::GenExpr(SysYParser::ExpContext& expr) {
if (!expr.addExp()) {
throw std::runtime_error(FormatError("irgen", "非法表达式"));
}
return GenAddExpr(*expr.addExp());
}
ir::Value* IRGenImpl::GenAddExpr(SysYParser::AddExpContext& add) {
// 当前表达式层次仍是最小实现,直接贴合 addExp -> primary 的语法形状。
const auto& terms = add.primary();
if (terms.empty()) {
throw std::runtime_error(FormatError("irgen", "空加法表达式"));
}
ir::Value* acc = GenPrimary(*terms[0]);
for (size_t i = 1; i < terms.size(); ++i) {
ir::Value* rhs = GenPrimary(*terms[i]);
std::string name = module_.context().NextTemp();
acc = builder_.CreateBinary(ir::Opcode::Add, acc, rhs, name);
}
return acc;
}
ir::Value* IRGenImpl::GenPrimary(SysYParser::PrimaryContext& primary) {
if (primary.Number()) {
return builder_.CreateConstInt(std::stoi(primary.Number()->getText()));
}
if (primary.Ident()) {
auto* decl = sema_.ResolveVarUse(&primary);
if (!decl) {
throw std::runtime_error(
FormatError("irgen",
"变量使用缺少语义绑定: " + primary.Ident()->getText()));
}
auto it = storage_map_.find(decl);
if (it == storage_map_.end()) {
throw std::runtime_error(
FormatError("irgen",
"变量声明缺少存储槽位: " + primary.Ident()->getText()));
}
return builder_.CreateLoad(it->second, module_.context().NextTemp());
}
if (primary.exp()) {
return GenExpr(*primary.exp());
}
throw std::runtime_error(FormatError("irgen", "暂不支持的表达式形式"));
}