Files
Compiler/main.cpp

273 lines
10 KiB
C++
Raw Permalink Normal View History

2025-11-16 21:04:02 +08:00
// main.cpp
#include "ast.h"
#include "mini_c.tab.hpp" // Bison生成的头文件
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector> // 需要包含 vector
#include <fstream> // 需要包含 fstream 用于文件输出
#include <filesystem> // 需要包含 filesystem (C++17) 用于路径操作
#include "interpreter.h" // 可能其他模式需要
#include "ir.h" // IR 定义
#include "semantic.h" // 语义分析器
#include "AssemblyGenerator.h" // *** 包含汇编生成器头文件 ***
#include "ObjectFileGenerator.h"
#include "InstructionEncoder.h" // 你的指令编码器
#include "PrettyPrinter.h"
// 错误处理函数
void error(const char* msg)
{
// 注意Bison/Flex 可能在内部调用这个,确保它符合需要
// 或者在Flex/Bison中使用 YYERROR 宏
std::fprintf(stderr, "Lexer/Parser error: %s\n", msg);
}
extern FILE* yyin; // Flex 使用的输入文件指针
extern ASTNode *ast_root; // Bison 解析后生成的 AST 根节点 (在 .y 文件中定义)
/*──────────────────────────────
* AST prettyprinter
**/
// (tag_name, node_loc, print_ast 函数保持不变)
static const char* tag_name(ASTTag t)
{
#define CASE(x) case ASTTag::x: return #x;
switch (t) {
CASE(ID) CASE(CONST) CASE(STRING)
CASE(UNARY) CASE(BINARY) CASE(LOGIC_AND) CASE(LOGIC_OR)
CASE(COND) CASE(ASSIGN)
CASE(ARRAY_REF) CASE(STRUCT_REF) CASE(FUNC_CALL)
CASE(PRE_INC) CASE(PRE_DEC) CASE(POST_INC) CASE(POST_DEC)
CASE(SIZEOF_EXPR) CASE(CAST_EXPR) CASE(COMPOUND_LITERAL)
CASE(EXPR_LIST) CASE(ARG_LIST)
CASE(SPECIFIER) CASE(SPEC_LIST) CASE(DECLARATION) CASE(INIT_DECL)
CASE(INIT_DECL_LIST) CASE(DECLARATOR) CASE(ARRAY_DECL) CASE(FUNC_DECL)
CASE(OLD_FUNC_DECL) CASE(POINTER) CASE(PARAM_DECL) CASE(PARAM_LIST)
CASE(ENUM_SPEC) CASE(SU_SPEC) CASE(STRUCT_DECL) CASE(ENUM_CONST)
CASE(TYPE_NAME_NODE) CASE(ABS_DECL) CASE(ABS_ARRAY) CASE(ABS_FUNC)
CASE(INIT_EXPR) CASE(INIT_LIST_NODE) CASE(INIT_ITEM_LIST)
CASE(DESIGNATED_INIT) CASE(ARRAY_DESIGNATOR) CASE(FIELD_DESIGNATOR)
CASE(LABELED_ID_STMT) CASE(CASE_STMT) CASE(DEFAULT_STMT)
CASE(COMPOUND_STMT) CASE(EXPR_STMT) CASE(IF_STMT) CASE(SWITCH_STMT)
CASE(WHILE_STMT) CASE(DO_WHILE_STMT) CASE(FOR_STMT) CASE(FOR_DECL_STMT)
CASE(GOTO_STMT) CASE(CONTINUE_STMT) CASE(BREAK_STMT) CASE(RETURN_STMT)
CASE(BLOCK_ITEM_LIST) CASE(BLOCK_DECL) CASE(BLOCK_STMT) // 添加了 BLOCK_DECL
CASE(TRANSL_UNIT) CASE(DECL_STMT) CASE(FUNCTION_DEF)
// 添加其他可能存在的 Tag
default: return "UNKNOWN";
}
#undef CASE
}
static SourceLoc node_loc(const ASTNode* n) {
if (!n) return {0, 0};
if (n->loc.line || n->loc.col) return n->loc;
if (!n->kids.empty() && n->kids[0]) return node_loc(n->kids[0]); // 添加空指针检查
return n->loc;
}
static void print_ast(const ASTNode* n, int indent = 0)
{
if (!n) return;
auto l = node_loc(n);
std::cout << std::string(indent,' ')
<< "[" << l.line << ":" << l.col << "] "
<< tag_name(n->tag) ;
if (!n->text.empty()) std::cout << " \"" << n->text << "\"";
if (n->ival) std::cout << " (" << n->ival << ")";
if (n->flag) std::cout << " [flag]";
// 打印类型信息(如果存在)
if (n->type) std::cout << " {type: " << n->type->toString() << "}";
std::cout << '\n';
for (auto* child : n->kids) print_ast(child, indent + 2);
}
/*──────────────────────────────
* main
**/
int main(int argc, char* argv[])
{
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <operation> <file>\n";
std::cerr << "Operations: static_compile, view_ast, view_ir, gen_asm\n";
return 1;
}
std::string operation = argv[1];
std::string inputFilename = argv[2];
yyin = std::fopen(inputFilename.c_str(), "r");
if (!yyin) {
std::perror(inputFilename.c_str());
return 2;
}
if (yyparse() == 0 && ast_root != nullptr) {
// 1. 语义分析
SemanticAnalyzer sema;
sema.analyze(ast_root); // 调用 analyze (返回 void)
// *** 修正错误检查 ***
// 通过检查 diagnostics() 的结果来判断是否有错误
bool hasSemanticErrors = !sema.diagnostics().empty();
if (hasSemanticErrors) {
std::cerr << "[!] Semantic Errors Detected:\n";
for (const auto &d : sema.diagnostics()) { // 直接使用 diagnostics() 获取错误
std::cerr << " [" << d.loc.line << ":" << d.loc.col << "] Error: "
<< d.message << "\n";
}
std::cerr << "Compilation aborted due to semantic errors.\n";
fclose(yyin);
return 3; // 返回错误码
}
// else { // 如果没有错误,可以继续执行
// std::cout << "Semantic analysis successful.\n";
// }
// 2. 根据操作执行不同逻辑 (后续代码保持不变)
if (operation == "sc") {
std::cout << "Static compilation checks passed (Semantic Analysis).\n";
} else if (operation == "ast") {
std::cout << "---- Abstract Syntax Tree (AST) ----\n";
print_ast(ast_root);
} else if (operation == "ir") {
// ... (view_ir 代码保持不变) ...
auto globalScope = sema.getGlobalScope();
if (!globalScope) { // *** 添加检查 ***
std::cerr << "FATAL ERROR in main: SemanticAnalyzer::getGlobalScope() returned a null pointer!" << std::endl;
fclose(yyin);
return 6; // 或者其他错误码
}
IRGenerator irgen(globalScope);
auto quads = irgen.generate(ast_root);
std::cout << "\n---- Three-address code (IR) ----\n";
for (const auto &q : quads) {
printf("%-8s %-8s %-8s -> %-8s",
q.op.c_str(),
q.arg1.c_str(),
q.arg2.c_str(),
q.result.c_str());
printf(" @ (%d,%d)", q.loc.line, q.loc.col);
if (!q.var.empty()) printf(" var=%s", q.var.c_str());
if (q.type) printf(" type=%s", q.type->toString().c_str());
printf("\n");
}
}
else if (operation == "debug") {
auto globalScope = sema.getGlobalScope();
IRGenerator irgen(globalScope);
auto quads = irgen.generate(ast_root);
IRInterpreter interp;
interp.runStepByStep(quads);
}
else if (operation == "asm") {
// 确保拿到全局符号表
auto globalScope = sema.getGlobalScope();
if (!globalScope) {
std::cerr << "FATAL ERROR in main: SemanticAnalyzer::getGlobalScope() returned a null pointer!" << std::endl;
fclose(yyin);
return 6;
}
// 生成 IR
IRGenerator irgen(globalScope);
auto quads = irgen.generate(ast_root);
// 生成 ARM64 汇编
AssemblyGenerator asmGen(quads);
std::string asmCode = asmGen.generate();
// 将汇编代码写入文件
std::ofstream outFile("1.s"); // 你可以自定义文件名
if (!outFile) {
std::cerr << "Error: Failed to open output file for writing!" << std::endl;
fclose(yyin);
return 7;
}
outFile << asmCode;
outFile.close();
std::cout << "Assembly code successfully written to '1.s'.\n";
}
else if (operation == "obj") {
const char* assemblyFile = "1.s";
const char* objectFile = "1.o";
// 调用系统命令:使用 `as` 汇编器来将 `1.s` 编译成 `1.o`
std::string command = "as " + std::string(assemblyFile) + " -o " + std::string(objectFile);
// 输出命令并执行
std::cout << "Running command: " << command << std::endl;
// 执行命令
int result = system(command.c_str());
// 检查命令是否执行成功
if (result == 0) {
std::cout << "Compilation successful, " << objectFile << " created." << std::endl;
} else {
std::cerr << "Error during compilation." << std::endl;
}
}
else if (operation == "exec") {
const char* objectFile = "1.o";
const char* executableFile = "1";
// 调用系统命令:使用 `g++` 链接器将 `1.o` 链接成可执行文件 `1`
std::string command = "g++ " + std::string(objectFile) + " -o " + std::string(executableFile);
// 输出命令并执行
std::cout << "Running command: " << command << std::endl;
// 执行命令
int result = system(command.c_str());
// 检查命令是否执行成功
if (result == 0) {
std::cout << "Executable created successfully: " << executableFile << std::endl;
} else {
std::cerr << "Error during linking." << std::endl;
}
}
else if (operation == "pp") {
PrettyPrinter pp(std::cout, /*缩进宽度*/ 4);
pp.print(ast_root);
}
else {
std::cerr << "Error: Unknown operation '" << operation << "'\n";
std::cerr << "Available operations: static_compile, view_ast, view_ir, gen_asm\n";
fclose(yyin);
return 1;
}
fclose(yyin);
return 0;
} else {
std::cerr << "Error: Parsing failed";
if (ast_root == nullptr && yyin != nullptr) {
std::cerr << " (AST generation failed)";
}
std::cerr << ".\n";
if (yyin) fclose(yyin);
return 1;
}
}