set up structure for opt

This commit is contained in:
2024-10-17 14:25:21 +00:00
parent cafd3ccdac
commit 84c92dac81
9 changed files with 182 additions and 8 deletions

View File

@ -2,8 +2,9 @@ add_subdirectory(ast)
add_subdirectory(semantic)
add_subdirectory(IR)
add_subdirectory(naivebackend)
add_subdirectory(opt)
add_executable(zmxcc main.cpp)
target_link_libraries(zmxcc semantic argparse IR naivebackend)
target_link_libraries(zmxcc semantic argparse IR naivebackend opt)
set_target_properties(zmxcc PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)

View File

@ -4,6 +4,7 @@
#include "IR/IR.h"
#include "naivebackend/naivebackend.h"
#include "semantic/semantic.h"
#include "opt/opt.h"
int main(int argc, char **argv) {
argparse::ArgumentParser program("zmxcc");
@ -12,10 +13,9 @@ int main(int argc, char **argv) {
program.add_argument("-o", "--output").help("output file path").nargs(1).required();
program.add_argument("--naive-IR")
.help("output unoptimized LLVM IR code")
.default_value(false)
.implicit_value(true);
program.add_argument("--naive-IR").help("output unoptimized LLVM IR code").default_value(false).implicit_value(true);
program.add_argument("--optimize-all").help("enable all optimizations").default_value(false).implicit_value(true);
try {
program.parse_args(argc, argv);
@ -28,6 +28,7 @@ int main(int argc, char **argv) {
auto input_file = program.get<std::string>("input");
auto output_file = program.get<std::string>("output");
bool output_naive_ir = program.get<bool>("--naive-IR");
bool optimize_all = program.get<bool>("--optimize-all");
std::ifstream fin(input_file);
std::ofstream fout(output_file);
@ -41,9 +42,12 @@ int main(int argc, char **argv) {
IR->RecursivePrint(fout);
return 0;
}
IR->RecursivePrint(std::cerr);
GenerateNaiveASM(fout, IR);
if (!optimize_all) {
GenerateNaiveASM(fout, IR);
} else {
auto IR_with_out_allocas = Mem2Reg(IR);
IR_with_out_allocas->RecursivePrint(fout);
}
} catch (const SemanticError &err) {
std::cout << err.what() << std::endl;
return err.GetErrorCode();

5
src/opt/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
include_directories(${CMAKE_SOURCE_DIR}/include/opt)
file(GLOB NAIVE_BACKEND_SOURCES "*.cpp")
add_library(opt STATIC ${NAIVE_BACKEND_SOURCES})
target_link_libraries(opt PUBLIC ast)

109
src/opt/cfg.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "cfg.h"
#include <string>
CFGNodeCollection GetCFGNodeCollectionsIntersection(const CFGNodeCollection &a, const CFGNodeCollection &b) {
// assume that thety are both sorted
CFGNodeCollection res;
auto ita = a.begin();
auto itb = b.begin();
while (ita != a.end() && itb != b.end()) {
if (*ita == *itb) {
res.push_back(*ita);
ita++;
itb++;
} else if (*ita < *itb) {
ita++;
} else {
itb++;
}
}
return res;
}
CFGNodeCollection GetCFGNodeCollectionsUnion(const CFGNodeCollection &a, const CFGNodeCollection &b) {
// assume that thety are both sorted
CFGNodeCollection res;
auto ita = a.begin();
auto itb = b.begin();
while (ita != a.end() && itb != b.end()) {
if (*ita == *itb) {
res.push_back(*ita);
ita++;
itb++;
} else if (*ita < *itb) {
res.push_back(*ita);
ita++;
} else {
res.push_back(*itb);
itb++;
}
}
while (ita != a.end()) {
res.push_back(*ita);
ita++;
}
while (itb != b.end()) {
res.push_back(*itb);
itb++;
}
return res;
}
CFGNodeCollection GetCFGNodeCollectionsDifference(const CFGNodeCollection &a, const CFGNodeCollection &b) {
// assume that thety are both sorted
CFGNodeCollection res;
auto ita = a.begin();
auto itb = b.begin();
while (ita != a.end() && itb != b.end()) {
if (*ita == *itb) {
ita++;
itb++;
} else if (*ita < *itb) {
res.push_back(*ita);
ita++;
} else {
itb++;
}
}
while (ita != a.end()) {
res.push_back(*ita);
ita++;
}
return res;
}
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func) {
CFGType res;
if (!func->init_block) {
throw std::runtime_error("Function does not have an init block");
}
res.label_to_block[func->init_block->label_full] = func->init_block.get();
res.nodes.push_back(std::make_shared<CFGNodeType>());
res.entry = res.nodes.back().get();
res.entry->corresponding_block = func->init_block.get();
res.block_to_node[func->init_block.get()] = res.entry;
for (auto block_ptr : func->basic_blocks) {
res.label_to_block[block_ptr->label_full] = block_ptr.get();
res.nodes.push_back(std::make_shared<CFGNodeType>());
res.nodes.back()->corresponding_block = block_ptr.get();
res.block_to_node[block_ptr.get()] = res.nodes.back().get();
}
// now add information for successors and predecessors
for (auto node : res.nodes) {
auto block = node->corresponding_block;
if (block->exit_action) {
if (auto br = std::dynamic_pointer_cast<BRAction>(block->exit_action)) {
node->successors.push_back(res.block_to_node[res.label_to_block[br->true_label_full]]);
node->successors.push_back(res.block_to_node[res.label_to_block[br->false_label_full]]);
} else if (auto uncond = std::dynamic_pointer_cast<UNConditionJMPAction>(block->exit_action)) {
node->successors.push_back(res.block_to_node[res.label_to_block[uncond->label_full]]);
} else if (auto ret = std::dynamic_pointer_cast<RETAction>(block->exit_action)) {
// do nothing
} else {
throw std::runtime_error("Unknown exit action");
}
} else {
throw std::runtime_error("Block does not have an exit action");
}
}
return res;
}

13
src/opt/mem2reg.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "mem2reg.h"
#include "cfg.h"
void ConductMem2RegForFunction(const std::shared_ptr<FunctionDefItem> &func, const CFGType &cfg) {}
std::shared_ptr<ModuleItem> Mem2Reg(std::shared_ptr<ModuleItem> src) {
auto res = std::make_shared<ModuleItem>(*src);
for (auto &func : res->function_defs) {
func = std::make_shared<FunctionDefItem>(*func);
auto cfg = BuildCFGForFunction(func);
ConductMem2RegForFunction(func, cfg);
}
return res;
}