//go:build byollvm #include #include #include #include #include #include #include #include #include #include #include #include using namespace llvm; using namespace clang; #include "cc1as.h" // This file provides C wrappers for the builtin tools cc1 and cc1as // provided by Clang, and calls them as the driver would call them. extern "C" { bool tinygo_clang_driver(int argc, char **argv) { std::vector args(argv, argv + argc); // The compiler invocation needs a DiagnosticsEngine so it can report problems llvm::IntrusiveRefCntPtr DiagOpts = new clang::DiagnosticOptions(); clang::TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts); clang::DiagnosticsEngine Diags(llvm::IntrusiveRefCntPtr(new clang::DiagnosticIDs()), &*DiagOpts, &DiagnosticPrinter, false); // Create the clang driver clang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), Diags); // Create the set of actions to perform std::unique_ptr C(TheDriver.BuildCompilation(args)); if (!C) { return false; } const clang::driver::JobList &Jobs = C->getJobs(); // There may be more than one job, for example for .S files // (preprocessor + assembler). for (auto Cmd : Jobs) { // Select the tool: cc1 or cc1as. const llvm::opt::ArgStringList &CCArgs = Cmd.getArguments(); if (strcmp(*CCArgs.data(), "-cc1") == 0) { // This is the C frontend. // Initialize a compiler invocation object from the clang (-cc1) arguments. std::unique_ptr Clang(new clang::CompilerInstance()); bool success = clang::CompilerInvocation::CreateFromArgs( Clang->getInvocation(), CCArgs, Diags); if (!success) { return false; } // Create the actual diagnostics engine. Clang->createDiagnostics(); if (!Clang->hasDiagnostics()) { return false; } // Execute the frontend actions. success = ExecuteCompilerInvocation(Clang.get()); if (!success) { return false; } } else if (strcmp(*CCArgs.data(), "-cc1as") == 0) { // This is the assembler frontend. Parse the arguments. AssemblerInvocation Asm; ArrayRef Argv = llvm::ArrayRef(CCArgs); if (!AssemblerInvocation::CreateFromArgs(Asm, Argv.slice(1), Diags)) return false; // Execute the invocation, unless there were parsing errors. bool failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags); if (failed) { return false; } } else { // Unknown tool, print the tool and exit. fprintf(stderr, "unknown tool: %s\n", *CCArgs.data()); return false; } } // Commands executed successfully. return true; } } // extern "C"