diff --git a/CMakeLists.txt b/CMakeLists.txt index ba4c67a..d42dc14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,20 +5,6 @@ project(movForth) set(CMAKE_CXX_STANDARD 17) - -find_package(LLVM REQUIRED CONFIG) - -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") -message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - -# Set your project compile flags. -# E.g. if using the C++ header files -# you will need to enable C++11 support -# for your compiler. - -include_directories(${LLVM_INCLUDE_DIRS}) -add_definitions(${LLVM_DEFINITIONS}) - # Now build our tools add_executable(movForth @@ -42,16 +28,61 @@ add_executable(movForth sources/Generation/IRGenerator.cpp sources/Generation/FBuilder.cpp + sources/Generation/ObjectGenerator.cpp -# DirtyPass/Inliner.cpp -# DirtyPass/IPO.h -# DirtyPass/InlineSimple.cpp -# DirtyPass/LegacyPassManager.cpp + # DirtyPass/Inliner.cpp + # DirtyPass/IPO.h + # DirtyPass/InlineSimple.cpp + # DirtyPass/LegacyPassManager.cpp ) + +SET(LLVM13 "/home/reschivon/Hard-Drive/clang+llvm-12.0.1-x86_64-linux-gnu-ubuntu-") +# add_library(LLVM "${LLVM13}") +find_package(LLVM REQUIRED CONFIG PATHS) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +# Set your project compile flags. +# E.g. if using the C++ header files +# you will need to enable C++11 support +# for your compiler. + +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) + # Find the libraries that correspond to the LLVM components # that we wish to use -llvm_map_components_to_libnames(llvm_libs support core irreader native passes) +llvm_map_components_to_libnames(llvm_libs + # support core irreader native passes codegen + aarch64asmparser aarch64asmprinter aarch64codegen aarch64desc aarch64disassembler aarch64info + aarch64utils amdgpuasmparser amdgpuasmprinter amdgpucodegen amdgpudesc + amdgpudisassembler amdgpuinfo amdgpuutils analysis armasmparser armasmprinter armcodegen armdesc + armdisassembler arminfo armutils asmparser asmprinter avrasmparser avrasmprinter avrcodegen avrdesc + avrdisassembler avrinfo binaryformat bitreader bitwriter bpfasmparser bpfasmprinter bpfcodegen + bpfdesc bpfdisassembler bpfinfo codegen core coroutines coverage debuginfocodeview debuginfodwarf + + # executionengine engine + + debuginfomsf debuginfopdb demangle dlltooldriver fuzzmutate globalisel + hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation + interpreter ipo irreader lanaiasmparser lanaiasmprinter lanaicodegen lanaidesc lanaidisassembler + lanaiinfo libdriver lineeditor linker lto mc mcdisassembler mcjit mcparser mipsasmparser mipsasmprinter + mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430asmprinter msp430codegen msp430desc + msp430info native nativecodegen nvptxasmprinter nvptxcodegen nvptxdesc nvptxinfo objcarcopts object + objectyaml option orcjit passes powerpcasmparser powerpcasmprinter powerpccodegen powerpcdesc + powerpcdisassembler powerpcinfo profiledata runtimedyld scalaropts selectiondag sparcasmparser + sparcasmprinter sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize + systemzasmparser systemzasmprinter systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen + target transformutils vectorize webassemblyasmprinter webassemblycodegen webassemblydesc + webassemblydisassembler webassemblyinfo windowsmanifest x86asmparser x86asmprinter x86codegen x86desc + x86disassembler x86info x86utils xcoreasmprinter xcorecodegen xcoredesc xcoredisassembler xcoreinfo + + # all-targets +) + +# execute_process(COMMAND llvm-config --libs all OUTPUT_VARIABLE llvm_libraries) # Link against LLVM libraries message(STATUS "Linking LLVM libraries ${llvm_libs}") diff --git a/headers/Generation/ObjectGenerator.h b/headers/Generation/ObjectGenerator.h new file mode 100644 index 0000000..7013056 --- /dev/null +++ b/headers/Generation/ObjectGenerator.h @@ -0,0 +1,16 @@ + +#ifndef MOVFORTH_OBJECTGENERATOR_H +#define MOVFORTH_OBJECTGENERATOR_H + +#include + +using namespace llvm; +namespace mov { + class ObjectGenerator { + public: + static void generate(const std::string &filename, Module &module); + static void link(const std::string &assembly_name, const std::string &executable_name); + }; +} + +#endif //MOVFORTH_OBJECTGENERATOR_H diff --git a/main.cpp b/main.cpp index 7b147b5..ba85a96 100644 --- a/main.cpp +++ b/main.cpp @@ -2,7 +2,7 @@ #include "headers/Interpretation/Interpreter.h" #include "headers/Symbolic/Pass.h" #include "headers/Generation/IRGenerator.h" - +#include "headers/Generation/ObjectGenerator.h" int main() { @@ -38,5 +38,12 @@ int main() { ir_generator.exec_module(); + mov::ObjectGenerator::generate("../Out.S", *module); + + // Link the assembly file provided + // Note: invokes `clang++` command in a new shell instance + // May not work on every system + mov::ObjectGenerator::link("../Out.S", "LinkedOut"); + } diff --git a/sources/Generation/IRGenerator.cpp b/sources/Generation/IRGenerator.cpp index 397f5fb..51a5495 100644 --- a/sources/Generation/IRGenerator.cpp +++ b/sources/Generation/IRGenerator.cpp @@ -43,14 +43,17 @@ IRGenerator::IRGenerator() // fpm->add(createPartiallyInlineLibCallsPass()); //Inline standard calls // fpm->add(createDeadCodeEliminationPass()); // fpm->add(createCFGSimplificationPass()); //Cleanup -// fpm->add(createInstructionCombiningPass()); + +// merge successive `icmp %x, 0` which can happen becasue branchif compiles +// an icmp, which must be undone by another icmp + fpm->add(createInstructionCombiningPass()); // fpm->add(createFlattenCFGPass()); //Flatten the control flow graph. // constant folding pass -// fpm->add(createSROAPass()); -// fpm->add(createConstantPropagationPass()); -// fpm->add(createReassociatePass()); -// fpm->add(createCFGSimplificationPass()); + fpm->add(createSROAPass()); + fpm->add(createConstantPropagationPass()); + fpm->add(createReassociatePass()); + fpm->add(createCFGSimplificationPass()); fpm->doInitialization(); diff --git a/sources/Generation/ObjectGenerator.cpp b/sources/Generation/ObjectGenerator.cpp new file mode 100644 index 0000000..485b66d --- /dev/null +++ b/sources/Generation/ObjectGenerator.cpp @@ -0,0 +1,75 @@ + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetMachine.h" + + +#include "../../headers/Generation/ObjectGenerator.h" +#include "../../DirtyPass/LegacyPassManager.h" +#include "../../headers/SystemExec.h" +#include "../../headers/Print.h" + +using namespace mov; +using namespace llvm; + +void ObjectGenerator::generate(const std::string &filename, Module &module) { + auto TargetTriple = sys::getDefaultTargetTriple(); + + InitializeAllTargetInfos(); + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmParsers(); + InitializeAllAsmPrinters(); + + std::string Error; + auto Target = TargetRegistry::lookupTarget(TargetTriple, Error); + + // Print an error and exit if we couldn't find the requested target. + // This generally occurs if we've forgotten to initialise the + // TargetRegistry or we have a bogus target triple. + if (!Target) { + errs() << Error; + return; + } + + auto CPU = "generic"; + auto Features = ""; + + TargetOptions opt; + auto RM = Optional(); + auto TargetMachine = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); + + module.setDataLayout(TargetMachine->createDataLayout()); + module.setTargetTriple(TargetTriple); + + std::error_code EC; + raw_fd_ostream dest(filename, EC, sys::fs::OpenFlags::F_None); + + if (EC) { + errs() << "Could not open file: " << EC.message(); + return; + } + + legacy::PassManager pass; + // auto FileType = TargetMachine::CGFT_ObjectFile; + auto FileType = TargetMachine::CGFT_AssemblyFile; + + if (TargetMachine->addPassesToEmitFile(pass, dest, FileType)) { + errs() << "TargetMachine can't emit a file of this type"; + return; + } + + pass.run(module); + dest.flush(); +} + +void ObjectGenerator::link(const std::string &assembly_name, const std::string &executable_name) { + println(); + println("==========[Linking]==========="); + auto command = "clang++ " + assembly_name + " -stdlib=libstdc++ -o " + executable_name; + println(exec(command.c_str())); + println("Linked to libstdc++"); + +}