From 25343e085684b6bc0784e8b4bec1a49d0df419c8 Mon Sep 17 00:00:00 2001 From: Sofia Date: Sat, 11 Apr 2026 18:40:35 +0300 Subject: [PATCH] Produce LLVM IR and object file --- .gitignore | 3 ++- src/main.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index c795b05..c12ab5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -build \ No newline at end of file +build +test.o \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index db79527..5371c46 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,15 +41,28 @@ std::string read_file(std::string& filepath) { return out; } -int main() { +int write_file(std::string& filepath, std::string& content) { + std::ofstream output{ filepath }; + if (!output) { + std::cerr << "Failed to open " << filepath << " for reading" << std::endl; + return 1; + } - std::string filename{ "test.c" }; + output << content << std::endl; + return 0; +} - std::string out{ read_file(filename) }; +struct CompileOutput { + std::string llvm_ir_string; + std::string obj_string; +}; + +std::optional compile(std::string& in_filename) { + std::string out{ read_file(in_filename) }; std::cout << out << std::endl; - auto tokens = token::tokenize(out, filename); + auto tokens = token::tokenize(out, in_filename); for (token::Token token : tokens) { std::cout << token << std::endl; } @@ -64,7 +77,7 @@ int main() { } if (stream.peek().type != token::Type::Eof) { std::cerr << statement.unwrap_err() << std::endl; - return 1; + return {}; } stream.expect(token::Type::Eof); @@ -92,7 +105,7 @@ int main() { std::cerr << "FATAL: " << error.what() << std::endl; std::cerr << " at " << error.m_meta.start.line + 1 << ":" << error.m_meta.start.col + 1; std::cerr << " to " << error.m_meta.end.line + 1 << ":" << error.m_meta.end.col + 1 << std::endl; - return 1; + return {}; } llvm::InitializeAllTargetInfos(); @@ -110,15 +123,47 @@ int main() { builder.mod->setDataLayout(TargetMachine->createDataLayout()); builder.mod->setTargetTriple(TargetMachine->getTargetTriple()); - std::string ir_output; - llvm::raw_string_ostream dest{ ir_output }; + std::string llvm_ir_string; + llvm::raw_string_ostream llvm_ir_dest{ llvm_ir_string }; - builder.mod->print(dest, nullptr); - dest.flush(); + builder.mod->print(llvm_ir_dest, nullptr); + llvm_ir_dest.flush(); - std::cout << ir_output << std::endl; + std::error_code EC; + std::string obj_string; + llvm::raw_string_ostream obj_stream{ obj_string }; + llvm::buffer_ostream obj_dest{ obj_stream }; - std::cout << "hello" << std::endl; + if (EC) { + llvm::errs() << "Unable to open file (" << EC.message() << ")"; + return {}; + } + + llvm::legacy::PassManager pass{}; + if (TargetMachine->addPassesToEmitFile(pass, obj_dest, nullptr, llvm::CodeGenFileType::ObjectFile)) { + llvm::errs() << "Target Machine can't emit file"; + return {}; + } + + pass.run(*builder.mod); + obj_string = (std::string_view)obj_dest.str(); + + return CompileOutput{ + llvm_ir_string, + obj_string, + }; +} + +int main() { + + std::string in_filename{ "test.c" }; + std::string out_filename{ "test.o" }; + + auto out = compile(in_filename); + if (out) { + std::cout << out->llvm_ir_string << std::endl; + write_file(out_filename, out->obj_string); + } return 0; } \ No newline at end of file