clang.cpp raw
1 //go:build byollvm
2
3 #include <llvm/Config/llvm-config.h>
4 #include <clang/Basic/DiagnosticOptions.h>
5 #include <clang/CodeGen/CodeGenAction.h>
6 #include <clang/Driver/Compilation.h>
7 #include <clang/Driver/Driver.h>
8 #include <clang/Frontend/CompilerInstance.h>
9 #include <clang/Frontend/CompilerInvocation.h>
10 #include <clang/Frontend/FrontendDiagnostic.h>
11 #include <clang/Frontend/TextDiagnosticPrinter.h>
12 #include <clang/FrontendTool/Utils.h>
13 #include <llvm/ADT/IntrusiveRefCntPtr.h>
14 #include <llvm/Option/Option.h>
15 #include <llvm/TargetParser/Host.h>
16
17 using namespace llvm;
18 using namespace clang;
19
20 #include "cc1as.h"
21
22 // This file provides C wrappers for the builtin tools cc1 and cc1as
23 // provided by Clang, and calls them as the driver would call them.
24
25 extern "C" {
26
27 bool moxie_clang_driver(int argc, char **argv) {
28 std::vector<const char*> args(argv, argv + argc);
29
30 // The compiler invocation needs a DiagnosticsEngine so it can report problems
31 llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions();
32 clang::TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
33 clang::DiagnosticsEngine Diags(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()), &*DiagOpts, &DiagnosticPrinter, false);
34
35 // Create the clang driver
36 clang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), Diags);
37
38 // Create the set of actions to perform
39 std::unique_ptr<clang::driver::Compilation> C(TheDriver.BuildCompilation(args));
40 if (!C) {
41 return false;
42 }
43 const clang::driver::JobList &Jobs = C->getJobs();
44
45 // There may be more than one job, for example for .S files
46 // (preprocessor + assembler).
47 for (auto Cmd : Jobs) {
48 // Select the tool: cc1 or cc1as.
49 const llvm::opt::ArgStringList &CCArgs = Cmd.getArguments();
50
51 if (strcmp(*CCArgs.data(), "-cc1") == 0) {
52 // This is the C frontend.
53 // Initialize a compiler invocation object from the clang (-cc1) arguments.
54 std::unique_ptr<clang::CompilerInstance> Clang(new clang::CompilerInstance());
55 bool success = clang::CompilerInvocation::CreateFromArgs(
56 Clang->getInvocation(),
57 CCArgs,
58 Diags);
59 if (!success) {
60 return false;
61 }
62
63 // Create the actual diagnostics engine.
64 #if LLVM_VERSION_MAJOR >= 20
65 Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
66 #else
67 Clang->createDiagnostics();
68 #endif
69 if (!Clang->hasDiagnostics()) {
70 return false;
71 }
72
73 // Execute the frontend actions.
74 success = ExecuteCompilerInvocation(Clang.get());
75 if (!success) {
76 return false;
77 }
78
79 } else if (strcmp(*CCArgs.data(), "-cc1as") == 0) {
80 // This is the assembler frontend. Parse the arguments.
81 AssemblerInvocation Asm;
82 ArrayRef<const char *> Argv = llvm::ArrayRef<const char*>(CCArgs);
83 if (!AssemblerInvocation::CreateFromArgs(Asm, Argv.slice(1), Diags))
84 return false;
85
86 // Execute the invocation, unless there were parsing errors.
87 bool failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
88 if (failed) {
89 return false;
90 }
91
92 } else {
93 // Unknown tool, print the tool and exit.
94 fprintf(stderr, "unknown tool: %s\n", *CCArgs.data());
95 return false;
96 }
97 }
98
99 // Commands executed successfully.
100 return true;
101 }
102
103 } // extern "C"
104