parent
80e0a0e081
commit
ab4bd7a366
@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
add_subdirectory(parser)
|
||||
add_subdirectory(ir)
|
||||
add_subdirectory(opt)
|
||||
add_subdirectory(riscv)
|
||||
|
||||
set(SOURCE_FILES main.cpp)
|
||||
|
||||
add_executable(carrotcompiler ${SOURCE_FILES})
|
||||
set_target_properties(carrotcompiler PROPERTIES OUTPUT_NAME "compiler")
|
||||
|
||||
target_include_directories(compiler PRIVATE parser ir opt riscv)
|
||||
|
||||
target_link_libraries(compiler parser ir opt riscv)
|
@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
set(SOURCE_FILES "ir.cpp" "genIR.cpp")
|
||||
|
||||
add_library(ir STATIC ${SOURCE_FILES})
|
||||
|
||||
target_include_directories(ir PRIVATE "${PARSER_INCLUDE}")
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,210 @@
|
||||
#pragma once
|
||||
|
||||
#include "ast.h"
|
||||
#include "ir.h"
|
||||
#include <map>
|
||||
|
||||
class Scope {
|
||||
public:
|
||||
// enter a new scope
|
||||
void enter() { symbol.push_back({}); }
|
||||
|
||||
// exit a scope
|
||||
void exit() { symbol.pop_back(); }
|
||||
|
||||
bool in_global() { return symbol.size() == 1; }
|
||||
|
||||
// push a name to scope
|
||||
// return true if successful
|
||||
// return false if this name already exits
|
||||
// but func name could be same with variable name
|
||||
bool push(std::string name, Value *val) {
|
||||
bool result;
|
||||
result = (symbol[symbol.size() - 1].insert({name, val})).second;
|
||||
return result;
|
||||
}
|
||||
|
||||
Value *find(std::string name) {
|
||||
for (auto s = symbol.rbegin(); s != symbol.rend(); s++) {
|
||||
auto iter = s->find(name);
|
||||
if (iter != s->end()) {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::map<std::string, Value *>> symbol;
|
||||
};
|
||||
|
||||
class GenIR : public Visitor {
|
||||
public:
|
||||
void visit(CompUnitAST &ast) override;
|
||||
void visit(DeclDefAST &ast) override;
|
||||
void visit(DeclAST &ast) override;
|
||||
void visit(DefAST &ast) override;
|
||||
void visit(InitValAST &ast) override;
|
||||
void visit(FuncDefAST &ast) override;
|
||||
void visit(FuncFParamAST &ast) override;
|
||||
void visit(BlockAST &ast) override;
|
||||
void visit(BlockItemAST &ast) override;
|
||||
void visit(StmtAST &ast) override;
|
||||
void visit(ReturnStmtAST &ast) override;
|
||||
void visit(SelectStmtAST &ast) override;
|
||||
void visit(IterationStmtAST &ast) override;
|
||||
void visit(AddExpAST &ast) override;
|
||||
void visit(LValAST &ast) override;
|
||||
void visit(MulExpAST &ast) override;
|
||||
void visit(UnaryExpAST &ast) override;
|
||||
void visit(PrimaryExpAST &ast) override;
|
||||
void visit(CallAST &ast) override;
|
||||
void visit(NumberAST &ast) override;
|
||||
void visit(RelExpAST &ast) override;
|
||||
void visit(EqExpAST &ast) override;
|
||||
void visit(LAndExpAST &ast) override;
|
||||
void visit(LOrExpAST &ast) override;
|
||||
|
||||
IRStmtBuilder *builder;
|
||||
Scope scope;
|
||||
std::unique_ptr<Module> module;
|
||||
|
||||
GenIR() {
|
||||
module = std::unique_ptr<Module>(new Module());
|
||||
builder = new IRStmtBuilder(nullptr, module.get());
|
||||
auto TyVoid = module->void_ty_;
|
||||
auto TyInt32 = module->int32_ty_;
|
||||
auto TyInt32Ptr = module->get_pointer_type(module->int32_ty_);
|
||||
auto TyFloat = module->float32_ty_;
|
||||
auto TyFloatPtr = module->get_pointer_type(module->float32_ty_);
|
||||
|
||||
auto input_type = new FunctionType(TyInt32, {});
|
||||
auto get_int = new Function(input_type, "getint", module.get());
|
||||
|
||||
input_type = new FunctionType(TyFloat, {});
|
||||
auto get_float = new Function(input_type, "getfloat", module.get());
|
||||
|
||||
input_type = new FunctionType(TyInt32, {});
|
||||
auto get_char = new Function(input_type, "getch", module.get());
|
||||
|
||||
std::vector<Type *> input_params;
|
||||
std::vector<Type *>().swap(input_params);
|
||||
input_params.push_back(TyInt32Ptr);
|
||||
input_type = new FunctionType(TyInt32, input_params);
|
||||
auto get_int_array = new Function(input_type, "getarray", module.get());
|
||||
|
||||
std::vector<Type *>().swap(input_params);
|
||||
input_params.push_back(TyFloatPtr);
|
||||
input_type = new FunctionType(TyInt32, input_params);
|
||||
auto get_float_array = new Function(input_type, "getfarray", module.get());
|
||||
|
||||
std::vector<Type *> output_params;
|
||||
std::vector<Type *>().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
auto output_type = new FunctionType(TyVoid, output_params);
|
||||
auto put_int = new Function(output_type, "putint", module.get());
|
||||
|
||||
std::vector<Type *>().swap(output_params);
|
||||
output_params.push_back(TyFloat);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto put_float = new Function(output_type, "putfloat", module.get());
|
||||
|
||||
std::vector<Type *>().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto put_char = new Function(output_type, "putch", module.get());
|
||||
|
||||
std::vector<Type *>().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
output_params.push_back(TyInt32Ptr);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto put_int_array = new Function(output_type, "putarray", module.get());
|
||||
|
||||
std::vector<Type *>().swap(output_params);
|
||||
output_params.push_back(TyInt32);
|
||||
output_params.push_back(TyFloatPtr);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto put_float_array = new Function(output_type, "putfarray", module.get());
|
||||
|
||||
output_params.clear();
|
||||
// output_params.push_back(TyInt32);
|
||||
auto time_type = new FunctionType(TyVoid, output_params);
|
||||
auto sysy_start_time =
|
||||
new Function(time_type, "_sysy_starttime", module.get());
|
||||
auto sysy_stop_time =
|
||||
new Function(time_type, "_sysy_stoptime", module.get());
|
||||
|
||||
output_params.clear();
|
||||
output_params.push_back(TyInt32Ptr);
|
||||
output_params.push_back(TyInt32Ptr);
|
||||
output_params.push_back(TyInt32);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto memcpy = new Function(output_type, "__aeabi_memcpy4", module.get());
|
||||
|
||||
output_params.clear();
|
||||
output_params.push_back(TyInt32Ptr);
|
||||
output_params.push_back(TyInt32);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto memclr = new Function(output_type, "__aeabi_memclr4", module.get());
|
||||
|
||||
output_params.push_back(TyInt32);
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto memset = new Function(output_type, "__aeabi_memset4", module.get());
|
||||
|
||||
output_params.clear();
|
||||
output_type = new FunctionType(TyVoid, output_params);
|
||||
auto llvm_memset =
|
||||
new Function(output_type, "llvm.memset.p0.i32", module.get());
|
||||
|
||||
// output_params.clear();
|
||||
// output_params.push_back(TyInt32);
|
||||
// output_type = new FunctionType(TyInt32, output_params);
|
||||
// auto my_malloc = new Function(output_type, "malloc", module.get());
|
||||
|
||||
scope.enter();
|
||||
scope.push("getint", get_int);
|
||||
scope.push("getfloat", get_float);
|
||||
scope.push("getch", get_char);
|
||||
scope.push("getarray", get_int_array);
|
||||
scope.push("getfarray", get_float_array);
|
||||
scope.push("putint", put_int);
|
||||
scope.push("putfloat", put_float);
|
||||
scope.push("putch", put_char);
|
||||
scope.push("putarray", put_int_array);
|
||||
scope.push("putfarray", put_float_array);
|
||||
scope.push("starttime", sysy_start_time);
|
||||
scope.push("stoptime", sysy_stop_time);
|
||||
scope.push("memcpy", memcpy);
|
||||
scope.push("memclr", memclr);
|
||||
scope.push("memset", memset);
|
||||
scope.push("llvm.memset.p0.i32", llvm_memset);
|
||||
// scope.push("malloc",my_malloc);
|
||||
}
|
||||
std::unique_ptr<Module> getModule() { return std::move(module); }
|
||||
|
||||
void checkInitType() const;
|
||||
|
||||
static int getNextDim(vector<int> &dimensionsCnt, int up, int cnt);
|
||||
|
||||
void localInit(Value *ptr, vector<unique_ptr<InitValAST>> &list,
|
||||
vector<int> &dimensionsCnt, int up);
|
||||
|
||||
static int getNextDim(vector<int> &elementsCnts, int up);
|
||||
|
||||
ConstantArray *globalInit(vector<int> &dimensions,
|
||||
vector<ArrayType *> &arrayTys, int up,
|
||||
vector<unique_ptr<InitValAST>> &list);
|
||||
|
||||
static void mergeElements(vector<int> &dimensions,
|
||||
vector<ArrayType *> &arrayTys, int up, int dimAdd,
|
||||
vector<Constant *> &elements,
|
||||
vector<int> &elementsCnts);
|
||||
|
||||
void finalMerge(vector<int> &dimensions, vector<ArrayType *> &arrayTys,
|
||||
int up, vector<Constant *> &elements,
|
||||
vector<int> &elementsCnts) const;
|
||||
|
||||
bool checkCalType(Value **val, int *intVal, float *floatVal);
|
||||
|
||||
void checkCalType(Value **val);
|
||||
};
|
@ -0,0 +1,105 @@
|
||||
#include "CombineInstr.h"
|
||||
#include "ConstSpread.h"
|
||||
#include "LoopInvariant.h"
|
||||
#include "SimplifyJump.h"
|
||||
#include "ast.h"
|
||||
#include "backend.h"
|
||||
#include "define.h"
|
||||
#include "genIR.h"
|
||||
#include "DeleteDeadCode.h"
|
||||
#include "opt.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <unistd.h>
|
||||
|
||||
extern unique_ptr<CompUnitAST> root;
|
||||
extern int yyparse();
|
||||
extern FILE *yyin;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Assert the number of arguments
|
||||
assert(argc >= 2);
|
||||
|
||||
char *filename = nullptr;
|
||||
int print_ir = false;
|
||||
int print_asm = false;
|
||||
|
||||
std::string output = "-";
|
||||
|
||||
int opt;
|
||||
bool isO2 = false;
|
||||
while ((opt = getopt(argc, argv, "Sco:O::")) != -1) {
|
||||
switch (opt) {
|
||||
case 'S':
|
||||
print_asm = true;
|
||||
print_ir = false;
|
||||
break;
|
||||
case 'c':
|
||||
print_ir = true;
|
||||
print_asm = false;
|
||||
break;
|
||||
case 'o':
|
||||
output = optarg;
|
||||
break;
|
||||
case 'O':
|
||||
isO2 = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
filename = argv[optind];
|
||||
|
||||
yyin = fopen(filename, "r");
|
||||
if (yyin == nullptr) {
|
||||
std::cout << "yyin open" << filename << "failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Frontend parser
|
||||
yyparse();
|
||||
|
||||
// Generate IR from AST
|
||||
GenIR genIR;
|
||||
root->accept(genIR);
|
||||
std::unique_ptr<Module> m = genIR.getModule();
|
||||
|
||||
// Run IR optimization
|
||||
if (isO2) {
|
||||
std::vector<Optimization *> Opt;
|
||||
Opt.push_back(new DeadCodeDeletion(m.get()));
|
||||
Opt.push_back(new ConstSpread(m.get()));
|
||||
Opt.push_back(new CombineInstr(m.get()));
|
||||
Opt.push_back(new DomainTree(m.get()));
|
||||
Opt.push_back(new SimplifyJump(m.get()));
|
||||
Opt.push_back(new LoopInvariant(m.get()));
|
||||
Opt.push_back(new SimplifyJump(m.get()));
|
||||
for (auto x : Opt)
|
||||
x->execute();
|
||||
}
|
||||
|
||||
// Open output file
|
||||
std::ofstream fout;
|
||||
std::ostream *out;
|
||||
if (output == "-") {
|
||||
out = &std::cout;
|
||||
} else {
|
||||
fout.open(output);
|
||||
out = &fout;
|
||||
}
|
||||
|
||||
// Print IR result
|
||||
const std::string IR = m->print();
|
||||
if (print_ir) {
|
||||
*out << IR << std::endl;
|
||||
}
|
||||
|
||||
// Generate assembly file
|
||||
if (print_asm) {
|
||||
auto builder = new RiscvBuilder();
|
||||
const std::string RiscvCode = builder->buildRISCV(m.get());
|
||||
*out << RiscvCode << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
#include "BasicOperation.h"
|
||||
|
||||
void deleteUse(Value *opnd, Instruction *inst) {
|
||||
for (auto it = opnd->use_list_.begin(); it != opnd->use_list_.end(); ++it)
|
||||
if (it->val_ == inst) {
|
||||
opnd->use_list_.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SolvePhi(BasicBlock *bb, BasicBlock *suc) {
|
||||
std::vector<Instruction *> uselessPhi;
|
||||
for (auto instr : suc->instr_list_) {
|
||||
if (instr->op_id_ == Instruction::PHI) {
|
||||
for (int i = 1; i < instr->num_ops_; i = i + 2)
|
||||
if (instr->get_operand(i) == bb) {
|
||||
instr->remove_operands(i - 1, i);
|
||||
break;
|
||||
}
|
||||
if (instr->parent_->pre_bbs_.size() == 1) {
|
||||
Value *only = instr->get_operand(0);
|
||||
instr->replace_all_use_with(only);
|
||||
uselessPhi.push_back(instr);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto instr : uselessPhi)
|
||||
suc->delete_instr(instr);
|
||||
}
|
||||
|
||||
void dfsGraph(BasicBlock *bb, std::set<BasicBlock *> &vis) {
|
||||
if (!bb)
|
||||
return;
|
||||
vis.insert(bb);
|
||||
for (auto suc : bb->succ_bbs_) {
|
||||
if (vis.find(suc) == vis.end())
|
||||
dfsGraph(suc, vis);
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteUnusedBB(Function *func) {
|
||||
std::set<BasicBlock *> vis;
|
||||
for (auto bb : func->basic_blocks_)
|
||||
if (bb->name_ == "label_entry") {
|
||||
dfsGraph(bb, vis);
|
||||
break;
|
||||
}
|
||||
for (auto bb : func->basic_blocks_)
|
||||
if (vis.find(bb) == vis.end()) {
|
||||
bb->parent_->remove_bb(bb);
|
||||
for (auto suc : bb->succ_bbs_)
|
||||
SolvePhi(bb, suc);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#ifndef BASICOPERATION
|
||||
#define BASICOPERATION
|
||||
#include "../ir/ir.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include "opt.h"
|
||||
|
||||
void deleteUse(Value* opnd,Instruction *inst);
|
||||
void dfsGraph(BasicBlock *bb, std::set<BasicBlock *> &vis);
|
||||
void SolvePhi(BasicBlock *bb, BasicBlock *succ_bb);
|
||||
void DeleteUnusedBB(Function *func);
|
||||
|
||||
#endif // !BASICOPERATION
|
@ -0,0 +1,6 @@
|
||||
set(SOURCE_FILES ConstSpread.cpp BasicOperation.cpp LoopInvariant.cpp CombineInstr.cpp SimplifyJump.cpp opt.cpp DeleteDeadCode.cpp)
|
||||
|
||||
add_library(opt ${SOURCE_FILES})
|
||||
|
||||
target_link_libraries(opt PRIVATE ir)
|
||||
target_include_directories(opt PRIVATE ${CMAKE_SOURCE_DIR}/src/ir)
|
@ -0,0 +1,13 @@
|
||||
#ifndef COMBINEINSTRH
|
||||
#define COMBINEINSTRH
|
||||
#include "opt.h"
|
||||
|
||||
class CombineInstr : public Optimization {
|
||||
|
||||
public:
|
||||
CombineInstr(Module *m) : Optimization(m) {}
|
||||
void execute();
|
||||
void checkBlock(BasicBlock *bb);
|
||||
};
|
||||
|
||||
#endif // !COMBINEINSTRH
|
@ -0,0 +1,354 @@
|
||||
#include "ConstSpread.h"
|
||||
|
||||
ConstantInt *ConstSpread::CalcInt(Instruction::OpID op, ConstantInt *v1,
|
||||
ConstantInt *v2) {
|
||||
int a = v1->value_, b = v2->value_;
|
||||
switch (op) {
|
||||
case Instruction::Add:
|
||||
return new ConstantInt(m->int32_ty_, a + b);
|
||||
case Instruction::Sub:
|
||||
return new ConstantInt(m->int32_ty_, a - b);
|
||||
case Instruction::Mul:
|
||||
return new ConstantInt(m->int32_ty_, a * b);
|
||||
case Instruction::SDiv:
|
||||
return new ConstantInt(m->int32_ty_, a / b);
|
||||
case Instruction::SRem:
|
||||
return new ConstantInt(m->int32_ty_, a % b);
|
||||
case Instruction::Shl:
|
||||
return new ConstantInt(m->int32_ty_, a << b);
|
||||
case Instruction::LShr:
|
||||
return new ConstantInt(m->int32_ty_, (unsigned)a >> b);
|
||||
case Instruction::AShr:
|
||||
return new ConstantInt(m->int32_ty_, a >> b);
|
||||
case Instruction::And:
|
||||
return new ConstantInt(m->int32_ty_, a & b);
|
||||
case Instruction::Or:
|
||||
return new ConstantInt(m->int32_ty_, a | b);
|
||||
case Instruction::Xor:
|
||||
return new ConstantInt(m->int32_ty_, a ^ b);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ConstantFloat *ConstSpread::CalcFloat(Instruction::OpID op, ConstantFloat *v1,
|
||||
ConstantFloat *v2) {
|
||||
float a = v1->value_, b = v2->value_;
|
||||
switch (op) {
|
||||
case Instruction::FAdd:
|
||||
return new ConstantFloat(m->float32_ty_, a + b);
|
||||
case Instruction::FSub:
|
||||
return new ConstantFloat(m->float32_ty_, a - b);
|
||||
case Instruction::FMul:
|
||||
return new ConstantFloat(m->float32_ty_, a * b);
|
||||
case Instruction::FDiv:
|
||||
return new ConstantFloat(m->float32_ty_, a / b);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ConstantInt *ConstSpread::CalcICMP(ICmpInst::ICmpOp op, ConstantInt *v1,
|
||||
ConstantInt *v2) {
|
||||
int lhs = v1->value_;
|
||||
int rhs = v2->value_;
|
||||
switch (op) {
|
||||
case ICmpInst::ICMP_EQ:
|
||||
return new ConstantInt(m->int1_ty_, lhs == rhs);
|
||||
case ICmpInst::ICMP_NE:
|
||||
return new ConstantInt(m->int1_ty_, lhs != rhs);
|
||||
case ICmpInst::ICMP_SGT:
|
||||
return new ConstantInt(m->int1_ty_, lhs > rhs);
|
||||
case ICmpInst::ICMP_SGE:
|
||||
return new ConstantInt(m->int1_ty_, lhs >= rhs);
|
||||
case ICmpInst::ICMP_SLE:
|
||||
return new ConstantInt(m->int1_ty_, lhs <= rhs);
|
||||
case ICmpInst::ICMP_SLT:
|
||||
return new ConstantInt(m->int1_ty_, lhs < rhs);
|
||||
case ICmpInst::ICMP_UGE:
|
||||
return new ConstantInt(m->int1_ty_, (unsigned)lhs >= (unsigned)rhs);
|
||||
case ICmpInst::ICMP_ULE:
|
||||
return new ConstantInt(m->int1_ty_, (unsigned)lhs <= (unsigned)rhs);
|
||||
case ICmpInst::ICMP_ULT:
|
||||
return new ConstantInt(m->int1_ty_, (unsigned)lhs < (unsigned)rhs);
|
||||
case ICmpInst::ICMP_UGT:
|
||||
return new ConstantInt(m->int1_ty_, (unsigned)lhs > (unsigned)rhs);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
ConstantInt *ConstSpread::CalcFCMP(FCmpInst::FCmpOp op, ConstantFloat *v1,
|
||||
ConstantFloat *v2) {
|
||||
float lhs = v1->value_;
|
||||
float rhs = v2->value_;
|
||||
switch (op) {
|
||||
case FCmpInst::FCMP_UEQ:
|
||||
return new ConstantInt(m->int1_ty_, lhs == rhs);
|
||||
case FCmpInst::FCMP_UNE:
|
||||
return new ConstantInt(m->int1_ty_, lhs != rhs);
|
||||
case FCmpInst::FCMP_UGT:
|
||||
return new ConstantInt(m->int1_ty_, lhs > rhs);
|
||||
case FCmpInst::FCMP_UGE:
|
||||
return new ConstantInt(m->int1_ty_, lhs >= rhs);
|
||||
case FCmpInst::FCMP_ULE:
|
||||
return new ConstantInt(m->int1_ty_, lhs <= rhs);
|
||||
case FCmpInst::FCMP_ULT:
|
||||
return new ConstantInt(m->int1_ty_, lhs < rhs);
|
||||
case FCmpInst::FCMP_FALSE:
|
||||
return new ConstantInt(m->int1_ty_, 0);
|
||||
case FCmpInst::FCMP_TRUE:
|
||||
return new ConstantInt(m->int1_ty_, 1);
|
||||
case FCmpInst::FCMP_OEQ:
|
||||
return new ConstantInt(m->int1_ty_, lhs == rhs);
|
||||
case FCmpInst::FCMP_ONE:
|
||||
return new ConstantInt(m->int1_ty_, lhs != rhs);
|
||||
case FCmpInst::FCMP_OGE:
|
||||
return new ConstantInt(m->int1_ty_, lhs >= rhs);
|
||||
case FCmpInst::FCMP_OGT:
|
||||
return new ConstantInt(m->int1_ty_, lhs > rhs);
|
||||
case FCmpInst::FCMP_OLE:
|
||||
return new ConstantInt(m->int1_ty_, lhs <= rhs);
|
||||
case FCmpInst::FCMP_OLT:
|
||||
return new ConstantInt(m->int1_ty_, lhs < rhs);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ConstSpread::execute() {
|
||||
assert(m != nullptr);
|
||||
for (Function *foo : m->function_list_) {
|
||||
if (foo->basic_blocks_.size()) {
|
||||
bool change = true;
|
||||
while (change) {
|
||||
change = false;
|
||||
change |= SpreadingConst(foo);
|
||||
change |= BranchProcess(foo);
|
||||
DeleteUnusedBB(foo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ConstSpread::SpreadingConst(Function *func) {
|
||||
uselessInstr.clear();
|
||||
for (auto bb : func->basic_blocks_) {
|
||||
ConstIntMap.clear();
|
||||
ConstFloatMap.clear();
|
||||
for (auto instr : bb->instr_list_) {
|
||||
ConstantInt *testConstInta = nullptr, *testConstIntb = nullptr;
|
||||
ConstantFloat *testConstFloata = nullptr, *testConstFloatb = nullptr;
|
||||
switch (instr->op_id_) {
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SRem:
|
||||
case Instruction::URem:
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
case Instruction::Shl:
|
||||
case Instruction::AShr:
|
||||
case Instruction::LShr:
|
||||
testConstInta = dynamic_cast<ConstantInt *>(instr->get_operand(0));
|
||||
testConstIntb = dynamic_cast<ConstantInt *>(instr->get_operand(1));
|
||||
if (testConstInta && testConstIntb) {
|
||||
auto intRes =
|
||||
this->CalcInt(instr->op_id_, testConstInta, testConstIntb);
|
||||
if (intRes) {
|
||||
instr->replace_all_use_with(intRes);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instruction::ICmp:
|
||||
testConstInta = dynamic_cast<ConstantInt *>(instr->get_operand(0));
|
||||
testConstIntb = dynamic_cast<ConstantInt *>(instr->get_operand(1));
|
||||
if (testConstInta && testConstIntb) {
|
||||
auto res = this->CalcICMP(dynamic_cast<ICmpInst *>(instr)->icmp_op_,
|
||||
testConstInta, testConstIntb);
|
||||
if (res) {
|
||||
instr->replace_all_use_with(res);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instruction::FCmp:
|
||||
testConstFloata = dynamic_cast<ConstantFloat *>(instr->get_operand(0));
|
||||
testConstFloatb = dynamic_cast<ConstantFloat *>(instr->get_operand(1));
|
||||
if (testConstFloata && testConstFloatb) {
|
||||
auto res = this->CalcFCMP(dynamic_cast<FCmpInst *>(instr)->fcmp_op_,
|
||||
testConstFloata, testConstFloatb);
|
||||
if (res) {
|
||||
instr->replace_all_use_with(res);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instruction::FAdd:
|
||||
case Instruction::FSub:
|
||||
case Instruction::FMul:
|
||||
case Instruction::FDiv:
|
||||
testConstFloata = dynamic_cast<ConstantFloat *>(instr->get_operand(0));
|
||||
testConstFloatb = dynamic_cast<ConstantFloat *>(instr->get_operand(1));
|
||||
if (testConstFloata && testConstFloatb) {
|
||||
auto floaRes =
|
||||
this->CalcFloat(instr->op_id_, testConstFloata, testConstFloatb);
|
||||
if (floaRes) {
|
||||
instr->replace_all_use_with(floaRes);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instruction::FNeg:
|
||||
testConstFloata = dynamic_cast<ConstantFloat *>(instr->get_operand(0));
|
||||
if (testConstFloata) {
|
||||
instr->replace_all_use_with(
|
||||
new ConstantFloat(m->float32_ty_, -testConstFloata->value_));
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
break;
|
||||
case Instruction::FPtoSI:
|
||||
testConstFloata = dynamic_cast<ConstantFloat *>(instr->get_operand(0));
|
||||
if (testConstFloata) {
|
||||
instr->replace_all_use_with(
|
||||
new ConstantInt(m->int32_ty_, testConstFloata->value_));
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
break;
|
||||
case Instruction::SItoFP:
|
||||
testConstInta = dynamic_cast<ConstantInt *>(instr->get_operand(0));
|
||||
if (testConstInta) {
|
||||
instr->replace_all_use_with(
|
||||
new ConstantFloat(m->float32_ty_, testConstInta->value_));
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
break;
|
||||
case Instruction::ZExt:
|
||||
testConstInta = dynamic_cast<ConstantInt *>(instr->get_operand(0));
|
||||
if (testConstInta) {
|
||||
instr->replace_all_use_with(
|
||||
new ConstantInt(m->int32_ty_, testConstInta->value_));
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
break;
|
||||
case Instruction::Call:
|
||||
ConstIntMap.clear();
|
||||
ConstFloatMap.clear();
|
||||
case Instruction::Load: {
|
||||
auto globalVar = dynamic_cast<GlobalVariable *>(instr->get_operand(0));
|
||||
if (globalVar) {
|
||||
auto iterInt = ConstIntMap.find(globalVar);
|
||||
auto iterFloat = ConstFloatMap.find(globalVar);
|
||||
if (iterInt != ConstIntMap.end()) {
|
||||
instr->replace_all_use_with(iterInt->second);
|
||||
uselessInstr[instr] = bb;
|
||||
} else if (iterFloat != ConstFloatMap.end()) {
|
||||
instr->replace_all_use_with(iterFloat->second);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
} else if (dynamic_cast<AllocaInst *>(instr->get_operand(0))) {
|
||||
auto pos = dynamic_cast<AllocaInst *>(instr->get_operand(0));
|
||||
if (pos->alloca_ty_->tid_ == Type::IntegerTyID) {
|
||||
auto iterInt = ConstIntMap.find(pos);
|
||||
if (iterInt != ConstIntMap.end()) {
|
||||
instr->replace_all_use_with(iterInt->second);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
} else if (pos->alloca_ty_->tid_ == Type::FloatTyID) {
|
||||
auto iterFloat = ConstFloatMap.find(pos);
|
||||
if (iterFloat != ConstFloatMap.end()) {
|
||||
instr->replace_all_use_with(iterFloat->second);
|
||||
uselessInstr[instr] = bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Instruction::Store: {
|
||||
// std::cout << "EVER STORE\n";
|
||||
auto storePos = instr->get_operand(1);
|
||||
auto storeValInt = dynamic_cast<ConstantInt *>(instr->get_operand(0));
|
||||
auto storeValFloat =
|
||||
dynamic_cast<ConstantFloat *>(instr->get_operand(0));
|
||||
if (storeValInt) {
|
||||
auto iter1 = ConstIntMap.find(storePos);
|
||||
if (iter1 != ConstIntMap.end()) {
|
||||
if (iter1->second->value_ == storeValInt->value_)
|
||||
uselessInstr[instr] = bb;
|
||||
else
|
||||
iter1->second = storeValInt;
|
||||
} else
|
||||
ConstIntMap[storePos] = storeValInt;
|
||||
} else if (storeValFloat) {
|
||||
auto iter = ConstFloatMap.find(storePos);
|
||||
if (iter != ConstFloatMap.end()) {
|
||||
if (iter->second->value_ == storeValInt->value_)
|
||||
uselessInstr[instr] = bb;
|
||||
else
|
||||
iter->second = storeValFloat;
|
||||
} else
|
||||
ConstFloatMap[storePos] = storeValFloat;
|
||||
} else {
|
||||
// 非常量存储,则该地址数据不再是常量
|
||||
auto iterInt = ConstIntMap.find(storePos);
|
||||
auto iterFloat = ConstFloatMap.find(storePos);
|
||||
if (iterInt != ConstIntMap.end())
|
||||
ConstIntMap.erase(iterInt);
|
||||
if (iterFloat != ConstFloatMap.end())
|
||||
ConstFloatMap.erase(iterFloat);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!uselessInstr.empty()) {
|
||||
for (auto [instr, bb] : uselessInstr)
|
||||
bb->delete_instr(instr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConstSpread::BranchProcess(Function *func) {
|
||||
bool change = false;
|
||||
for (auto bb : func->basic_blocks_) {
|
||||
auto br = bb->get_terminator();
|
||||
if (!br)
|
||||
continue;
|
||||
if (br->op_id_ == Instruction::Br &&
|
||||
dynamic_cast<BranchInst *>(br)->num_ops_ == 3) {
|
||||
auto cond = dynamic_cast<ConstantInt *>(br->get_operand(0));
|
||||
auto truebb = br->get_operand(1);
|
||||
auto falsebb = br->get_operand(2);
|
||||
if (!cond)
|
||||
continue;
|
||||
change = true;
|
||||
if (cond->value_ == 0) {
|
||||
bb->delete_instr(br);
|
||||
for (auto succ_bb : bb->succ_bbs_) {
|
||||
succ_bb->remove_pre_basic_block(bb);
|
||||
if (succ_bb != falsebb) {
|
||||
SolvePhi(bb, succ_bb);
|
||||
}
|
||||
}
|
||||
bb->succ_bbs_.clear();
|
||||
new BranchInst(dynamic_cast<BasicBlock *>(falsebb), bb);
|
||||
} else {
|
||||
bb->delete_instr(br);
|
||||
for (auto succ_bb : bb->succ_bbs_) {
|
||||
succ_bb->remove_pre_basic_block(bb);
|
||||
if (succ_bb != truebb) {
|
||||
SolvePhi(bb, succ_bb);
|
||||
}
|
||||
}
|
||||
bb->succ_bbs_.clear();
|
||||
new BranchInst(dynamic_cast<BasicBlock *>(truebb), bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
return change;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
#ifndef CONSTSPREAD
|
||||
#define CONSTSPREAD
|
||||
#include "../ir/ir.h"
|
||||
#include "BasicOperation.h"
|
||||
#include "opt.h"
|
||||
|
||||
class ConstSpread : public Optimization {
|
||||
public:
|
||||
ConstSpread(Module *m_) : Optimization(m_) {}
|
||||
void execute();
|
||||
ConstantInt *CalcInt(Instruction::OpID op, ConstantInt *v1, ConstantInt *v2);
|
||||
ConstantFloat *CalcFloat(Instruction::OpID op, ConstantFloat *v1,
|
||||
ConstantFloat *v2);
|
||||
ConstantInt *CalcICMP(ICmpInst::ICmpOp op, ConstantInt *v1, ConstantInt *v2);
|
||||
ConstantInt *CalcFCMP(FCmpInst::FCmpOp op, ConstantFloat *v1, ConstantFloat *v2);
|
||||
bool SpreadingConst(Function *func);
|
||||
bool BranchProcess(Function *func);
|
||||
std::map<Value *, ConstantInt *> ConstIntMap;
|
||||
std::map<Value *, ConstantFloat *> ConstFloatMap;
|
||||
std::map<Instruction *, BasicBlock *> uselessInstr;
|
||||
};
|
||||
|
||||
#endif // !CONSTSPREAD
|
@ -0,0 +1,180 @@
|
||||
#include "DeleteDeadCode.h"
|
||||
#include "ConstSpread.h"
|
||||
|
||||
std::set<std::string> OptFunc = {"getint", "getfloat",
|
||||
"getch", "getarray",
|
||||
"getfarray", "putint",
|
||||
"putfloat", "putch",
|
||||
"putarray", "putfarray",
|
||||
"_sysy_starttime", "_sysy_stoptime",
|
||||
"memcpy", "memclr",
|
||||
"memset", "llvm.memset.p0.i32",
|
||||
"__aeabi_memcpy4", "__aeabi_memclr4",
|
||||
"__aeabi_memset4"};
|
||||
|
||||
void DeadCodeDeletion::initFuncPtrArg() {
|
||||
for (auto foo : m->function_list_) {
|
||||
if (foo->basic_blocks_.empty())
|
||||
continue;
|
||||
for (auto arg : foo->arguments_)
|
||||
if (arg->type_->tid_ == Type::PointerTyID) {
|
||||
if (!funcPtrArgs.count(foo))
|
||||
funcPtrArgs[foo] = {};
|
||||
funcPtrArgs[foo].insert(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
void DeadCodeDeletion::Init(Function *foo) {
|
||||
storePos.clear();
|
||||
for (auto bb : foo->basic_blocks_) {
|
||||
for (auto ins : bb->instr_list_) {
|
||||
if (ins->op_id_ == Instruction::GetElementPtr) {
|
||||
} else if (ins->op_id_ == Instruction::Store) {
|
||||
if (!storePos.count(ins->get_operand(1))) {
|
||||
storePos.insert({ins->get_operand(1), {}});
|
||||
}
|
||||
storePos[ins->get_operand(1)].push_back(ins);
|
||||
if (dynamic_cast<GlobalVariable *>(ins->get_operand(1)))
|
||||
OptFunc.insert(foo->name_);
|
||||
if (dynamic_cast<GetElementPtrInst *>(ins->get_operand(1)))
|
||||
OptFunc.insert(foo->name_);
|
||||
if (funcPtrArgs[foo].count(ins->get_operand(1)))
|
||||
OptFunc.insert(foo->name_);
|
||||
} else if (ins->op_id_ == Instruction::Call) {
|
||||
auto f = ins->get_operand(ins->operands_.size() - 1);
|
||||
if (OptFunc.count(f->name_))
|
||||
OptFunc.insert(foo->name_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool DeadCodeDeletion::checkOpt(Function *foo, Instruction *ins) {
|
||||
if (ins->op_id_ == Instruction::Ret) {
|
||||
exitBlock = ins->parent_;
|
||||
return true;
|
||||
} else if (ins->op_id_ == Instruction::Call) {
|
||||
auto f = ins->get_operand(ins->operands_.size() - 1);
|
||||
return OptFunc.count(f->name_);
|
||||
} else if (ins->op_id_ == Instruction::Store) {
|
||||
if (dynamic_cast<GlobalVariable *>(ins->get_operand(1)))
|
||||
return true;
|
||||
if (dynamic_cast<GetElementPtrInst *>(ins->get_operand(1)))
|
||||
return true;
|
||||
if (funcPtrArgs[foo].count(ins->get_operand(1)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeadCodeDeletion::findInstr(Function *foo) {
|
||||
std::list<Value *> workList;
|
||||
for (auto bb : foo->basic_blocks_) {
|
||||
for (auto ins : bb->instr_list_) {
|
||||
if (checkOpt(foo, ins)) {
|
||||
uselessInstr.insert(ins);
|
||||
workList.push_back(ins);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!workList.empty()) {
|
||||
auto ins = dynamic_cast<Instruction *>(workList.back());
|
||||
workList.pop_back();
|
||||
if (ins == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (auto operand : ins->operands_) {
|
||||
auto temp = dynamic_cast<Instruction *>(operand);
|
||||
if (!temp)
|
||||
continue;
|
||||
if (uselessInstr.insert(temp).second) {
|
||||
workList.push_back(temp);
|
||||
}
|
||||
}
|
||||
if (ins->op_id_ == Instruction::PHI) {
|
||||
for (int i = 1; i < ins->operands_.size(); i += 2) {
|
||||
auto bb = dynamic_cast<BasicBlock *>(ins->get_operand(i));
|
||||
auto br = bb->get_terminator();
|
||||
if (uselessInstr.insert(br).second) {
|
||||
workList.push_back(br);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (storePos.count(ins)) {
|
||||
for (auto curInstr : storePos[ins]) {
|
||||
if (uselessInstr.insert(dynamic_cast<Instruction *>(curInstr)).second) {
|
||||
workList.push_back(curInstr);
|
||||
}
|
||||
}
|
||||
storePos.erase(ins);
|
||||
}
|
||||
if (uselessBlock.insert(ins->parent_).second) {
|
||||
for (auto RFrontier : ins->parent_->rdom_frontier_) {
|
||||
auto t = RFrontier->get_terminator();
|
||||
if (uselessInstr.insert(t).second) {
|
||||
workList.push_back(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void DeadCodeDeletion::deleteInstr(Function *foo) {
|
||||
int deleteCnt = 0, changeCnt = 0;
|
||||
for (auto bb : foo->basic_blocks_) {
|
||||
std::vector<Instruction *> ins2Del;
|
||||
for (auto ins : bb->instr_list_) {
|
||||
if (!uselessInstr.count(ins)) {
|
||||
if (ins->op_id_ != Instruction::Br) {
|
||||
ins2Del.push_back(ins);
|
||||
} else {
|
||||
if (ins->operands_.size() == 3) {
|
||||
changeCnt++;
|
||||
auto trueBB = dynamic_cast<BasicBlock *>(ins->get_operand(1));
|
||||
auto falseBB = dynamic_cast<BasicBlock *>(ins->get_operand(2));
|
||||
trueBB->remove_pre_basic_block(bb);
|
||||
falseBB->remove_pre_basic_block(bb);
|
||||
bb->remove_succ_basic_block(trueBB);
|
||||
bb->remove_succ_basic_block(falseBB);
|
||||
BasicBlock *temp = exitBlock;
|
||||
std::vector<BasicBlock *> rdoms(bb->rdoms_.begin(),
|
||||
bb->rdoms_.end());
|
||||
std::sort(rdoms.begin(), rdoms.end(),
|
||||
[=](BasicBlock *x, BasicBlock *y) -> bool {
|
||||
return x->rdoms_.count(y);
|
||||
});
|
||||
for (auto rdbb : rdoms) {
|
||||
if (rdbb != bb && uselessBlock.count(rdbb)) {
|
||||
temp = rdbb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ins->remove_operands(0, 2);
|
||||
ins->num_ops_ = 1;
|
||||
ins->operands_.resize(1);
|
||||
ins->use_pos_.resize(1);
|
||||
ins->set_operand(0, temp);
|
||||
bb->add_succ_basic_block(temp);
|
||||
temp->add_pre_basic_block(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
deleteCnt += ins2Del.size();
|
||||
for (auto ins : ins2Del) {
|
||||
bb->delete_instr(ins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeadCodeDeletion::execute() {
|
||||
ReverseDomainTree reverseDomainTree(m);
|
||||
reverseDomainTree.execute();
|
||||
initFuncPtrArg();
|
||||
for (auto foo : m->function_list_)
|
||||
if (!foo->basic_blocks_.empty()) {
|
||||
Init(foo);
|
||||
findInstr(foo);
|
||||
deleteInstr(foo);
|
||||
DeleteUnusedBB(foo);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#ifndef DELETEDEADCODEH
|
||||
#define DELETEDEADCODEH
|
||||
|
||||
#include "opt.h"
|
||||
|
||||
extern std::set<std::string> sysLibFunc;
|
||||
|
||||
class DeadCodeDeletion : public Optimization {
|
||||
std::map<Function *, std::set<Value *>> funcPtrArgs;
|
||||
std::map<Value *, std::vector<Value *>> storePos;
|
||||
BasicBlock *exitBlock;
|
||||
std::set<Instruction *> uselessInstr;
|
||||
std::set<BasicBlock *> uselessBlock;
|
||||
|
||||
public:
|
||||
DeadCodeDeletion(Module *m) : Optimization(m), exitBlock(nullptr) {}
|
||||
void execute();
|
||||
void initFuncPtrArg();
|
||||
void Init(Function *foo);
|
||||
bool checkOpt(Function *foo, Instruction *instr);
|
||||
void findInstr(Function *foo);
|
||||
void deleteInstr(Function *foo);
|
||||
};
|
||||
|
||||
#endif // !DELETEDEADCODEH
|
@ -0,0 +1,31 @@
|
||||
#ifndef LOOPH
|
||||
#define LOOPH
|
||||
|
||||
#include "BasicOperation.h"
|
||||
|
||||
struct node {
|
||||
BasicBlock *bb;
|
||||
std::set<node *> pre;
|
||||
std::set<node *> suc;
|
||||
int dfn, low;
|
||||
bool inStack;
|
||||
node() = default;
|
||||
node(BasicBlock *bb_, int dfn_, int low_, bool inStack_)
|
||||
: bb(bb_), dfn(dfn_), low(low_), inStack(inStack_) {}
|
||||
};
|
||||
|
||||
class LoopInvariant : public Optimization {
|
||||
int ind;
|
||||
std::stack<node *> tarjanStack;
|
||||
std::stack<std::set<BasicBlock *> *> loopStack;
|
||||
std::map<std::set<BasicBlock *> *, BasicBlock *> entryPos;
|
||||
|
||||
public:
|
||||
LoopInvariant(Module *m) : Optimization(m) {}
|
||||
void execute();
|
||||
void searchLoop();
|
||||
bool searchSCC(std::set<node *> &basicBlock, std::set<std::set<node *> *> &SCCs);
|
||||
void tarjan(node *pos, std::set<std::set<node *> *> &SCCs);
|
||||
};
|
||||
|
||||
#endif // !LOOPH
|
@ -0,0 +1,120 @@
|
||||
#include "SimplifyJump.h"
|
||||
|
||||
void SimplifyJump::execute() {
|
||||
for (auto foo : m->function_list_)
|
||||
if (foo->basic_blocks_.empty()) {
|
||||
deleteUnReachableBlock(foo);
|
||||
mergePreBlock(foo);
|
||||
deleteUselessPhi(foo);
|
||||
deleteUselessJump(foo);
|
||||
}
|
||||
}
|
||||
|
||||
void SimplifyJump::deleteUselessBlock(Function *foo,
|
||||
std::vector<BasicBlock *> &uselessBlock) {
|
||||
for (auto bb : uselessBlock)
|
||||
foo->remove_bb(bb);
|
||||
}
|
||||
|
||||
bool SimplifyJump::checkUselessJump(BasicBlock *bb) {
|
||||
auto JumpPos = bb->get_terminator()->get_operand(0);
|
||||
for (auto preBB : bb->pre_bbs_) {
|
||||
auto br = preBB->get_terminator();
|
||||
if (br->operands_.size() == 1)
|
||||
continue;
|
||||
auto trueBB = br->get_operand(1);
|
||||
auto falseBB = br->get_operand(2);
|
||||
if (trueBB == JumpPos || falseBB == JumpPos)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimplifyJump::deleteUnReachableBlock(Function *foo) {
|
||||
std::vector<BasicBlock *> uselessBlock;
|
||||
for (int i = 2; i < foo->basic_blocks_.size(); i++) {
|
||||
auto curbb = foo->basic_blocks_[i];
|
||||
if (curbb->pre_bbs_.empty()) {
|
||||
uselessBlock.push_back(curbb);
|
||||
// 发现无用块后需要提前进行phi合流处理
|
||||
for (auto use : curbb->use_list_) {
|
||||
auto instr = dynamic_cast<PhiInst *>(use.val_);
|
||||
if (instr != nullptr)
|
||||
instr->remove_operands(use.arg_no_ - 1, use.arg_no_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimplifyJump::mergePreBlock(Function *foo) {
|
||||
std::vector<BasicBlock *> uselessBlock;
|
||||
for (int i = 2; i < foo->basic_blocks_.size(); i++) {
|
||||
auto bb = foo->basic_blocks_[i];
|
||||
if (bb->pre_bbs_.size() == 1) {
|
||||
auto preBlock = *bb->pre_bbs_.begin();
|
||||
auto preBr = preBlock->get_terminator();
|
||||
if (preBlock->succ_bbs_.size() != 1)
|
||||
continue;
|
||||
preBlock->delete_instr(preBr);
|
||||
for (auto instr : bb->instr_list_) {
|
||||
preBlock->add_instruction(instr);
|
||||
bb->remove_instr(instr);
|
||||
}
|
||||
preBlock->remove_succ_basic_block(bb);
|
||||
for (auto suc : bb->succ_bbs_) {
|
||||
preBlock->add_succ_basic_block(suc);
|
||||
suc->remove_pre_basic_block(bb);
|
||||
suc->add_pre_basic_block(preBlock);
|
||||
}
|
||||
bb->replace_all_use_with(preBlock);
|
||||
uselessBlock.push_back(bb);
|
||||
}
|
||||
}
|
||||
deleteUselessBlock(foo, uselessBlock);
|
||||
}
|
||||
|
||||
void SimplifyJump::deleteUselessPhi(Function *foo) {
|
||||
for (auto bb : foo->basic_blocks_)
|
||||
if (bb->pre_bbs_.size() == 1)
|
||||
for (auto instr : bb->instr_list_)
|
||||
if (instr->is_phi()) {
|
||||
instr->replace_all_use_with(instr->get_operand(0));
|
||||
bb->delete_instr(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void SimplifyJump::deleteUselessJump(Function *foo) {
|
||||
std::vector<BasicBlock *> uselessBlock;
|
||||
for (int i = 2; i < foo->basic_blocks_.size(); i++) {
|
||||
BasicBlock *curbb = foo->basic_blocks_[i];
|
||||
if (curbb->instr_list_.size() != 1)
|
||||
continue;
|
||||
auto branchInstr = curbb->get_terminator();
|
||||
if (branchInstr->operands_.size() != 1 || branchInstr->is_ret())
|
||||
continue;
|
||||
if (!checkUselessJump(curbb))
|
||||
continue;
|
||||
uselessBlock.push_back(curbb);
|
||||
auto JumpTarget = dynamic_cast<BasicBlock *>(branchInstr->get_operand(0));
|
||||
for (auto instr : JumpTarget->instr_list_)
|
||||
if (instr->is_phi()) {
|
||||
for (int i = 1; i < instr->operands_.size(); i += 2) {
|
||||
if (instr->get_operand(i) == curbb) {
|
||||
auto val = instr->get_operand(i - 1);
|
||||
instr->remove_operands(i - 1, i);
|
||||
for (auto preBB : curbb->pre_bbs_) {
|
||||
instr->add_operand(val);
|
||||
instr->add_operand(preBB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
curbb->replace_all_use_with(JumpTarget);
|
||||
for (auto preBB : curbb->pre_bbs_) {
|
||||
preBB->add_succ_basic_block(JumpTarget);
|
||||
JumpTarget->add_pre_basic_block(preBB);
|
||||
}
|
||||
}
|
||||
deleteUselessBlock(foo, uselessBlock);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#ifndef SIMPLIFYJUMPH
|
||||
#define SIMPLIFYJUMPH
|
||||
#include "opt.h"
|
||||
|
||||
class SimplifyJump : public Optimization {
|
||||
|
||||
public:
|
||||
SimplifyJump(Module *m) : Optimization(m) {}
|
||||
void execute();
|
||||
void deleteUselessBlock(Function *foo,
|
||||
std::vector<BasicBlock *> &uselessBlock);
|
||||
bool checkUselessJump(BasicBlock *bb);
|
||||
void deleteUselessPhi(Function *foo);
|
||||
void deleteUselessJump(Function *foo);
|
||||
void mergePreBlock(Function *foo);
|
||||
void deleteUnReachableBlock(Function *foo);
|
||||
};
|
||||
|
||||
#endif // !SIMPLIFYJUMPH
|
@ -0,0 +1,206 @@
|
||||
#include "opt.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
void DomainTree::execute() {
|
||||
for (auto foo : m->function_list_)
|
||||
if (!foo->basic_blocks_.empty()) {
|
||||
getBlockDom(foo);
|
||||
getBlockDomFront(foo);
|
||||
}
|
||||
}
|
||||
|
||||
bool DomainTree::isLoopEdge(BasicBlock *a, BasicBlock *b) {
|
||||
return TraverseInd[a] > TraverseInd[b];
|
||||
}
|
||||
|
||||
std::vector<BasicBlock *> DomainTree::postTraverse(BasicBlock *bb) {
|
||||
std::set<BasicBlock *> vis;
|
||||
std::vector<BasicBlock *> ans;
|
||||
std::function<void(BasicBlock *)> dfs = [&](BasicBlock *place) {
|
||||
vis.insert(place);
|
||||
for (auto child : place->succ_bbs_)
|
||||
if (vis.find(child) == vis.end())
|
||||
dfs(child);
|
||||
ans.push_back(place);
|
||||
};
|
||||
dfs(bb);
|
||||
return ans;
|
||||
}
|
||||
|
||||
void DomainTree::getReversePostTraverse(Function *f) {
|
||||
doms.clear();
|
||||
reversePostTraverse.clear();
|
||||
TraverseInd.clear();
|
||||
auto entryBlock = *f->basic_blocks_.begin();
|
||||
auto seq = postTraverse(entryBlock);
|
||||
std::reverse(reversePostTraverse.begin(), reversePostTraverse.end());
|
||||
for (int i = 0; i < seq.size(); i++)
|
||||
TraverseInd[seq[i]] = i;
|
||||
reversePostTraverse = seq;
|
||||
}
|
||||
|
||||
void DomainTree::getBlockDom(Function *f) {
|
||||
getReversePostTraverse(f);
|
||||
auto root = *f->basic_blocks_.begin();
|
||||
auto root_id = TraverseInd[root];
|
||||
doms.resize(root_id + 1, nullptr);
|
||||
doms.back() = root;
|
||||
bool change = true;
|
||||
while (change) {
|
||||
change = false;
|
||||
for (auto bb : reversePostTraverse)
|
||||
if (bb != root) {
|
||||
auto preds = bb->pre_bbs_;
|
||||
BasicBlock *curDom = nullptr;
|
||||
for (auto pred_bb : preds)
|
||||
if (doms[TraverseInd[pred_bb]] != nullptr) {
|
||||
curDom = pred_bb;
|
||||
break;
|
||||
}
|
||||
for (auto pred_bb : preds)
|
||||
if (doms[TraverseInd[pred_bb]] != nullptr)
|
||||
curDom = intersect(pred_bb, curDom);
|
||||
if (doms[TraverseInd[bb]] != curDom) {
|
||||
doms[TraverseInd[bb]] = curDom;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto bb : reversePostTraverse)
|
||||
bb->idom_ = doms[TraverseInd[bb]];
|
||||
}
|
||||
|
||||
void DomainTree::getBlockDomFront(Function *foo) {
|
||||
for (auto b : foo->basic_blocks_) {
|
||||
auto b_pred = b->pre_bbs_;
|
||||
if (b_pred.size() >= 2) {
|
||||
for (auto pred : b_pred) {
|
||||
auto runner = pred;
|
||||
while (runner != doms[TraverseInd[b]]) {
|
||||
runner->dom_frontier_.insert(b);
|
||||
runner = doms[TraverseInd[runner]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicBlock *DomainTree::intersect(BasicBlock *b1, BasicBlock *b2) {
|
||||
auto head1 = b1;
|
||||
auto head2 = b2;
|
||||
while (head1 != head2) {
|
||||
while (TraverseInd[head1] < TraverseInd[head2])
|
||||
head1 = doms[TraverseInd[head1]];
|
||||
while (TraverseInd[head2] < TraverseInd[head1])
|
||||
head2 = doms[TraverseInd[head2]];
|
||||
}
|
||||
return head1;
|
||||
}
|
||||
|
||||
void ReverseDomainTree::execute() {
|
||||
for (auto f : m->function_list_)
|
||||
if (!f->basic_blocks_.empty()) {
|
||||
for (auto bb : f->basic_blocks_) {
|
||||
bb->rdoms_.clear();
|
||||
bb->rdom_frontier_.clear();
|
||||
}
|
||||
getBlockDomR(f);
|
||||
getBlockDomFrontR(f);
|
||||
getBlockRdoms(f);
|
||||
}
|
||||
}
|
||||
|
||||
void ReverseDomainTree::getPostTraverse(BasicBlock *bb,
|
||||
std::set<BasicBlock *> &visited) {
|
||||
visited.insert(bb);
|
||||
for (auto parent : bb->pre_bbs_)
|
||||
if (visited.find(parent) == visited.end())
|
||||
getPostTraverse(parent, visited);
|
||||
reverseTraverseInd[bb] = reverseTraverse.size();
|
||||
reverseTraverse.push_back(bb);
|
||||
}
|
||||
|
||||
void ReverseDomainTree::getReversePostTraverse(Function *f) {
|
||||
reverseDomainBlock.clear();
|
||||
reverseTraverse.clear();
|
||||
reverseTraverseInd.clear();
|
||||
for (auto bb : f->basic_blocks_) {
|
||||
auto terminate_instr = bb->get_terminator();
|
||||
if (terminate_instr->op_id_ == Instruction::Ret) {
|
||||
exitBlock = bb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(exitBlock != nullptr);
|
||||
std::set<BasicBlock *> visited = {};
|
||||
getPostTraverse(exitBlock, visited);
|
||||
reverse(reverseTraverse.begin(), reverseTraverse.end());
|
||||
}
|
||||
|
||||
void ReverseDomainTree::getBlockDomR(Function *f) {
|
||||
getReversePostTraverse(f);
|
||||
auto root = exitBlock;
|
||||
auto root_id = reverseTraverseInd[root];
|
||||
for (int i = 0; i < root_id; i++)
|
||||
reverseDomainBlock.push_back(nullptr);
|
||||
reverseDomainBlock.push_back(root);
|
||||
bool change = true;
|
||||
while (change) {
|
||||
change = false;
|
||||
for (auto bb : reverseTraverse) {
|
||||
if (bb != root) {
|
||||
BasicBlock *new_irdom = nullptr;
|
||||
for (auto rpred_bb : bb->succ_bbs_)
|
||||
if (reverseDomainBlock[reverseTraverseInd[rpred_bb]] != nullptr) {
|
||||
new_irdom = rpred_bb;
|
||||
break;
|
||||
}
|
||||
for (auto rpred_bb : bb->succ_bbs_)
|
||||
if (reverseDomainBlock[reverseTraverseInd[rpred_bb]] != nullptr)
|
||||
new_irdom = intersect(rpred_bb, new_irdom);
|
||||
if (reverseDomainBlock[reverseTraverseInd[bb]] != new_irdom) {
|
||||
reverseDomainBlock[reverseTraverseInd[bb]] = new_irdom;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void ReverseDomainTree::getBlockRdoms(Function *f) {
|
||||
for (auto bb : f->basic_blocks_) {
|
||||
if (bb == exitBlock)
|
||||
continue;
|
||||
auto current = bb;
|
||||
while (current != exitBlock) {
|
||||
bb->rdoms_.insert(current);
|
||||
current = reverseDomainBlock[reverseTraverseInd[current]];
|
||||
}
|
||||
}
|
||||
}
|
||||
void ReverseDomainTree::getBlockDomFrontR(Function *f) {
|
||||
for (auto bb_iter = f->basic_blocks_.rbegin();
|
||||
bb_iter != f->basic_blocks_.rend(); bb_iter++) {
|
||||
auto bb = *bb_iter;
|
||||
if (bb->succ_bbs_.size() >= 2) {
|
||||
for (auto rpred : bb->succ_bbs_) {
|
||||
auto runner = rpred;
|
||||
while (runner != reverseDomainBlock[reverseTraverseInd[bb]]) {
|
||||
runner->rdom_frontier_.insert(bb);
|
||||
runner = reverseDomainBlock[reverseTraverseInd[runner]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BasicBlock *ReverseDomainTree::intersect(BasicBlock *b1, BasicBlock *b2) {
|
||||
auto head1 = b1;
|
||||
auto head2 = b2;
|
||||
while (head1 != head2) {
|
||||
while (reverseTraverseInd[head1] < reverseTraverseInd[head2])
|
||||
head1 = reverseDomainBlock[reverseTraverseInd[head1]];
|
||||
while (reverseTraverseInd[head2] < reverseTraverseInd[head1])
|
||||
head2 = reverseDomainBlock[reverseTraverseInd[head2]];
|
||||
}
|
||||
return head1;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
// Currently a dummy file
|
||||
#ifndef OPTH
|
||||
#define OPTH
|
||||
|
||||
#include "ir.h"
|
||||
|
||||
class Optimization {
|
||||
public:
|
||||
Module *m;
|
||||
explicit Optimization(Module *m_) : m(m_) {}
|
||||
virtual void execute() = 0;
|
||||
};
|
||||
|
||||
class DomainTree : public Optimization {
|
||||
std::vector<BasicBlock *> reversePostTraverse;
|
||||
std::map<BasicBlock *, int> TraverseInd;
|
||||
std::vector<BasicBlock *> doms;
|
||||
|
||||
public:
|
||||
DomainTree(Module *m) : Optimization(m) {}
|
||||
void execute();
|
||||
void getReversePostTraverse(Function *foo);
|
||||
std::vector<BasicBlock *> postTraverse(BasicBlock *bb);
|
||||
void getBlockDom(Function *foo);
|
||||
void getBlockDomFront(Function *foo);
|
||||
BasicBlock *intersect(BasicBlock *b1, BasicBlock *b2);
|
||||
bool isLoopEdge(BasicBlock *a, BasicBlock *b);
|
||||
};
|
||||
|
||||
class ReverseDomainTree : public Optimization {
|
||||
std::map<BasicBlock *, int> reverseTraverseInd;
|
||||
std::vector<BasicBlock *> reverseDomainBlock;
|
||||
std::vector<BasicBlock *> reverseTraverse;
|
||||
BasicBlock *exitBlock;
|
||||
|
||||
public:
|
||||
ReverseDomainTree(Module *m) : Optimization(m), exitBlock(nullptr) {}
|
||||
void execute();
|
||||
BasicBlock *intersect(BasicBlock *b1, BasicBlock *b2);
|
||||
void getReversePostTraverse(Function *foo);
|
||||
void getBlockDomR(Function *foo);
|
||||
void getBlockRdoms(Function *foo);
|
||||
void getBlockDomFrontR(Function *foo);
|
||||
void getPostTraverse(BasicBlock *bb, std::set<BasicBlock *> &visited);
|
||||
};
|
||||
#endif // !OPTH
|
@ -0,0 +1,22 @@
|
||||
# Require Flex & Bison as generator
|
||||
# find_package(FLEX 2.5.4 REQUIRED)
|
||||
# find_package(BISON 2.4.1 REQUIRED)
|
||||
|
||||
set(PARSER_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
# set(PARSER_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
set(LEXER_CPP "${PARSER_DIR}/lexer.cpp")
|
||||
set(LEXER_DEF "${PARSER_DIR}/lexer.hpp")
|
||||
set(PARSER_CPP "${PARSER_DIR}/parser.cpp")
|
||||
set(PARSER_DEF "${PARSER_DIR}/parser.hpp")
|
||||
|
||||
# Generate tokenizer & parser via Flex & Bison
|
||||
# flex_target(LEXER "lexer.l" "${LEXER_CPP}" DEFINES_FILE "${LEXER_DEF}")
|
||||
# bison_target(PARSER "parser.y" "${PARSER_CPP}" DEFINES_FILE "${PARSER_DEF}")
|
||||
# add_flex_bison_dependency(LEXER PARSER)
|
||||
|
||||
set(SOURCE_FILES "${LEXER_CPP}" "${PARSER_CPP}" "ast.cpp")
|
||||
set(PARSER_INCLUDE ${PARSER_DIR} ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
|
||||
|
||||
add_library(parser STATIC ${SOURCE_FILES})
|
||||
target_include_directories(parser PRIVATE "${PARSER_INCLUDE}")
|
@ -0,0 +1,10 @@
|
||||
objs=parser.o lexer.o ast.o display.o
|
||||
CC=gcc
|
||||
|
||||
parser:$(objs)
|
||||
$(CC) -o parser ${objs}
|
||||
%.o:%.c
|
||||
$(CC) -c $<
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm parser $(objs) parser.c lexer.c parser.h -f
|
@ -0,0 +1,716 @@
|
||||
#include "ast.h"
|
||||
#include "parser.h" //由bison根据parser.y生成
|
||||
#define DEBUG 1
|
||||
#define INTEGER_MINVALUE -2147483647
|
||||
#define ARRAYCALL 123456789
|
||||
int LEV=0;
|
||||
int main_flag = 0;
|
||||
int call_flag = 0;
|
||||
int main_call = 0;
|
||||
int current_offset = 0;
|
||||
char break_label[30];
|
||||
char continue_label[30];
|
||||
char case_temp[30];
|
||||
char case_label[30];
|
||||
char array_name[30];
|
||||
char struct_name[33];
|
||||
int struct_width = 0;
|
||||
int struct_flag = 0;
|
||||
int array_index = 0;
|
||||
int struct_var_flag = 0;
|
||||
int rtn, flag = 0;
|
||||
int rtn2, op;
|
||||
int return_flag = 0;
|
||||
struct ASTNode* left;
|
||||
struct ASTNode* right;
|
||||
char tokens[200][200]; //用来存储TAC语句信息
|
||||
const char spState[8][20] = { "FUNCTION", "GOTO", "CALL", "PARAM", "LABEL", "ARG", "RETURN","BLOCK" };
|
||||
|
||||
int varlen = 0; //记录当前变量长度
|
||||
int lineNo = 0; //记录行号
|
||||
ASTNode *new_node(node_type type, ASTNode *left, ASTNode *mid, ASTNode *right, int int_val, float float_val, char *symbol, node_type d_type) {
|
||||
ASTNode *n = (ASTNode *)malloc(sizeof(ASTNode));
|
||||
n->type = type;
|
||||
n->left = left;
|
||||
n->mid = mid;
|
||||
n->right = right;
|
||||
n->int_val = int_val;
|
||||
n->float_val = float_val;
|
||||
n->symbol = symbol;
|
||||
n->d_type = d_type;
|
||||
return n;
|
||||
}
|
||||
|
||||
int targetNum[1024];
|
||||
int currentNum[1024];
|
||||
int currentLayer = 0;
|
||||
int handle_next_display = 1;
|
||||
|
||||
int getBranchNum(ASTNode* T)
|
||||
{
|
||||
int count = 0;
|
||||
if(T->left)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
if(T->right)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
if(T->mid)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void printVarType(node_type type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Int:
|
||||
printf("int");
|
||||
break;
|
||||
case Float:
|
||||
printf("float");
|
||||
break;
|
||||
case Void:
|
||||
printf("void");
|
||||
break;
|
||||
default:
|
||||
printf("unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gapProcess()
|
||||
{
|
||||
for(int i=1;i<=currentLayer;i++)
|
||||
{
|
||||
if(i < currentLayer)
|
||||
{
|
||||
if(currentNum[i] <= targetNum[i])
|
||||
{
|
||||
printf("| ");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(currentNum[i] < targetNum[i])
|
||||
{
|
||||
printf("|--");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("`--");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gapManage(ASTNode* T, int reverse)
|
||||
{
|
||||
currentNum[currentLayer]++;
|
||||
currentLayer++;
|
||||
targetNum[currentLayer] = getBranchNum(T);
|
||||
currentNum[currentLayer] = 1;
|
||||
if(reverse)
|
||||
{
|
||||
nextDisplayReverse(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextDisplay(T);
|
||||
}
|
||||
currentLayer--;
|
||||
}
|
||||
|
||||
void sameGapManage(ASTNode* T, int reverse)
|
||||
{
|
||||
currentNum[currentLayer]++;
|
||||
currentLayer++;
|
||||
targetNum[currentLayer] = getBranchNum(T) - 1;
|
||||
currentNum[currentLayer] = 1;
|
||||
if(T->right)
|
||||
{
|
||||
display(T->right);
|
||||
}
|
||||
currentLayer--;
|
||||
display(T->left);
|
||||
}
|
||||
|
||||
void nextDisplay(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
display(T->left);
|
||||
}
|
||||
if(T->mid)
|
||||
{
|
||||
display(T->mid);
|
||||
}
|
||||
if(T->right)
|
||||
{
|
||||
display(T->right);
|
||||
}
|
||||
}
|
||||
|
||||
void nextDisplayReverse(ASTNode* T)
|
||||
{
|
||||
if(T->right)
|
||||
{
|
||||
display(T->right);
|
||||
}
|
||||
if(T->mid)
|
||||
{
|
||||
display(T->mid);
|
||||
}
|
||||
if(T->left)
|
||||
{
|
||||
display(T->left);
|
||||
}
|
||||
}
|
||||
|
||||
void print_root(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("CompUnit\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_comp_unit(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
handle_next_display = 0;
|
||||
switch(T->right->type)
|
||||
{
|
||||
case ConstDecl:
|
||||
print_const_decl(T->right);
|
||||
break;
|
||||
case VarDecl:
|
||||
print_var_decl(T->right);
|
||||
break;
|
||||
case FuncDef:
|
||||
print_func_def(T->right);
|
||||
break;
|
||||
}
|
||||
if(T->left)
|
||||
{
|
||||
currentLayer++;
|
||||
targetNum[currentLayer] = getBranchNum(T) - 1;
|
||||
currentNum[currentLayer] = 1;
|
||||
currentLayer--;
|
||||
display(T->left);
|
||||
}
|
||||
}
|
||||
|
||||
void print_const_decl(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("ConstDecl ");
|
||||
printVarType(T->d_type);
|
||||
printf("\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_const_def(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
gapProcess();
|
||||
printf("ConstDef %s\n", T->symbol);
|
||||
if(T->left)
|
||||
{
|
||||
sameGapManage(T, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gapManage(T, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void print_const_exp_array(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("ConstExpArray\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_const_init_val(ASTNode* T)
|
||||
{
|
||||
if(T->right && T->right->type == ConstExp)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_const_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("ConstInitVal {}\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_const_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == 0)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_mul_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("ConstExp ");
|
||||
if(T->d_type == PLUS)
|
||||
{
|
||||
printf("+\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("-\n");
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_var_decl(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("VarDecl ");
|
||||
printVarType(T->d_type);
|
||||
printf("\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_var_def(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
gapProcess();
|
||||
printf("VarDef %s\n", T->symbol);
|
||||
if(T->left)
|
||||
{
|
||||
sameGapManage(T, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gapManage(T, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void print_init_val(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == Exp)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_exp(T->right);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(T->right)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_init_vals(T->right);
|
||||
}
|
||||
else
|
||||
{
|
||||
gapProcess();
|
||||
printf("Null Init Vals\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_init_vals(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
gapProcess();
|
||||
printf("InitVals\n");
|
||||
if(T->left)
|
||||
{
|
||||
sameGapManage(T, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gapManage(T, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void print_func_def(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("FuncDef ");
|
||||
printVarType(T->d_type);
|
||||
printf(" %s\n", T->symbol);
|
||||
gapManage(T, 0);
|
||||
}
|
||||
|
||||
void print_func_f_param(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
gapProcess();
|
||||
printf("FuncFParams ");
|
||||
printVarType(T->d_type);
|
||||
printf(" %s\n", T->symbol);
|
||||
if(T->left)
|
||||
{
|
||||
sameGapManage(T, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gapManage(T, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void print_block(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("Block\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_block_item(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
handle_next_display = 0;
|
||||
switch(T->right->type)
|
||||
{
|
||||
case ConstDecl:
|
||||
print_const_decl(T->right);
|
||||
break;
|
||||
case VarDecl:
|
||||
print_var_decl(T->right);
|
||||
break;
|
||||
case Stmt:
|
||||
print_stmt(T->right);
|
||||
break;
|
||||
}
|
||||
if(T->left)
|
||||
{
|
||||
currentLayer++;
|
||||
targetNum[currentLayer] = getBranchNum(T) - 1;
|
||||
currentNum[currentLayer] = 1;
|
||||
currentLayer--;
|
||||
display(T->left);
|
||||
}
|
||||
}
|
||||
|
||||
void print_stmt(ASTNode* T)
|
||||
{
|
||||
switch (T->int_val)
|
||||
{
|
||||
case BlankStmt:
|
||||
gapProcess();
|
||||
printf("Blank Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case ExpStmt:
|
||||
handle_next_display = 0;
|
||||
print_exp(T->right);
|
||||
break;
|
||||
case AssignStmt:
|
||||
gapProcess();
|
||||
printf("Assign Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case Block:
|
||||
handle_next_display = 0;
|
||||
print_block(T->right);
|
||||
break;
|
||||
case IfStmt:
|
||||
gapProcess();
|
||||
printf("If Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case IfElseStmt:
|
||||
gapProcess();
|
||||
printf("If-Else Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case WhileStmt:
|
||||
gapProcess();
|
||||
printf("While Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case BreakStmt:
|
||||
gapProcess();
|
||||
printf("Break Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case ContinueStmt:
|
||||
gapProcess();
|
||||
printf("Continue Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case BlankReturnStmt:
|
||||
gapProcess();
|
||||
printf("Blank Return Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
case ReturnStmt:
|
||||
gapProcess();
|
||||
printf("Return Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
default:
|
||||
gapProcess();
|
||||
printf("Unknown Statement\n");
|
||||
gapManage(T, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_exp(ASTNode* T)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_add_exp(T->right);
|
||||
}
|
||||
|
||||
void print_add_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == MUL)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_mul_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("AddExp");
|
||||
if(T->int_val == PLUS)
|
||||
{
|
||||
printf(" +\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" -\n");
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_mul_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == UnaryExp)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_unary_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("MulExp");
|
||||
if(T->int_val == MUL)
|
||||
{
|
||||
printf(" *\n");
|
||||
}
|
||||
else if(T->int_val == DIV)
|
||||
{
|
||||
printf(" /\n");
|
||||
}
|
||||
else if(T->int_val == MOD)
|
||||
{
|
||||
printf(" %%\n");
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_unary_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == PrimaryExp)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_primary_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("UnaryExp ");
|
||||
switch (T->int_val)
|
||||
{
|
||||
case FuncRParams:
|
||||
printf("%s()\n", T->symbol);
|
||||
break;
|
||||
case Plus:
|
||||
printf("+\n");
|
||||
break;
|
||||
case Minus:
|
||||
printf("-\n");
|
||||
break;
|
||||
case NOT:
|
||||
printf("NOT\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_func_r_params(ASTNode* T)
|
||||
{
|
||||
if(T->left)
|
||||
{
|
||||
currentNum[currentLayer]--;
|
||||
}
|
||||
gapProcess();
|
||||
printf("FuncRParams\n");
|
||||
if(T->left)
|
||||
{
|
||||
sameGapManage(T, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gapManage(T, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void print_primary_exp(ASTNode* T)
|
||||
{
|
||||
if(T->d_type == NonType)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
if(T->int_val == Exp)
|
||||
{
|
||||
print_exp(T->right);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_lv_al(T->right);
|
||||
}
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("PrimaryExp ");
|
||||
if(T->d_type == Int)
|
||||
{
|
||||
printf("IntLiteral %d\n", T->int_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("FloatLiteral %f\n", T->float_val);
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_lv_al(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
//printVarType(T->d_type);
|
||||
printf("LVal %s\n", T->symbol);
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_cond(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == 0 && T->right->type == Cond)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_cond(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("Cond");
|
||||
if(T->int_val == OR)
|
||||
{
|
||||
printf(" OR\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_l_and_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == 0)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_eq_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("LAndExp AND\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_eq_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == 0)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_rel_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("EqExp");
|
||||
if(T->int_val == EQ)
|
||||
{
|
||||
printf(" ==\n");
|
||||
}
|
||||
else if(T->int_val == NE)
|
||||
{
|
||||
printf(" !=\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_rel_exp(ASTNode* T)
|
||||
{
|
||||
if(T->int_val == 0)
|
||||
{
|
||||
handle_next_display = 0;
|
||||
print_add_exp(T->right);
|
||||
return;
|
||||
}
|
||||
gapProcess();
|
||||
printf("RelExp ");
|
||||
if(T->int_val == LT)
|
||||
{
|
||||
printf("<\n");
|
||||
}
|
||||
else if(T->int_val == GT)
|
||||
{
|
||||
printf(">\n");
|
||||
}
|
||||
else if(T->int_val == LE)
|
||||
{
|
||||
printf("<=\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(">=\n");
|
||||
}
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_exp_array(ASTNode* T)
|
||||
{
|
||||
gapProcess();
|
||||
printf("ExpArray []\n");
|
||||
gapManage(T, 1);
|
||||
}
|
||||
|
||||
void print_unknown(ASTNode* T)
|
||||
{
|
||||
currentNum[currentLayer]++;
|
||||
gapProcess();
|
||||
printf("Unknown\n");
|
||||
}
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
bison -d parser.y -o parser.c
|
||||
flex -o lexer.c lexer.l
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
enum STYPE { SEMI, ASS, EXP, CONT, BRE, RET, BLK, SEL, ITER };
|
||||
|
||||
enum UOP { UOP_ADD, UOP_MINUS, UOP_NOT };
|
||||
|
||||
enum AOP { AOP_ADD, AOP_MINUS };
|
||||
|
||||
enum MOP { MOP_MUL, MOP_DIV, MOP_MOD };
|
||||
|
||||
enum ROP { ROP_GTE, ROP_LTE, ROP_GT, ROP_LT };
|
||||
|
||||
enum EOP { EOP_EQ, EOP_NEQ };
|
||||
|
||||
enum TYPE { TYPE_VOID, TYPE_INT, TYPE_FLOAT };
|
@ -0,0 +1,101 @@
|
||||
#include "ast.h"
|
||||
extern int targetNum[1024];
|
||||
extern int currentNum[1024];
|
||||
extern int currentLayer;
|
||||
extern int handle_next_display;
|
||||
|
||||
void display(ASTNode* T)
|
||||
{
|
||||
handle_next_display = 1;
|
||||
switch (T->type)
|
||||
{
|
||||
case Root:
|
||||
print_root(T);
|
||||
break;
|
||||
case CompUnit:
|
||||
print_comp_unit(T);
|
||||
break;
|
||||
case ConstDecl:
|
||||
print_const_decl(T);
|
||||
break;
|
||||
case ConstDef:
|
||||
print_const_def(T);
|
||||
break;
|
||||
case ConstExpArray:
|
||||
print_const_exp_array(T);
|
||||
break;
|
||||
case ConstInitVal:
|
||||
print_const_init_val(T);
|
||||
break;
|
||||
case ConstExp:
|
||||
print_const_exp(T);
|
||||
break;
|
||||
case VarDecl:
|
||||
print_var_decl(T);
|
||||
break;
|
||||
case VarDef:
|
||||
print_var_def(T);
|
||||
break;
|
||||
case InitVal:
|
||||
print_init_val(T);
|
||||
break;
|
||||
case InitVals:
|
||||
print_init_vals(T);
|
||||
break;
|
||||
case FuncDef:
|
||||
print_func_def(T);
|
||||
break;
|
||||
case FuncFParam:
|
||||
print_func_f_param(T);
|
||||
break;
|
||||
case Block:
|
||||
print_block(T);
|
||||
break;
|
||||
case BlockItem:
|
||||
print_block_item(T);
|
||||
break;
|
||||
case Stmt:
|
||||
print_stmt(T);
|
||||
break;
|
||||
case Exp:
|
||||
print_exp(T);
|
||||
break;
|
||||
case AddExp:
|
||||
print_add_exp(T);
|
||||
break;
|
||||
case MulExp:
|
||||
print_mul_exp(T);
|
||||
break;
|
||||
case UnaryExp:
|
||||
print_unary_exp(T);
|
||||
break;
|
||||
case FuncRParams:
|
||||
print_func_r_params(T);
|
||||
break;
|
||||
case PrimaryExp:
|
||||
print_primary_exp(T);
|
||||
break;
|
||||
case LVal:
|
||||
print_lv_al(T);
|
||||
break;
|
||||
case Cond:
|
||||
print_cond(T);
|
||||
break;
|
||||
case LAndExp:
|
||||
print_l_and_exp(T);
|
||||
break;
|
||||
case EqExp:
|
||||
print_eq_exp(T);
|
||||
break;
|
||||
case RelExp:
|
||||
print_rel_exp(T);
|
||||
break;
|
||||
case ExpArray:
|
||||
print_exp_array(T);
|
||||
break;
|
||||
default:
|
||||
handle_next_display = 0;
|
||||
print_unknown(T);
|
||||
break;
|
||||
}
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,102 @@
|
||||
%option noyywrap
|
||||
%option yylineno
|
||||
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "ast.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define TESTINFO(type,value) printf("LexToken(%s,%s,%d))\n",type,value,yylineno)
|
||||
int line_cnt = 1;
|
||||
%}
|
||||
|
||||
|
||||
MultilineComment "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/"
|
||||
SingleLineComment "//"[^\n]+
|
||||
Lex_err [1-9][0-9]*[a-zA-Z]+[0-9]*|0[0-7]*[8-9a-zA-Z_]+[0-9a-zA-Z_]*
|
||||
|
||||
%%
|
||||
"//".* { }
|
||||
"/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" {
|
||||
int len = strlen(yytext);
|
||||
for (int i = 0; i < len; i++)
|
||||
if(yytext[i] == '\n')
|
||||
line_cnt++;
|
||||
}
|
||||
"\n" { line_cnt++; }
|
||||
[ \t] { }
|
||||
"int" { TESTINFO("INT","int"); return INT; }
|
||||
"float" { TESTINFO("FLOAT","float"); return FLOAT; }
|
||||
"void" { TESTINFO("VOID","void");return VOID; }
|
||||
"const" { TESTINFO("CONST","const"); return CONST; }
|
||||
"return" { TESTINFO("RETURN","return"); return RETURN; }
|
||||
"if" { TESTINFO("IF","if"); return IF; }
|
||||
"else" { TESTINFO("ELSE","else"); return ELSE; }
|
||||
"while" { TESTINFO("WHILE","while");return WHILE; }
|
||||
"break" { TESTINFO("BREAK","break");return BREAK; }
|
||||
"continue" { TESTINFO("CONTINUE","continue"); return CONTINUE; }
|
||||
"(" { TESTINFO("LP","()");return LP; }
|
||||
")" { TESTINFO("RP",")");return RP; }
|
||||
"[" { TESTINFO("LB","[");return LB; }
|
||||
"]" { TESTINFO("RB","]");return RB; }
|
||||
"{" { TESTINFO("LC","{");return LC; }
|
||||
"}" { TESTINFO("RC","}");return RC; }
|
||||
"," { TESTINFO("COMMA",",");return COMMA; }
|
||||
";" { TESTINFO("SEMI",";");return SEMICOLON; }
|
||||
"+" { TESTINFO("PLUS","+");return PLUS; }
|
||||
"-" { TESTINFO("MINUS","-");return MINUS; }
|
||||
"!" { TESTINFO("NOT","!");return NOT; }
|
||||
"=" { TESTINFO("ASSIGN","=");return ASSIGN; }
|
||||
"*" { TESTINFO("MUL","*");return MUL; }
|
||||
"/" { TESTINFO("DIV","/");return DIV; }
|
||||
"%" { TESTINFO("MOD","%");return MOD; }
|
||||
"&&" { TESTINFO("AND","&&");return AND; }
|
||||
"||" { TESTINFO("OR","||");return OR; }
|
||||
"==" { TESTINFO("EQ","==");return EQ; }
|
||||
"!=" { TESTINFO("NE","!=");return NE; }
|
||||
"<" { TESTINFO("LT","<");return LT; }
|
||||
"<=" { TESTINFO("LE","<=");return LE; }
|
||||
">" { TESTINFO("GT",">");return GT; }
|
||||
">=" { TESTINFO("GE",">=");return GE; }
|
||||
0[xX][0-9a-fA-F]* {
|
||||
int val = 0;
|
||||
int len = strlen(yytext);
|
||||
for (int i = 2; i < len; i++) {
|
||||
val <<= 4;
|
||||
if (isdigit(yytext[i]))
|
||||
val += yytext[i] - '0';
|
||||
else
|
||||
val += yytext[i] - 'a' + 10;
|
||||
}
|
||||
yylval.int_val = val;
|
||||
TESTINFO("INT_LIT","int_lit");
|
||||
return INT_LIT;
|
||||
}
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9_]* {
|
||||
yylval.str_val = (char *)malloc(strlen(yytext) + 1);
|
||||
strcpy(yylval.str_val, yytext);
|
||||
yylval.str_val[strlen(yytext)] = '\0';
|
||||
TESTINFO("ID","id");
|
||||
return ID;
|
||||
}
|
||||
[0-9]*\.[0-9]+f?|[0-9]+e-?[0-9]+f? {
|
||||
yylval.float_val = atof(yytext);
|
||||
TESTINFO("FLOAT_LIT","float_lit");
|
||||
return FLOAT_LIT; }
|
||||
{Lex_err} { return LEX_ERR; }
|
||||
[1-9][0-9]*|0 { yylval.int_val = atoi(yytext); return INT_LIT; }
|
||||
0[0-7]+ {
|
||||
int val = 0;
|
||||
int len = strlen(yytext);
|
||||
for (int i = 1; i < len; i++)
|
||||
val = (val << 3) + yytext[i] - '0';
|
||||
yylval.int_val = val;
|
||||
TESTINFO("INT_LIT","int_lit");
|
||||
return INT_LIT;
|
||||
}
|
||||
. { }
|
||||
%%
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,131 @@
|
||||
/* A Bison parser, made by GNU Bison 3.5.1. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/* Undocumented macros, especially those whose name start with YY_,
|
||||
are private implementation details. Do not rely on them. */
|
||||
|
||||
#ifndef YY_YY_PARSER_H_INCLUDED
|
||||
# define YY_YY_PARSER_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
/* Token type. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
enum yytokentype
|
||||
{
|
||||
ID = 258,
|
||||
INT_LIT = 259,
|
||||
FLOAT_LIT = 260,
|
||||
INT = 261,
|
||||
FLOAT = 262,
|
||||
VOID = 263,
|
||||
CONST = 264,
|
||||
RETURN = 265,
|
||||
IF = 266,
|
||||
ELSE = 267,
|
||||
WHILE = 268,
|
||||
BREAK = 269,
|
||||
CONTINUE = 270,
|
||||
LP = 271,
|
||||
RP = 272,
|
||||
LB = 273,
|
||||
RB = 274,
|
||||
LC = 275,
|
||||
RC = 276,
|
||||
COMMA = 277,
|
||||
SEMICOLON = 278,
|
||||
MINUS = 279,
|
||||
NOT = 280,
|
||||
ASSIGN = 281,
|
||||
PLUS = 282,
|
||||
MUL = 283,
|
||||
DIV = 284,
|
||||
MOD = 285,
|
||||
AND = 286,
|
||||
OR = 287,
|
||||
EQ = 288,
|
||||
NE = 289,
|
||||
LT = 290,
|
||||
LE = 291,
|
||||
GT = 292,
|
||||
GE = 293,
|
||||
LEX_ERR = 294,
|
||||
THEN = 295
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
union YYSTYPE
|
||||
{
|
||||
#line 25 "parser.y"
|
||||
|
||||
int int_val;
|
||||
float float_val;
|
||||
char *str_val;
|
||||
struct ASTNode *node_val;
|
||||
|
||||
#line 105 "parser.h"
|
||||
|
||||
};
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
/* Location type. */
|
||||
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
|
||||
typedef struct YYLTYPE YYLTYPE;
|
||||
struct YYLTYPE
|
||||
{
|
||||
int first_line;
|
||||
int first_column;
|
||||
int last_line;
|
||||
int last_column;
|
||||
};
|
||||
# define YYLTYPE_IS_DECLARED 1
|
||||
# define YYLTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
extern YYLTYPE yylloc;
|
||||
int yyparse (void);
|
||||
|
||||
#endif /* !YY_YY_PARSER_H_INCLUDED */
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -0,0 +1,196 @@
|
||||
%define parse.error verbose
|
||||
%locations
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
ASTNode *root;
|
||||
|
||||
extern FILE *yyin;
|
||||
extern int line_cnt;
|
||||
extern int yylineno;
|
||||
extern char *yytext;
|
||||
extern int yylex();
|
||||
extern int yyparse();
|
||||
//extern void yyerror(char *msg);
|
||||
void yyerror(const char* fmt, ...);
|
||||
int syntax_error = 0;
|
||||
char filename[100];
|
||||
%}
|
||||
|
||||
%union {
|
||||
int int_val;
|
||||
float float_val;
|
||||
char *str_val;
|
||||
struct ASTNode *node_val;
|
||||
}
|
||||
|
||||
%type <node_val> CompUnit ConstDecl VarDecl FuncDef ConstDef ConstInitVal VarDef InitVal FuncFParam ConstExpArray Block
|
||||
%type <node_val> Root BlockItem Stmt LVal PrimaryExp UnaryExp FuncRParams MulExp Exp RelExp EqExp LAndExp LNotExp Cond ConstExp
|
||||
%type <node_val> ExpArray AddExp LOrExp InitVals
|
||||
//ForList
|
||||
|
||||
%token <str_val> ID
|
||||
%token <int_val> INT_LIT
|
||||
%token <float_val> FLOAT_LIT
|
||||
|
||||
%token <int_val> INT FLOAT VOID CONST RETURN IF ELSE WHILE BREAK CONTINUE LP RP LB RB LC RC COMMA SEMICOLON
|
||||
%token <int_val> MINUS NOT ASSIGN PLUS MUL DIV MOD AND OR EQ NE LT LE GT GE LEX_ERR
|
||||
//FOR INC DEC THEN
|
||||
|
||||
%nonassoc THEN
|
||||
%nonassoc ELSE
|
||||
|
||||
%start Root
|
||||
|
||||
%%
|
||||
Root: CompUnit { root = new_node(Root, NULL, NULL, $1, 0, 0, NULL, NonType); };
|
||||
CompUnit: ConstDecl { $$ = new_node(CompUnit, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| VarDecl { $$ = new_node(CompUnit, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| FuncDef { $$ = new_node(CompUnit, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| ConstDecl CompUnit { $$ = new_node(CompUnit, $2, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| VarDecl CompUnit { $$ = new_node(CompUnit, $2, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| FuncDef CompUnit { $$ = new_node(CompUnit, $2, NULL, $1, 0, 0, NULL, NonType); };
|
||||
|
||||
ConstDecl: CONST INT ConstDef SEMICOLON { $$ = new_node(ConstDecl, NULL, NULL, $3, 0, 0, NULL, Int); }
|
||||
| CONST FLOAT ConstDef SEMICOLON { $$ = new_node(ConstDecl, NULL, NULL, $3, 0, 0, NULL, Float); };
|
||||
ConstDef: ID ConstExpArray ASSIGN ConstInitVal { $$ = new_node(ConstDef, NULL, $2, $4, 0, 0, $1, NonType); }
|
||||
| ID ConstExpArray ASSIGN ConstInitVal COMMA ConstDef { $$ = new_node(ConstDef, $6, $2, $4, 0, 0, $1, NonType); };
|
||||
ConstExpArray: { $$ = NULL; }
|
||||
| LB ConstExp RB ConstExpArray { $$ = new_node(ConstExpArray, $4, NULL, $2, 0, 0, NULL, NonType); };
|
||||
ConstInitVal: ConstExp { $$ = new_node(ConstInitVal, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| LC RC { $$ = new_node(ConstInitVal, NULL, NULL, NULL, 0, 0, NULL, NonType); }
|
||||
| LC ConstInitVal RC { $$ = new_node(ConstInitVal, NULL, NULL, $2, 0, 0, NULL, NonType); }
|
||||
| LC ConstInitVal COMMA ConstInitVal RC { $$ = new_node(ConstInitVal, $4, NULL, $2, 0, 0, NULL, NonType); };
|
||||
ConstExp: MulExp { $$ = new_node(ConstExp, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| MulExp PLUS Exp { $$ = new_node(ConstExp, $3, NULL, $1, PLUS, 0, NULL, NonType); }
|
||||
| MulExp MINUS Exp { $$ = new_node(ConstExp, $3, NULL, $1, MINUS, 0, NULL, NonType); };
|
||||
|
||||
VarDecl: INT VarDef SEMICOLON { $$ = new_node(VarDecl, NULL, NULL, $2, 0, 0, NULL, Int); }
|
||||
| FLOAT VarDef SEMICOLON { $$ = new_node(VarDecl, NULL, NULL, $2, 0, 0, NULL, Float); };
|
||||
VarDef: ID ConstExpArray { $$ = new_node(VarDef, NULL, $2, NULL, 0, 0, $1, NonType); }
|
||||
| ID ConstExpArray ASSIGN InitVal { $$ = new_node(VarDef, NULL, $2, $4, 0, 0, $1, NonType); }
|
||||
| ID ConstExpArray COMMA VarDef { $$ = new_node(VarDef, $4, $2, NULL, 0, 0, $1, NonType); }
|
||||
| ID ConstExpArray ASSIGN InitVal COMMA VarDef { $$ = new_node(VarDef, $6, $2, $4, 0, 0, $1, NonType); };
|
||||
InitVal: Exp { $$ = new_node(InitVal, NULL, NULL, $1, Exp, 0, NULL, NonType); }
|
||||
| LC RC { $$ = new_node(InitVal, NULL, NULL, NULL, InitVals, 0, NULL, NonType); }
|
||||
| LC InitVals RC { $$ = new_node(InitVal, NULL, NULL, $2, InitVals, 0, NULL, NonType); };
|
||||
InitVals: InitVal { $$ = new_node(InitVals, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| InitVal COMMA InitVals { $$ = new_node(InitVals, $3, NULL, $1, 0, 0, NULL, NonType); };
|
||||
|
||||
FuncDef: INT ID LP RP Block { $$ = new_node(FuncDef, NULL, NULL, $5, 0, 0, $2, Int); }
|
||||
| FLOAT ID LP RP Block { $$ = new_node(FuncDef, NULL, NULL, $5, 0, 0, $2, Float); }
|
||||
| VOID ID LP RP Block { $$ = new_node(FuncDef, NULL, NULL, $5, 0, 0, $2, Void); }
|
||||
| INT ID LP FuncFParam RP Block { $$ = new_node(FuncDef, NULL, $4, $6, 0, 0, $2, Int); }
|
||||
| FLOAT ID LP FuncFParam RP Block { $$ = new_node(FuncDef, NULL, $4, $6, 0, 0, $2, Float); }
|
||||
| VOID ID LP FuncFParam RP Block { $$ = new_node(FuncDef, NULL, $4, $6, 0, 0, $2, Void); };;
|
||||
FuncFParam: INT ID { $$ = new_node(FuncFParam, NULL, NULL, NULL, 0, 0, $2, Int); }
|
||||
| FLOAT ID { $$ = new_node(FuncFParam, NULL, NULL, NULL, 0, 0, $2, Float); }
|
||||
| INT ID LB RB ExpArray { $$ = new_node(FuncFParam, NULL, NULL, $5, 0, 0, $2, Int); }
|
||||
| FLOAT ID LB RB ExpArray { $$ = new_node(FuncFParam, NULL, NULL, $5, 0, 0, $2, Float); }
|
||||
| INT ID COMMA FuncFParam { $$ = new_node(FuncFParam, $4, NULL, NULL, 0, 0, $2, Int); }
|
||||
| FLOAT ID COMMA FuncFParam { $$ = new_node(FuncFParam, $4, NULL, NULL, 0, 0, $2, Float); }
|
||||
| INT ID LB RB ExpArray COMMA FuncFParam { $$ = new_node(FuncFParam, $7, NULL, $5, 0, 0, $2, Int); }
|
||||
| FLOAT ID LB RB ExpArray COMMA FuncFParam { $$ = new_node(FuncFParam, $7, NULL, $5, 0, 0, $2, Float); };
|
||||
|
||||
Block: LC BlockItem RC { $$ = new_node(Block, NULL, NULL, $2, 0, 0, NULL, NonType); };
|
||||
BlockItem: { $$ = NULL; }
|
||||
| ConstDecl BlockItem { $$ = new_node(BlockItem, $2, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| VarDecl BlockItem { $$ = new_node(BlockItem, $2, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| Stmt BlockItem { $$ = new_node(BlockItem, $2, NULL, $1, 0, 0, NULL, NonType); };
|
||||
|
||||
|
||||
Stmt: LVal ASSIGN Exp SEMICOLON{$$ = new_node(Stmt,$1,NULL,$3,0,0,NULL,NonType);}
|
||||
| Exp SEMICOLON {$$ = new_node(Stmt,NULL,NULL,$1,0,0,NULL,NonType);}
|
||||
| SEMICOLON {$$ = NULL;}
|
||||
| Block{$$ = new_node(Stmt,NULL,NULL,$1,0,0,NULL,NonType);}
|
||||
| IF LP Cond RP Stmt {$$ = new_node(Stmt,$3,NULL,$5,0,0,NULL,NonType);}
|
||||
| IF LP Cond RP Stmt ELSE Stmt {$$ = new_node(Stmt,$3,$7,$5,0,0,NULL,NonType);}
|
||||
| WHILE LP Cond RP Stmt {$$ = new_node(Stmt,$3,NULL,$5,0,0,NULL,NonType);}
|
||||
| BREAK SEMICOLON {$$ = NULL;}
|
||||
| CONTINUE SEMICOLON {$$ = NULL;}
|
||||
| RETURN SEMICOLON {$$ = NULL;}
|
||||
| RETURN Exp SEMICOLON {$$ = new_node(Stmt,NULL,NULL,$2,0,0,NULL,NonType);}
|
||||
;
|
||||
|
||||
|
||||
|
||||
Exp: AddExp { $$ = new_node(Exp, NULL, NULL, $1, 0, 0, NULL, NonType); };
|
||||
AddExp: MulExp { $$ = new_node(AddExp, NULL, NULL, $1, MUL, 0, NULL, NonType); }
|
||||
| MulExp PLUS AddExp { $$ = new_node(AddExp, $3, NULL, $1, PLUS, 0, NULL, NonType); }
|
||||
| MulExp MINUS AddExp { $$ = new_node(AddExp, $3, NULL, $1, MINUS, 0, NULL, NonType); };
|
||||
MulExp: UnaryExp { $$ = new_node(MulExp, NULL, NULL, $1, UnaryExp, 0, NULL, NonType); }
|
||||
| UnaryExp MUL MulExp { $$ = new_node(MulExp, $3, NULL, $1, MUL, 0, NULL, NonType); }
|
||||
| UnaryExp DIV MulExp { $$ = new_node(MulExp, $3, NULL, $1, DIV, 0, NULL, NonType); }
|
||||
| UnaryExp MOD MulExp { $$ = new_node(MulExp, $3, NULL, $1, MOD, 0, NULL, NonType); };
|
||||
UnaryExp: PrimaryExp { $$ = new_node(UnaryExp, NULL, NULL, $1, PrimaryExp, 0, NULL, NonType); }
|
||||
| ID LP RP { $$ = new_node(UnaryExp, NULL, NULL, NULL, FuncRParams, 0, $1, NonType); }
|
||||
| ID LP FuncRParams RP { $$ = new_node(UnaryExp, NULL, NULL, $3, FuncRParams, 0, $1, NonType); }
|
||||
| PLUS UnaryExp { $$ = new_node(UnaryExp, NULL, NULL, $2, Plus, 0, NULL, NonType); }
|
||||
| MINUS UnaryExp { $$ = new_node(UnaryExp, NULL, NULL, $2, Minus, 0, NULL, NonType); }
|
||||
| NOT UnaryExp { $$ = new_node(UnaryExp, NULL, NULL, $2, NOT, 0, NULL, NonType); };
|
||||
FuncRParams: Exp { $$ = new_node(FuncRParams, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| Exp COMMA FuncRParams { $$ = new_node(FuncRParams, $3, NULL, $1, 0, 0, NULL, NonType); };
|
||||
PrimaryExp: LP Exp RP { $$ = new_node(PrimaryExp, NULL, NULL, $2, Exp, 0, NULL, NonType); }
|
||||
| LVal { $$ = new_node(PrimaryExp, NULL, NULL, $1, LVal, 0, NULL, NonType); }
|
||||
| INT_LIT { $$ = new_node(PrimaryExp, NULL, NULL, NULL, $1, 0, NULL, Int); }
|
||||
| FLOAT_LIT { $$ = new_node(PrimaryExp, NULL, NULL, NULL, 0, $1, NULL, Float); };
|
||||
LVal: ID ExpArray { $$ = new_node(LVal, NULL, NULL, $2, 0, 0, $1, NonType); };
|
||||
|
||||
Cond: LOrExp { $$ = new_node(Cond, NULL, NULL, $1, 0, 0, NULL, NonType); };
|
||||
LOrExp: LAndExp { $$ = new_node(Cond, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| LAndExp OR LOrExp { $$ = new_node(Cond, $3, NULL, $1, OR, 0, 0, NonType); }
|
||||
| LNotExp{ $$ = new_node(Cond, NULL, NULL, $1, 0, 0, NULL, NonType); };
|
||||
|
||||
LAndExp: EqExp { $$ = new_node(LAndExp, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| EqExp AND LAndExp { $$ = new_node(LAndExp, $3, NULL, $1, AND, 0, NULL, NonType); };
|
||||
|
||||
LNotExp: NOT LP EqExp RP { $$ = new_node(LNotExp, NULL, NULL, $3, 0, 0, NULL, NonType);};
|
||||
|
||||
EqExp: RelExp { $$ = new_node(EqExp, NULL, NULL, $1, 0, 0, NULL, NonType);}
|
||||
| RelExp EQ EqExp { $$ = new_node(EqExp, $3, NULL, $1, EQ, 0, NULL, NonType); }
|
||||
| RelExp NE EqExp { $$ = new_node(EqExp, $3, NULL, $1, NE, 0, NULL, NonType); };
|
||||
|
||||
RelExp: AddExp { $$ = new_node(RelExp, NULL, NULL, $1, 0, 0, NULL, NonType); }
|
||||
| AddExp LT RelExp { $$ = new_node(RelExp, $3, NULL, $1, LT, 0, NULL, NonType); }
|
||||
| AddExp GT RelExp { $$ = new_node(RelExp, $3, NULL, $1, GT, 0, NULL, NonType);}
|
||||
| AddExp LE RelExp { $$ = new_node(RelExp, $3, NULL, $1, LE, 0, NULL, NonType); }
|
||||
| AddExp GE RelExp { $$ = new_node(RelExp, $3, NULL, $1, GE, 0, NULL, NonType); };
|
||||
|
||||
ExpArray: { $$ = NULL; }
|
||||
| LB Exp RB ExpArray { $$ = new_node(ExpArray, $4, NULL, $2, 0, 0, NULL, NonType); };
|
||||
%%
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int index = strlen(argv[1]) - 1;
|
||||
while(index > 0 && argv[1][index - 1] != '/')
|
||||
index--;
|
||||
strcpy(filename, argv[1] + index);
|
||||
freopen(argv[1], "r", stdin);
|
||||
yyparse();
|
||||
if (syntax_error == 0)
|
||||
display(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void yyerror(char *msg) {
|
||||
printf("%s:%d\n", name, yylineno);
|
||||
printf("error text: %s\n", yytext);
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
#include<stdarg.h>
|
||||
void yyerror(const char* fmt, ...)
|
||||
{
|
||||
syntax_error = 1;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s:%d ", filename, yylineno);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, ".\n");
|
||||
}
|
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
set(SOURCE_FILES "riscv.cpp" instruction.cpp optimize.cpp backend.cpp regalloc.cpp)
|
||||
|
||||
add_library(riscv STATIC ${SOURCE_FILES})
|
||||
|
||||
target_link_libraries(riscv PRIVATE ir)
|
||||
target_include_directories(riscv PRIVATE ${CMAKE_SOURCE_DIR}/src/ir)
|
@ -0,0 +1,3 @@
|
||||
#include "optimize.h"
|
||||
|
||||
void OptimizeBlock() {}
|
@ -0,0 +1,11 @@
|
||||
#ifndef OPTIMIZEH
|
||||
#define OPTIMIZEH
|
||||
|
||||
#include "riscv.h"
|
||||
#include "ir.h"
|
||||
|
||||
// 进行数据流的优化
|
||||
// 在此之前先分配各寄存器
|
||||
// 可选
|
||||
void OptimizeBlock();
|
||||
#endif // !OPTIMIZEH
|
@ -0,0 +1,380 @@
|
||||
#include "regalloc.h"
|
||||
#include "instruction.h"
|
||||
#include "riscv.h"
|
||||
|
||||
int IntRegID = 32, FloatRegID = 32; // 测试阶段使用
|
||||
|
||||
Register *NamefindReg(std::string reg) {
|
||||
if (reg.size() > 4)
|
||||
return nullptr;
|
||||
|
||||
Register *reg_to_ret = new Register(Register::Int, 0);
|
||||
|
||||
// Check if int registers
|
||||
for (int i = 0; i < 32; i++) {
|
||||
reg_to_ret->rid_ = i;
|
||||
if (reg_to_ret->print() == reg)
|
||||
return reg_to_ret;
|
||||
}
|
||||
|
||||
// Else then float registers
|
||||
reg_to_ret->regtype_ = reg_to_ret->Float;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
reg_to_ret->rid_ = i;
|
||||
if (reg_to_ret->print() == reg)
|
||||
return reg_to_ret;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RiscvOperand *getRegOperand(std::string reg) {
|
||||
for (auto regope : regPool) {
|
||||
if (regope->print() == reg)
|
||||
return regope;
|
||||
}
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RiscvOperand *getRegOperand(Register::RegType op_ty_, int id) {
|
||||
Register *reg = new Register(op_ty_, id);
|
||||
for (auto regope : regPool) {
|
||||
if (regope->print() == reg->print()) {
|
||||
delete reg;
|
||||
return regope;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type *getStoreTypeFromRegType(RiscvOperand *riscvReg) {
|
||||
return riscvReg->getType() == RiscvOperand::OpTy::FloatReg
|
||||
? new Type(Type::TypeID::FloatTyID)
|
||||
: new Type(Type::TypeID::IntegerTyID);
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::findReg(Value *val, RiscvBasicBlock *bb,
|
||||
RiscvInstr *instr, int inReg, int load,
|
||||
RiscvOperand *specified, bool direct) {
|
||||
safeFindTimeStamp++;
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
bool isGVar = dynamic_cast<GlobalVariable *>(val) != nullptr;
|
||||
bool isAlloca = dynamic_cast<AllocaInst *>(val) != nullptr;
|
||||
bool isPointer = val->type_->tid_ == val->type_->PointerTyID;
|
||||
|
||||
// If there is no register allocated for value then get a new one
|
||||
if (specified != nullptr)
|
||||
setPositionReg(val, specified, bb, instr);
|
||||
else if (curReg.find(val) == curReg.end() || isAlloca ||
|
||||
val->is_constant()) { // Alloca and constant value is always unsafe.
|
||||
bool found = false;
|
||||
RiscvOperand *cur = nullptr;
|
||||
IntRegID = 32;
|
||||
FloatRegID = 32;
|
||||
while (!found) {
|
||||
if (val->type_->tid_ != Type::FloatTyID) {
|
||||
++IntRegID;
|
||||
if (IntRegID > 27)
|
||||
IntRegID = 18;
|
||||
|
||||
cur = getRegOperand(Register::Int, IntRegID);
|
||||
} else {
|
||||
++FloatRegID;
|
||||
if (FloatRegID > 27)
|
||||
FloatRegID = 18;
|
||||
cur = getRegOperand(Register::Float, FloatRegID);
|
||||
}
|
||||
if (regFindTimeStamp.find(cur) == regFindTimeStamp.end() ||
|
||||
safeFindTimeStamp - regFindTimeStamp[cur] > SAFE_FIND_LIMIT) {
|
||||
setPositionReg(val, cur, bb, instr);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
regFindTimeStamp[curReg[val]] = safeFindTimeStamp;
|
||||
return curReg[val];
|
||||
}
|
||||
|
||||
// ! Though all registers are considered unsafe, there is no way
|
||||
// ! to writeback registers properly in findReg() for now.
|
||||
// ! Therefore unsafe part below is not being executed for now.
|
||||
// ! Maybe should consider using writeback() instead.
|
||||
// For now, all registers are considered unsafe thus registers should always
|
||||
// load from memory before using and save to memory after using.
|
||||
auto mem_addr = findMem(val, bb, instr, 1); // Value's direct memory address
|
||||
auto current_reg = curReg[val]; // Value's current register
|
||||
auto load_type = val->type_;
|
||||
|
||||
regFindTimeStamp[current_reg] = safeFindTimeStamp; // Update time stamp
|
||||
if (load) {
|
||||
// Load before usage.
|
||||
if (mem_addr != nullptr) {
|
||||
bb->addInstrBefore(
|
||||
new LoadRiscvInst(load_type, current_reg, mem_addr, bb), instr);
|
||||
} else if (val->is_constant()) {
|
||||
// If value is a int constant, create a LI instruction.
|
||||
auto cval = dynamic_cast<ConstantInt *>(val);
|
||||
if (cval != nullptr)
|
||||
bb->addInstrBefore(new MoveRiscvInst(current_reg, cval->value_, bb),
|
||||
instr);
|
||||
else if (dynamic_cast<ConstantFloat *>(val) != nullptr)
|
||||
bb->addInstrBefore(
|
||||
new MoveRiscvInst(current_reg, this->findMem(val), bb), instr);
|
||||
else {
|
||||
std::cerr << "[Warning] Trying to find a register for unknown type of "
|
||||
"constant value which is not implemented for now."
|
||||
<< std::endl;
|
||||
}
|
||||
} else if (isAlloca) {
|
||||
bb->addInstrBefore(
|
||||
new BinaryRiscvInst(
|
||||
BinaryRiscvInst::ADDI, getRegOperand("fp"),
|
||||
new RiscvConst(static_cast<RiscvIntPhiReg *>(pos[val])->shift_),
|
||||
current_reg, bb),
|
||||
instr);
|
||||
// std::cerr << "[Debug] Get a alloca position <" << val->print() << ", "
|
||||
// << static_cast<RiscvIntPhiReg *>(pos[val])->print()
|
||||
// << "> into the register <" << current_reg->print() << ">"
|
||||
// << std::endl;
|
||||
} else {
|
||||
std::cerr << "[Error] Unknown error in findReg()." << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
return current_reg;
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::findMem(Value *val, RiscvBasicBlock *bb,
|
||||
RiscvInstr *instr, bool direct) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
if (pos.count(val) == 0 && !val->is_constant()) {
|
||||
std::cerr << "[Warning] Value " << std::hex << val << " (" << val->name_
|
||||
<< ")'s memory map not found." << std::endl;
|
||||
}
|
||||
bool isGVar = dynamic_cast<GlobalVariable *>(val) != nullptr;
|
||||
bool isPointer = val->type_->tid_ == val->type_->PointerTyID;
|
||||
bool isAlloca = dynamic_cast<AllocaInst *>(val) != nullptr;
|
||||
// All float constant considered as global variables for now.
|
||||
isGVar = isGVar || dynamic_cast<ConstantFloat *>(val) != nullptr;
|
||||
// Always loading global variable's address into t5 when execute findMem().
|
||||
if (isGVar) {
|
||||
if (bb == nullptr) {
|
||||
std::cerr << "[Warning] Trying to add global var addressing "
|
||||
"instruction, but basic block pointer is null."
|
||||
<< std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
bb->addInstrBefore(
|
||||
new LoadAddressRiscvInstr(getRegOperand("t5"), pos[val]->print(), bb),
|
||||
instr);
|
||||
return new RiscvIntPhiReg("t5");
|
||||
}
|
||||
// If not loading pointer's address directly, then use indirect addressing.
|
||||
// Ignore alloca due to the instruction only being dealt by findReg()
|
||||
if (isPointer && !isAlloca && !direct) {
|
||||
if (bb == nullptr) {
|
||||
std::cerr << "[Warning] Trying to add indirect pointer addressing "
|
||||
"instruction, but basic block pointer is null."
|
||||
<< std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bb->addInstrBefore(new LoadRiscvInst(new Type(Type::PointerTyID),
|
||||
getRegOperand("t4"), pos[val], bb),
|
||||
instr);
|
||||
return new RiscvIntPhiReg("t4");
|
||||
}
|
||||
// Cannot access to alloca's memory directly.
|
||||
else if (direct && isAlloca)
|
||||
return nullptr;
|
||||
|
||||
if (pos.find(val) == pos.end())
|
||||
return nullptr;
|
||||
|
||||
return pos[val];
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::findMem(Value *val) {
|
||||
return findMem(val, nullptr, nullptr, true);
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::findNonuse(Type *ty, RiscvBasicBlock *bb,
|
||||
RiscvInstr *instr) {
|
||||
if (ty->tid_ == Type::IntegerTyID || ty->tid_ == Type::PointerTyID) {
|
||||
++IntRegID;
|
||||
if (IntRegID > 27)
|
||||
IntRegID = 18;
|
||||
return getRegOperand(Register::Int, IntRegID);
|
||||
} else {
|
||||
++FloatRegID;
|
||||
if (FloatRegID > 27)
|
||||
FloatRegID = 18;
|
||||
return getRegOperand(Register::Float, FloatRegID);
|
||||
}
|
||||
}
|
||||
|
||||
void RegAlloca::setPosition(Value *val, RiscvOperand *riscvVal) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
if (pos.find(val) != pos.end()) {
|
||||
// std::cerr << "[Warning] Trying overwriting memory address map of value "
|
||||
// << std::hex << val << " (" << val->name_ << ") ["
|
||||
// << riscvVal->print() << " -> " << pos[val]->print() << "]"
|
||||
// << std::endl;
|
||||
// std::terminate();
|
||||
}
|
||||
|
||||
// std::cerr << "[Debug] [RegAlloca] Map value <" << val->print()
|
||||
// << "> to operand <" << riscvVal->print() << ">" << std::endl;
|
||||
|
||||
pos[val] = riscvVal;
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::findSpecificReg(Value *val, std::string RegName,
|
||||
RiscvBasicBlock *bb, RiscvInstr *instr,
|
||||
bool direct) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
RiscvOperand *retOperand = getRegOperand(RegName);
|
||||
|
||||
return findReg(val, bb, instr, 0, 1, retOperand, direct);
|
||||
}
|
||||
|
||||
void RegAlloca::setPositionReg(Value *val, RiscvOperand *riscvReg,
|
||||
RiscvBasicBlock *bb, RiscvInstr *instr) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
Value *old_val = getRegPosition(riscvReg);
|
||||
RiscvOperand *old_reg = getPositionReg(val);
|
||||
if (old_val != nullptr && old_val != val)
|
||||
writeback(riscvReg, bb, instr);
|
||||
if (old_reg != nullptr && old_reg != riscvReg)
|
||||
writeback(old_reg, bb, instr);
|
||||
setPositionReg(val, riscvReg);
|
||||
}
|
||||
|
||||
void RegAlloca::setPositionReg(Value *val, RiscvOperand *riscvReg) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
if (riscvReg->isRegister() == false) {
|
||||
std::cerr << "[Fatal error] Trying to map value " << std::hex << val
|
||||
<< " to not a register operand." << std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
// std::cerr << "[Debug] Map register <" << riscvReg->print() << "> to value <"
|
||||
// << val->print() << ">\n";
|
||||
|
||||
curReg[val] = riscvReg;
|
||||
regPos[riscvReg] = val;
|
||||
regUsed.insert(riscvReg);
|
||||
}
|
||||
|
||||
RiscvInstr *RegAlloca::writeback(RiscvOperand *riscvReg, RiscvBasicBlock *bb,
|
||||
RiscvInstr *instr) {
|
||||
Value *value = getRegPosition(riscvReg);
|
||||
if (value == nullptr)
|
||||
return nullptr; // Value not found in map
|
||||
|
||||
value = this->DSU_for_Variable.query(value);
|
||||
|
||||
// std::cerr << "[Debug] [RegAlloca] Writeback register <" << riscvReg->print()
|
||||
// << "> to value <" << value->print() << ">.\n";
|
||||
|
||||
// Erase map info
|
||||
regPos.erase(riscvReg);
|
||||
regFindTimeStamp.erase(riscvReg);
|
||||
curReg.erase(value);
|
||||
|
||||
RiscvOperand *mem_addr = findMem(value);
|
||||
|
||||
if (mem_addr == nullptr) {
|
||||
// std::cerr << "[Debug] [RegAlloca] Writeback ignore alloca pointer direct "
|
||||
// "access and immvalue.\n";
|
||||
return nullptr; // Maybe an immediate value or dicrect accessing alloca
|
||||
}
|
||||
|
||||
auto store_type = value->type_;
|
||||
auto store_instr = new StoreRiscvInst(value->type_, riscvReg, mem_addr, bb);
|
||||
|
||||
// Write store instruction
|
||||
if (instr != nullptr)
|
||||
bb->addInstrBefore(store_instr, instr);
|
||||
else
|
||||
bb->addInstrBack(store_instr);
|
||||
|
||||
return store_instr;
|
||||
}
|
||||
|
||||
RegAlloca::RegAlloca() {
|
||||
// 初始化寄存器对象池。
|
||||
if (regPool.size() == 0) {
|
||||
for (int i = 0; i < 32; i++)
|
||||
regPool.push_back(new RiscvIntReg(new Register(Register::Int, i)));
|
||||
for (int i = 0; i < 32; i++)
|
||||
regPool.push_back(new RiscvFloatReg(new Register(Register::Float, i)));
|
||||
}
|
||||
|
||||
// fp 的保护单独进行处理
|
||||
regUsed.insert(getRegOperand("ra"));
|
||||
savedRegister.push_back(getRegOperand("ra")); // 保护 ra
|
||||
// 保护 s1-s11
|
||||
for (int i = 1; i <= 11; i++)
|
||||
savedRegister.push_back(getRegOperand("s" + std::to_string(i)));
|
||||
// 保护 fs0-fs11
|
||||
for (int i = 0; i <= 11; i++)
|
||||
savedRegister.push_back(getRegOperand("fs" + std::to_string(i)));
|
||||
}
|
||||
|
||||
RiscvInstr *RegAlloca::writeback(Value *val, RiscvBasicBlock *bb,
|
||||
RiscvInstr *instr) {
|
||||
auto reg = getPositionReg(val);
|
||||
return writeback(reg, bb, instr);
|
||||
}
|
||||
|
||||
Value *RegAlloca::getRegPosition(RiscvOperand *reg) {
|
||||
if (regPos.find(reg) == regPos.end())
|
||||
return nullptr;
|
||||
return this->DSU_for_Variable.query(regPos[reg]);
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::getPositionReg(Value *val) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
if (curReg.find(val) == curReg.end())
|
||||
return nullptr;
|
||||
return curReg[val];
|
||||
}
|
||||
|
||||
RiscvOperand *RegAlloca::findPtr(Value *val, RiscvBasicBlock *bb,
|
||||
RiscvInstr *instr) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
if (ptrPos.find(val) == ptrPos.end()) {
|
||||
std::cerr << "[Fatal Error] Value's pointer position not found."
|
||||
<< std::endl;
|
||||
std::terminate();
|
||||
}
|
||||
return ptrPos[val];
|
||||
}
|
||||
|
||||
void RegAlloca::writeback_all(RiscvBasicBlock *bb, RiscvInstr *instr) {
|
||||
std::vector<RiscvOperand *> regs_to_writeback;
|
||||
for (auto p : regPos)
|
||||
regs_to_writeback.push_back(p.first);
|
||||
for (auto r : regs_to_writeback)
|
||||
writeback(r, bb, instr);
|
||||
}
|
||||
|
||||
void RegAlloca::setPointerPos(Value *val, RiscvOperand *PointerMem) {
|
||||
val = this->DSU_for_Variable.query(val);
|
||||
assert(val->type_->tid_ == Type::TypeID::PointerTyID ||
|
||||
val->type_->tid_ == Type::TypeID::ArrayTyID);
|
||||
// std::cerr << "SET POINTER: " << val->name_ << "!" << PointerMem->print()
|
||||
// << "\n";
|
||||
this->ptrPos[val] = PointerMem;
|
||||
}
|
||||
|
||||
void RegAlloca::clear() {
|
||||
curReg.clear();
|
||||
regPos.clear();
|
||||
safeFindTimeStamp = 0;
|
||||
regFindTimeStamp.clear();
|
||||
}
|
Loading…
Reference in new issue