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