init3
This commit is contained in:
parent
d5e0b54645
commit
0bf7488ed1
|
|
@ -1,18 +1,15 @@
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
project(LiteGoCompiler)
|
project(LiteGoCompiler)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -O3 -g")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -O2 -g")
|
||||||
|
|
||||||
|
|
||||||
# library in subdirectory
|
# library in subdirectory
|
||||||
add_subdirectory(antlr)
|
add_subdirectory(antlr)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
# executable
|
||||||
# excutable
|
|
||||||
add_executable(LiteGoCompiler main.cpp)
|
add_executable(LiteGoCompiler main.cpp)
|
||||||
|
|
||||||
target_include_directories(LiteGoCompiler
|
target_include_directories(LiteGoCompiler
|
||||||
|
|
@ -26,3 +23,12 @@ target_link_libraries(LiteGoCompiler
|
||||||
icg
|
icg
|
||||||
tcg
|
tcg
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Custom clean target to remove all directories
|
||||||
|
add_custom_target(clean-all
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_SOURCE_DIR}/*
|
||||||
|
COMMENT "Removing all directories and files in the current directory"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make 'clean' depend on 'clean-all'
|
||||||
|
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||||
144
main.cpp
144
main.cpp
|
|
@ -6,131 +6,115 @@
|
||||||
#include "GoParserListener.h"
|
#include "GoParserListener.h"
|
||||||
#include "GoParserBaseListener.h"
|
#include "GoParserBaseListener.h"
|
||||||
#include "TCG/Translator.h"
|
#include "TCG/Translator.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <optional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
void init_log(const std::string& log_file_name, const std::string& log_path) {
|
void init_log(const std::string& log_file_name, const std::string& log_path) {
|
||||||
system(("mkdir -p " + log_path).c_str());
|
system(("mkdir -p " + log_path).c_str());
|
||||||
google::InitGoogleLogging(log_file_name.c_str());
|
google::InitGoogleLogging(log_file_name.c_str());
|
||||||
google::SetLogDestination(google::GLOG_INFO, (log_path + "/").c_str());
|
google::SetLogDestination(google::GLOG_INFO, (log_path + "/").c_str());
|
||||||
// google::SetStderrLogging(google::INFO);
|
google::InstallFailureSignalHandler(); // Capture signals
|
||||||
google::InstallFailureSignalHandler(); // 捕捉信号
|
FLAGS_log_prefix = true; // Log prefixes
|
||||||
FLAGS_log_prefix = true; // 日志前缀
|
FLAGS_colorlogtostderr = true; // Color logs in stderr
|
||||||
FLAGS_colorlogtostderr = true; // 颜色
|
FLAGS_alsologtostderr = true; // Log to console
|
||||||
FLAGS_alsologtostderr = true; // 日志输出到屏幕
|
FLAGS_logbufsecs = 0; // Disable log buffering
|
||||||
FLAGS_logbufsecs = 0; // 日志缓冲时间
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct CmdParam {
|
struct CmdParam {
|
||||||
std::vector<std::string> input;
|
std::vector<std::string> input;
|
||||||
std::string output = ".";
|
std::string output;
|
||||||
std::string output_3code = "3code.txt";
|
std::string output_3code = "3code.txt";
|
||||||
std::string output_asm = "out.asm";
|
std::string output_asm = "out.asm";
|
||||||
std::string output_bin = "out.bin";
|
std::string output_bin = "out.bin";
|
||||||
std::string log_path = "./log";
|
std::string log_path;
|
||||||
std::string log_file_name;
|
std::string log_file_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<std::string> parse_option(const std::string& option, int& i, int argc, char* argv[]) {
|
||||||
|
if (i + 1 < argc) {
|
||||||
|
return argv[++i];
|
||||||
|
}
|
||||||
|
std::cerr << "Option " << option << " requires a value." << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
CmdParam read_cmd_param(int argc, char* argv[]) {
|
CmdParam read_cmd_param(int argc, char* argv[]) {
|
||||||
CmdParam cmd_param;
|
CmdParam cmd_param;
|
||||||
cmd_param.log_file_name = argv[0];
|
cmd_param.log_file_name = argv[0];
|
||||||
int i = 1;
|
|
||||||
while (i < argc) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
std::string argv_i = argv[i];
|
std::string argv_i = argv[i];
|
||||||
if (argv_i[0] == '-') {
|
if (argv_i.starts_with('-')) {
|
||||||
// option
|
|
||||||
if ((argv_i == "-h") || (argv_i == "--help")) {
|
|
||||||
std::cout << "可选参数如下:" << std::endl;
|
|
||||||
std::cout << "-h (--help): 帮助" << std::endl;
|
|
||||||
std::cout << "-o (--output): [default: .] 输出文件路径" << std::endl;
|
|
||||||
std::cout << "-3 (--3code): [default: 3code.txt] 输出 3code 文件名" << std::endl;
|
|
||||||
std::cout << "-a (--asm): [default: out] 输出 asm 文件名" << std::endl;
|
|
||||||
std::cout << "-b (--bin): [default: bin] 输出 bin 文件名" << std::endl;
|
|
||||||
std::cout << "-l (--log): [default: log] 输出 log 目录" << std::endl;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if (argv_i.length() == 1) {
|
if (argv_i.length() == 1) {
|
||||||
std::cout << "选项错误" << std::endl;
|
std::cerr << "Invalid option." << std::endl;
|
||||||
exit(0);
|
exit(EXIT_FAILURE);
|
||||||
} else if (i + 1 == argc) {
|
}
|
||||||
std::cout << "选项 " << argv_i << " 没有给定值" << std::endl;
|
if (auto value = parse_option(argv_i, i, argc, argv)) {
|
||||||
exit(0);
|
if (argv_i == "-o" || argv_i == "--output") {
|
||||||
} else {
|
cmd_param.output = *value;
|
||||||
// 解析参数
|
} else if (argv_i == "-l" || argv_i == "--log") {
|
||||||
if ((argv_i == "-o") || (argv_i == "--output")) {
|
cmd_param.log_path = *value;
|
||||||
cmd_param.output = argv[++i];
|
|
||||||
} else if ((argv_i == "-3") || (argv_i == "--3code")) {
|
|
||||||
cmd_param.output_3code = argv[++i];
|
|
||||||
} else if ((argv_i == "-a") || (argv_i == "--asm")) {
|
|
||||||
cmd_param.output_asm = argv[++i];
|
|
||||||
} else if ((argv_i == "-b") || (argv_i == "--bin")) {
|
|
||||||
cmd_param.output_bin == argv[++i];
|
|
||||||
} else if ((argv_i == "-l") || (argv_i == "--log")) {
|
|
||||||
cmd_param.log_path = argv[++i];
|
|
||||||
} else {
|
} else {
|
||||||
std::cout << "未知参数 " << argv_i << std::endl;
|
std::cerr << "Unknown parameter " << argv_i << std::endl;
|
||||||
exit(0);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// input
|
|
||||||
cmd_param.input.emplace_back(argv[i]);
|
cmd_param.input.emplace_back(argv[i]);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
if (cmd_param.input.size() == 0) {
|
|
||||||
std::cout << "没有输入的 .go 文件" << std::endl;
|
if (cmd_param.input.empty()) {
|
||||||
exit(0);
|
std::cerr << "No input .go files provided." << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
system(("mkdir -p " + cmd_param.output).c_str());
|
|
||||||
|
for (const auto& input_file : cmd_param.input) {
|
||||||
|
std::string base_name = std::filesystem::path(input_file).stem().string();
|
||||||
|
if (base_name.ends_with(".go")) {
|
||||||
|
base_name = base_name.substr(0, base_name.length() - 3);
|
||||||
|
}
|
||||||
|
cmd_param.output = base_name;
|
||||||
|
std::filesystem::create_directories(cmd_param.output);
|
||||||
|
}
|
||||||
|
|
||||||
return cmd_param;
|
return cmd_param;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
int main(int argc, char * argv[]){
|
|
||||||
std::string cmd0 = "cd ../grammar/java";
|
|
||||||
cmd0 += "&& javac *.java";
|
|
||||||
cmd0 += "&& cd ../../build";
|
|
||||||
// system(cmd0.c_str());
|
|
||||||
|
|
||||||
CmdParam cmd_param = read_cmd_param(argc, argv);
|
CmdParam cmd_param = read_cmd_param(argc, argv);
|
||||||
init_log(cmd_param.log_file_name, cmd_param.log_path);
|
init_log(cmd_param.log_file_name, cmd_param.log_path);
|
||||||
|
const string& filename = cmd_param.input.front();
|
||||||
|
|
||||||
// string filename = "calculate.go";
|
LOG(INFO) << "Starting translation for file: " << filename;
|
||||||
string filename = cmd_param.input[0];
|
|
||||||
LOG(WARNING) << "start 翻译文件: " << filename;
|
|
||||||
|
|
||||||
antlr4::ANTLRFileStream file;
|
antlr4::ANTLRFileStream file;
|
||||||
file.loadFromFile(filename);
|
file.loadFromFile(filename);
|
||||||
antlr4::ANTLRInputStream inputStream(file.toString());
|
antlr4::ANTLRInputStream inputStream(file.toString());
|
||||||
LOG(WARNING) << "start 词法分析";
|
|
||||||
|
LOG(INFO) << "Starting lexical analysis.";
|
||||||
GoLexer lexer(&inputStream);
|
GoLexer lexer(&inputStream);
|
||||||
antlr4::CommonTokenStream tokens(&lexer);
|
antlr4::CommonTokenStream tokens(&lexer);
|
||||||
LOG(WARNING) << "start 语法分析";
|
LOG(INFO) << "Starting syntax analysis.";
|
||||||
GoParser parser(&tokens);
|
GoParser parser(&tokens);
|
||||||
myGoListener listener;
|
myGoListener listener;
|
||||||
antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, parser.sourceFile());
|
antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, parser.sourceFile());
|
||||||
|
|
||||||
std::string path_3code = cmd_param.output + "/" + cmd_param.output_3code;
|
std::string path_3code = cmd_param.output + "/" + cmd_param.output_3code;
|
||||||
listener.Go23file_(path_3code);
|
listener.Go23file_(path_3code);
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
LOG(WARNING) << "start 三地址 -> 汇编";
|
LOG(INFO) << "Translating three-address code to assembly.";
|
||||||
std::shared_ptr<TACFile> tac_file = std::make_shared<TACFile>(std::move(listener.TACBlocks));
|
auto tac_file = make_shared<TACFile>(std::move(listener.TACBlocks));
|
||||||
Translator translator(std::shared_ptr<TACFile>(tac_file), listener.globalScope);
|
Translator translator(tac_file, listener.globalScope);
|
||||||
translator.Translate();
|
translator.Translate();
|
||||||
std::string path_asm = cmd_param.output + "/" + cmd_param.output_asm;
|
std::string path_asm = cmd_param.output + "/" + cmd_param.output_asm;
|
||||||
translator.OutputFile(path_asm);
|
translator.OutputFile(path_asm);
|
||||||
|
|
||||||
std::string path_bin = cmd_param.output + "/" + cmd_param.output_bin;
|
LOG(INFO) << "Translation completed successfully.";
|
||||||
std::string cmd;
|
|
||||||
cmd = "nasm -f elf32 -o " + cmd_param.output + "/out.o " + path_asm;
|
|
||||||
std::cout << cmd << std::endl; system(cmd.c_str());
|
|
||||||
cmd = "nasm -f elf32 -o " + cmd_param.output + "/print.o " + "/usr/local/share/doc/print.asm";
|
|
||||||
std::cout << cmd << std::endl; system(cmd.c_str());
|
|
||||||
cmd = "ld -m elf_i386 -o " + path_bin + " " + cmd_param.output + "/out.o " + cmd_param.output + "/print.o";
|
|
||||||
std::cout << cmd << std::endl; system(cmd.c_str());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
; print.asm
|
||||||
|
global myprint ; 设置print为全局可见
|
||||||
|
|
||||||
|
|
||||||
|
myprint:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push esi
|
||||||
|
|
||||||
|
mov edi, 0
|
||||||
|
|
||||||
|
sub esp, 1
|
||||||
|
mov byte [esp], 0
|
||||||
|
add edi, 1
|
||||||
|
|
||||||
|
sub esp, 1
|
||||||
|
mov byte [esp], 10
|
||||||
|
add edi, 1
|
||||||
|
|
||||||
|
mov edx, 0
|
||||||
|
mov eax, [ebp + 8]
|
||||||
|
; mov eax, 98765
|
||||||
|
mov ecx, 10
|
||||||
|
LOOP_:
|
||||||
|
div ecx
|
||||||
|
add edx, 48
|
||||||
|
sub esp, 1
|
||||||
|
mov byte [esp], dl
|
||||||
|
add edi, 1
|
||||||
|
mov edx, 0
|
||||||
|
cmp eax, 0
|
||||||
|
jne LOOP_
|
||||||
|
|
||||||
|
mov eax, 4 ; 发起系统调用
|
||||||
|
mov ebx, 1 ; ebx表示stdout
|
||||||
|
mov ecx, esp ; 表示字符串的地址
|
||||||
|
mov edx, edi ; 表示字符的个数
|
||||||
|
int 0x80 ; int 0x80表示系统调用
|
||||||
|
|
||||||
|
add esp, edi
|
||||||
|
|
||||||
|
pop esi
|
||||||
|
pop edx
|
||||||
|
pop ecx
|
||||||
|
pop ebx
|
||||||
|
pop eax
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
Binary file not shown.
Binary file not shown.
48
test/test.go
48
test/test.go
|
|
@ -1,48 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
var g int = ^20
|
|
||||||
|
|
||||||
func swap(x, y int) (int, int) {
|
|
||||||
return y, x
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// if语句
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var a,b int = 10,20
|
|
||||||
if a < 20 {
|
|
||||||
fmt.Printf("a 小于 20\n" );
|
|
||||||
} else {
|
|
||||||
fmt.Printf("a 不小于 20\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// for语句
|
|
||||||
var sum int
|
|
||||||
for i:=0; i <= 10; i++ {
|
|
||||||
sum += i
|
|
||||||
}
|
|
||||||
for sum <= 15 { //10加到15
|
|
||||||
sum += sum
|
|
||||||
}
|
|
||||||
for {}
|
|
||||||
|
|
||||||
// 函数调用
|
|
||||||
var s1,s2 int = "aaa","bbb"
|
|
||||||
s3, s4 := swap(s1, s2)
|
|
||||||
|
|
||||||
// 全局变量vs局部变量
|
|
||||||
var g int = 10
|
|
||||||
fmt.Printf ("结果: g = %d\n", g)
|
|
||||||
|
|
||||||
// 指针
|
|
||||||
var tmp int= 20
|
|
||||||
var p *int
|
|
||||||
ip = &a
|
|
||||||
fmt.Printf("*ip 变量的值: %d\n", *ip )
|
|
||||||
}
|
|
||||||
22
test_all.sh
22
test_all.sh
|
|
@ -6,18 +6,24 @@ failure_count=0
|
||||||
failed_files=()
|
failed_files=()
|
||||||
successful_files=()
|
successful_files=()
|
||||||
|
|
||||||
for test_file in ../test/*.go; do
|
test_folder=../test/e
|
||||||
|
|
||||||
|
for test_file in $test_folder/*.go; do
|
||||||
base_name=$(basename "$test_file" .go)
|
base_name=$(basename "$test_file" .go)
|
||||||
|
|
||||||
echo -e "\n========== 编译 $base_name =========="
|
echo -e "\n========== 编译 $base_name =========="
|
||||||
if ! ./LiteGoCompiler ../test/$test_file; then
|
if ! ./LiteGoCompiler $test_folder/$base_name.go; then
|
||||||
echo "编译错误"
|
echo "编译错误"
|
||||||
failure_count=$((failure_count + 1))
|
failure_count=$((failure_count + 1))
|
||||||
failed_files+=("$base_name")
|
failed_files+=("$base_name")
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! ld -m elf_i386 -o run.bin out.o print.o; then
|
nasm -f elf32 -o "$base_name/out.o" "$base_name/out.asm"
|
||||||
|
nasm -f elf32 -o "$test_folder/print.o" $test_folder/print.asm
|
||||||
|
|
||||||
|
|
||||||
|
if ! ld -m elf_i386 -o "$base_name/out.bin" "$base_name/out.o" "$test_folder/print.o"; then
|
||||||
echo "链接错误"
|
echo "链接错误"
|
||||||
failure_count=$((failure_count + 1))
|
failure_count=$((failure_count + 1))
|
||||||
failed_files+=("$base_name")
|
failed_files+=("$base_name")
|
||||||
|
|
@ -25,7 +31,7 @@ for test_file in ../test/*.go; do
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\n========== 运行 $base_name =========="
|
echo -e "\n========== 运行 $base_name =========="
|
||||||
if ! ./run.bin; then
|
if ! $base_name/out.bin; then
|
||||||
echo "运行错误"
|
echo "运行错误"
|
||||||
failure_count=$((failure_count + 1))
|
failure_count=$((failure_count + 1))
|
||||||
failed_files+=("$base_name")
|
failed_files+=("$base_name")
|
||||||
|
|
@ -38,7 +44,7 @@ done
|
||||||
|
|
||||||
# 输出统计结果
|
# 输出统计结果
|
||||||
echo -e "\n========== 编译结果统计 =========="
|
echo -e "\n========== 编译结果统计 =========="
|
||||||
echo "编译成功的文件数量: $success_count"
|
echo "成功的文件数量: $success_count"
|
||||||
echo "编译成功的文件名: ${successful_files[*]}"
|
echo "成功的文件名: ${successful_files[*]}"
|
||||||
echo "编译失败的文件数量: $failure_count"
|
echo "失败的文件数量: $failure_count"
|
||||||
echo "编译失败的文件名: ${failed_files[*]}"
|
echo "失败的文件名: ${failed_files[*]}"
|
||||||
Loading…
Reference in New Issue