// Copyright 2017 the Monicelli project authors. All rights reserved. // Use of this source code is governed by a GPLv3 license, see LICENSE.txt. #include "asmgen.h" #include "ast-printer.h" #include "codegen.h" #include "options.h" #include "parser.h" #include "llvm/Support/Host.h" #include #include #include using namespace pacciani; int main(int argc, char** argv) { ProgramOptions options = ProgramOptions::fromCommandLine(argc, argv); if (options.input_filenames_empty()) { std::cerr << "No input files.\n"; return 0; } if (options.shouldOnlyCompile() && options.input_filenames_size() > 1 && !options.getOutputFilename().empty()) { std::cerr << "Output filename in compile mode may be specified only with a " "single input file.\n"; return 1; } registerTargets(); auto triple = llvm::sys::getDefaultTargetTriple(); auto target_machine = getTargetMachine(triple, options.getCPU(), options.getCPUFeatures(), options.shouldEmitPIC()); #ifdef PACCIANI_ENABLE_LINKER std::vector object_filenames; object_filenames.reserve(options.input_filenames_size()); #endif for (const auto& input_filename : options.input_filenames()) { std::ifstream input{input_filename}; if (!input) { std::cerr << "Cannot open input file " << input_filename << ".\n"; return 1; } Parser parser{input, input_filename}; parser.setLexerTrace(options.shouldTraceLexer()); auto ast = parser.parse(); if (options.shouldPrintAST()) { printAst(std::cout, ast.get()); continue; } llvm::LLVMContext context; auto ir = generateIR(context, ast.get()); ir->setTargetTriple(triple); ir->setDataLayout(target_machine->createDataLayout()); runFunctionOptimizer(ir.get()); if (options.shouldPrintIR()) { printIR(std::cout, ir.get()); continue; } if (options.shouldSkipCompilation()) continue; std::string object_filename; if (options.shouldOnlyCompile() && !options.getOutputFilename().empty()) { object_filename = options.getOutputFilename(); } else { object_filename = basename(input_filename) + ".o"; } writeAssembly(object_filename, ir.get(), target_machine); #ifdef PACCIANI_ENABLE_LINKER object_filenames.emplace_back(std::move(object_filename)); #endif } #ifdef PACCIANI_ENABLE_LINKER if (!options.shouldSkipCompilation() && !options.shouldOnlyCompile() && !object_filenames.empty()) { linkAssembly(options.getOutputFilename(), object_filenames); } #endif }