-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Build out AST consumer patterns to reach the entry point into CIRGen #111732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CIR] Build out AST consumer patterns to reach the entry point into CIRGen #111732
Conversation
Created using spr 1.3.5
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-driver Author: Nathan Lanza (lanza) ChangesBuild out the necessary infrastructure for the main entry point into The main entry point to CIR generation is This patch also re-adds Full diff: https://github.com/llvm/llvm-project/pull/111732.diff 16 Files Affected:
diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h
new file mode 100644
index 00000000000000..9a8930ac46ea9c
--- /dev/null
+++ b/clang/include/clang/CIR/CIRGenerator.h
@@ -0,0 +1,60 @@
+//===- CIRGenerator.h - CIR Generation from Clang AST ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a simple interface to perform CIR generation from Clang
+// AST
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENERATOR_H
+#define LLVM_CLANG_CIR_CIRGENERATOR_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/CodeGenOptions.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <memory>
+
+namespace clang {
+class DeclGroupRef;
+class DiagnosticsEngine;
+} // namespace clang
+
+namespace mlir {
+class MLIRContext;
+} // namespace mlir
+namespace cir {
+class CIRGenModule;
+
+class CIRGenerator : public clang::ASTConsumer {
+ virtual void anchor();
+ clang::DiagnosticsEngine &diags;
+ clang::ASTContext *astCtx;
+ // Only used for debug info.
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs;
+
+ const clang::CodeGenOptions &codeGenOpts;
+
+protected:
+ std::unique_ptr<mlir::MLIRContext> mlirCtx;
+ std::unique_ptr<CIRGenModule> cgm;
+
+public:
+ CIRGenerator(clang::DiagnosticsEngine &diags,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
+ const clang::CodeGenOptions &cgo);
+ ~CIRGenerator() override;
+ void Initialize(clang::ASTContext &astCtx) override;
+ bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
+};
+
+} // namespace cir
+
+#endif // LLVM_CLANG_CIR_CIRGENERATOR_H
diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
new file mode 100644
index 00000000000000..2ab612613b73da
--- /dev/null
+++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
@@ -0,0 +1,60 @@
+//===---- CIRGenAction.h - CIR Code Generation Frontend Action -*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENACTION_H
+#define LLVM_CLANG_CIR_CIRGENACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/OwningOpRef.h"
+
+namespace mlir {
+class MLIRContext;
+class ModuleOp;
+} // namespace mlir
+
+namespace cir {
+class CIRGenConsumer;
+
+class CIRGenAction : public clang::ASTFrontendAction {
+public:
+ enum class OutputType {
+ EmitCIR,
+ };
+
+private:
+ friend class CIRGenConsumer;
+
+ mlir::OwningOpRef<mlir::ModuleOp> MLIRMod;
+
+ mlir::MLIRContext *MLIRCtx;
+
+protected:
+ CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx = nullptr);
+
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &CI,
+ llvm::StringRef InFile) override;
+
+public:
+ ~CIRGenAction() override;
+
+ OutputType Action;
+};
+
+class EmitCIRAction : public CIRGenAction {
+ virtual void anchor();
+
+public:
+ EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr);
+};
+
+} // namespace cir
+
+#endif
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 90f0c4f2df2130..9adc0b15f2ea82 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2996,7 +2996,7 @@ defm clangir : BoolFOption<"clangir",
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">,
BothFlags<[], [ClangOption, CC1Option], "">>;
-def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
+def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">;
/// ClangIR-specific options - END
diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt
index d2ff200e0da5f5..11cca734808dfa 100644
--- a/clang/lib/CIR/CMakeLists.txt
+++ b/clang/lib/CIR/CMakeLists.txt
@@ -2,3 +2,5 @@ include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include)
include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)
add_subdirectory(Dialect)
+add_subdirectory(CodeGen)
+add_subdirectory(FrontendAction)
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
new file mode 100644
index 00000000000000..95e62326939fc2
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -0,0 +1,32 @@
+//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for CIR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenModule.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Location.h"
+#include "mlir/IR/MLIRContext.h"
+
+using namespace cir;
+CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
+ clang::ASTContext &astctx,
+ const clang::CodeGenOptions &cgo,
+ DiagnosticsEngine &diags)
+ : astCtx(astctx), langOpts(astctx.getLangOpts()),
+ theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
+ target(astCtx.getTargetInfo()) {}
+
+// Emit code for a single top level declaration.
+void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
new file mode 100644
index 00000000000000..ab2a1d8864659a
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -0,0 +1,62 @@
+//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for CIR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
+#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
+
+#include "CIRGenTypeCache.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+
+namespace clang {
+class ASTContext;
+class CodeGenOptions;
+class Decl;
+class DiagnosticsEngine;
+class LangOptions;
+class TargetInfo;
+} // namespace clang
+
+using namespace clang;
+namespace cir {
+
+/// This class organizes the cross-function state that is used while generating
+/// CIR code.
+class CIRGenModule : public CIRGenTypeCache {
+ CIRGenModule(CIRGenModule &) = delete;
+ CIRGenModule &operator=(CIRGenModule &) = delete;
+
+public:
+ CIRGenModule(mlir::MLIRContext &context, clang::ASTContext &astctx,
+ const clang::CodeGenOptions &cgo,
+ clang::DiagnosticsEngine &diags);
+
+ ~CIRGenModule() = default;
+
+private:
+ /// Hold Clang AST information.
+ clang::ASTContext &astCtx;
+
+ const clang::LangOptions &langOpts;
+
+ /// A "module" matches a c/cpp source file: containing a list of functions.
+ mlir::ModuleOp theModule;
+
+ const clang::TargetInfo ⌖
+
+public:
+ void buildTopLevelDecl(clang::Decl *decl);
+};
+} // namespace cir
+
+#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
new file mode 100644
index 00000000000000..6478e0a0780994
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -0,0 +1,27 @@
+//===--- CIRGenTypeCache.h - Commonly used LLVM types and info -*- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This structure provides a set of common types useful during CIR emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
+#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
+
+namespace cir {
+
+/// This structure provides a set of types that are commonly used
+/// during IR emission. It's initialized once in CodeGenModule's
+/// constructor and then copied around into new CIRGenFunction's.
+struct CIRGenTypeCache {
+ CIRGenTypeCache() = default;
+};
+
+} // namespace cir
+
+#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTYPECACHE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
new file mode 100644
index 00000000000000..159355a99ece80
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -0,0 +1,43 @@
+//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This builds an AST and converts it to CIR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenModule.h"
+
+#include "clang/AST/DeclGroup.h"
+#include "clang/CIR/CIRGenerator.h"
+
+using namespace cir;
+using namespace clang;
+
+void CIRGenerator::anchor() {}
+
+CIRGenerator::CIRGenerator(clang::DiagnosticsEngine &diags,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
+ const CodeGenOptions &cgo)
+ : diags(diags), fs(std::move(vfs)), codeGenOpts{cgo} {}
+CIRGenerator::~CIRGenerator() = default;
+
+void CIRGenerator::Initialize(ASTContext &astCtx) {
+ using namespace llvm;
+
+ this->astCtx = &astCtx;
+
+ cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
+}
+
+bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
+
+ for (Decl *decl : group)
+ cgm->buildTopLevelDecl(decl);
+
+ return true;
+}
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
new file mode 100644
index 00000000000000..17a3aabfbd7f0e
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(
+ LLVM_LINK_COMPONENTS
+ Core
+ Support
+)
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIR
+ CIRGenerator.cpp
+ CIRGenModule.cpp
+
+ DEPENDS
+ MLIRCIR
+ ${dialect_libs}
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangLex
+ ${dialect_libs}
+ MLIRCIR
+)
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
new file mode 100644
index 00000000000000..72b9fa0c13c595
--- /dev/null
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -0,0 +1,72 @@
+//===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/FrontendAction/CIRGenAction.h"
+#include "clang/CIR/CIRGenerator.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OwningOpRef.h"
+
+using namespace cir;
+using namespace clang;
+
+namespace cir {
+
+class CIRGenConsumer : public clang::ASTConsumer {
+
+ virtual void anchor();
+
+ std::unique_ptr<raw_pwrite_stream> OutputStream;
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
+ std::unique_ptr<CIRGenerator> Gen;
+
+public:
+ CIRGenConsumer(CIRGenAction::OutputType Action,
+ DiagnosticsEngine &DiagnosticsEngine,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const HeaderSearchOptions &HeaderSearchOptions,
+ const CodeGenOptions &CodeGenOptions,
+ const TargetOptions &TargetOptions,
+ const LangOptions &LangOptions,
+ const FrontendOptions &FEOptions,
+ std::unique_ptr<raw_pwrite_stream> OS)
+ : OutputStream(std::move(OS)), FS(VFS),
+ Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS),
+ CodeGenOptions)) {}
+
+ bool HandleTopLevelDecl(DeclGroupRef D) override {
+ Gen->HandleTopLevelDecl(D);
+ return true;
+ }
+};
+} // namespace cir
+
+void CIRGenConsumer::anchor() {}
+
+CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
+ : MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {}
+
+CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
+
+std::unique_ptr<ASTConsumer>
+CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();
+
+ auto Result = std::make_unique<cir::CIRGenConsumer>(
+ Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
+ CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
+ CI.getLangOpts(), CI.getFrontendOpts(), std::move(Out));
+
+ return Result;
+}
+
+void EmitCIRAction::anchor() {}
+EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
+ : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
new file mode 100644
index 00000000000000..b0616ab5d64b09
--- /dev/null
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ Support
+ )
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIRFrontendAction
+ CIRGenAction.cpp
+
+ LINK_LIBS
+ clangAST
+ clangFrontend
+ clangCIR
+ MLIRCIR
+ MLIRIR
+ )
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 5b09f97c40b485..49b07322a21a52 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5139,6 +5139,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (Args.hasArg(options::OPT_fclangir))
+ CmdArgs.push_back("-fclangir");
+
if (IsOpenMPDevice) {
// We have to pass the triple of the host if compiling for an OpenMP device.
std::string NormalizedTriple =
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 51c379ade2704c..bfc7652b4c118f 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -12,6 +12,15 @@ set(link_libs
clangRewriteFrontend
)
+set(deps)
+
+if(CLANG_ENABLE_CIR)
+ list(APPEND link_libs
+ clangCIRFrontendAction
+ MLIRIR
+ )
+endif()
+
if(CLANG_ENABLE_ARCMT)
list(APPEND link_libs
clangARCMigrate
@@ -29,7 +38,13 @@ add_clang_library(clangFrontendTool
DEPENDS
ClangDriverOptions
+ ${deps}
LINK_LIBS
${link_libs}
)
+
+if(CLANG_ENABLE_CIR)
+ target_include_directories(clangFrontendTool PRIVATE ${LLVM_MAIN_SRC_DIR}/../mlir/include)
+ target_include_directories(clangFrontendTool PRIVATE ${CMAKE_BINARY_DIR}/tools/mlir/include)
+endif()
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 7476b1076d1038..60fde03289cf35 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -31,6 +31,11 @@
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
+
+#if CLANG_ENABLE_CIR
+#include "clang/CIR/FrontendAction/CIRGenAction.h"
+#endif
+
using namespace clang;
using namespace llvm::opt;
@@ -42,6 +47,13 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
StringRef Action("unknown");
(void)Action;
+ unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline;
+ frontend::ActionKind Act = CI.getFrontendOpts().ProgramAction;
+ bool EmitsCIR = Act == EmitCIR;
+
+ if (!UseCIR && EmitsCIR)
+ llvm::report_fatal_error("-emit-cir and only valid when using -fclangir");
+
switch (CI.getFrontendOpts().ProgramAction) {
case ASTDeclList: return std::make_unique<ASTDeclListAction>();
case ASTDump: return std::make_unique<ASTDumpAction>();
@@ -54,7 +66,11 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case EmitAssembly: return std::make_unique<EmitAssemblyAction>();
case EmitBC: return std::make_unique<EmitBCAction>();
case EmitCIR:
+#if CLANG_ENABLE_CIR
+ return std::make_unique<::cir::EmitCIRAction>();
+#else
llvm_unreachable("CIR suppport not built into clang");
+#endif
case EmitHTML: return std::make_unique<HTMLPrintAction>();
case EmitLLVM: return std::make_unique<EmitLLVMAction>();
case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
diff --git a/clang/test/CIR/hello.c b/clang/test/CIR/hello.c
new file mode 100644
index 00000000000000..61f38d0a5bd01a
--- /dev/null
+++ b/clang/test/CIR/hello.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s | FileCheck --allow-empty %s
+
+// just confirm that we don't crash
+// CHECK-NOT: *
+void foo() {}
diff --git a/clang/test/CIR/lit.local.cfg b/clang/test/CIR/lit.local.cfg
new file mode 100644
index 00000000000000..6afd60f47bff90
--- /dev/null
+++ b/clang/test/CIR/lit.local.cfg
@@ -0,0 +1,2 @@
+if not config.root.clang_enable_cir:
+ config.unsupported = True
|
|
@llvm/pr-subscribers-clangir Author: Nathan Lanza (lanza) ChangesBuild out the necessary infrastructure for the main entry point into The main entry point to CIR generation is This patch also re-adds Full diff: https://github.com/llvm/llvm-project/pull/111732.diff 16 Files Affected:
diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h
new file mode 100644
index 00000000000000..9a8930ac46ea9c
--- /dev/null
+++ b/clang/include/clang/CIR/CIRGenerator.h
@@ -0,0 +1,60 @@
+//===- CIRGenerator.h - CIR Generation from Clang AST ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a simple interface to perform CIR generation from Clang
+// AST
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENERATOR_H
+#define LLVM_CLANG_CIR_CIRGENERATOR_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/CodeGenOptions.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <memory>
+
+namespace clang {
+class DeclGroupRef;
+class DiagnosticsEngine;
+} // namespace clang
+
+namespace mlir {
+class MLIRContext;
+} // namespace mlir
+namespace cir {
+class CIRGenModule;
+
+class CIRGenerator : public clang::ASTConsumer {
+ virtual void anchor();
+ clang::DiagnosticsEngine &diags;
+ clang::ASTContext *astCtx;
+ // Only used for debug info.
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs;
+
+ const clang::CodeGenOptions &codeGenOpts;
+
+protected:
+ std::unique_ptr<mlir::MLIRContext> mlirCtx;
+ std::unique_ptr<CIRGenModule> cgm;
+
+public:
+ CIRGenerator(clang::DiagnosticsEngine &diags,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
+ const clang::CodeGenOptions &cgo);
+ ~CIRGenerator() override;
+ void Initialize(clang::ASTContext &astCtx) override;
+ bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
+};
+
+} // namespace cir
+
+#endif // LLVM_CLANG_CIR_CIRGENERATOR_H
diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
new file mode 100644
index 00000000000000..2ab612613b73da
--- /dev/null
+++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
@@ -0,0 +1,60 @@
+//===---- CIRGenAction.h - CIR Code Generation Frontend Action -*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENACTION_H
+#define LLVM_CLANG_CIR_CIRGENACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/OwningOpRef.h"
+
+namespace mlir {
+class MLIRContext;
+class ModuleOp;
+} // namespace mlir
+
+namespace cir {
+class CIRGenConsumer;
+
+class CIRGenAction : public clang::ASTFrontendAction {
+public:
+ enum class OutputType {
+ EmitCIR,
+ };
+
+private:
+ friend class CIRGenConsumer;
+
+ mlir::OwningOpRef<mlir::ModuleOp> MLIRMod;
+
+ mlir::MLIRContext *MLIRCtx;
+
+protected:
+ CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx = nullptr);
+
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &CI,
+ llvm::StringRef InFile) override;
+
+public:
+ ~CIRGenAction() override;
+
+ OutputType Action;
+};
+
+class EmitCIRAction : public CIRGenAction {
+ virtual void anchor();
+
+public:
+ EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr);
+};
+
+} // namespace cir
+
+#endif
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 90f0c4f2df2130..9adc0b15f2ea82 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2996,7 +2996,7 @@ defm clangir : BoolFOption<"clangir",
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">,
BothFlags<[], [ClangOption, CC1Option], "">>;
-def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
+def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">;
/// ClangIR-specific options - END
diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt
index d2ff200e0da5f5..11cca734808dfa 100644
--- a/clang/lib/CIR/CMakeLists.txt
+++ b/clang/lib/CIR/CMakeLists.txt
@@ -2,3 +2,5 @@ include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include)
include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)
add_subdirectory(Dialect)
+add_subdirectory(CodeGen)
+add_subdirectory(FrontendAction)
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
new file mode 100644
index 00000000000000..95e62326939fc2
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -0,0 +1,32 @@
+//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for CIR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenModule.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Location.h"
+#include "mlir/IR/MLIRContext.h"
+
+using namespace cir;
+CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
+ clang::ASTContext &astctx,
+ const clang::CodeGenOptions &cgo,
+ DiagnosticsEngine &diags)
+ : astCtx(astctx), langOpts(astctx.getLangOpts()),
+ theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
+ target(astCtx.getTargetInfo()) {}
+
+// Emit code for a single top level declaration.
+void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
new file mode 100644
index 00000000000000..ab2a1d8864659a
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -0,0 +1,62 @@
+//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for CIR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
+#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
+
+#include "CIRGenTypeCache.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+
+namespace clang {
+class ASTContext;
+class CodeGenOptions;
+class Decl;
+class DiagnosticsEngine;
+class LangOptions;
+class TargetInfo;
+} // namespace clang
+
+using namespace clang;
+namespace cir {
+
+/// This class organizes the cross-function state that is used while generating
+/// CIR code.
+class CIRGenModule : public CIRGenTypeCache {
+ CIRGenModule(CIRGenModule &) = delete;
+ CIRGenModule &operator=(CIRGenModule &) = delete;
+
+public:
+ CIRGenModule(mlir::MLIRContext &context, clang::ASTContext &astctx,
+ const clang::CodeGenOptions &cgo,
+ clang::DiagnosticsEngine &diags);
+
+ ~CIRGenModule() = default;
+
+private:
+ /// Hold Clang AST information.
+ clang::ASTContext &astCtx;
+
+ const clang::LangOptions &langOpts;
+
+ /// A "module" matches a c/cpp source file: containing a list of functions.
+ mlir::ModuleOp theModule;
+
+ const clang::TargetInfo ⌖
+
+public:
+ void buildTopLevelDecl(clang::Decl *decl);
+};
+} // namespace cir
+
+#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
new file mode 100644
index 00000000000000..6478e0a0780994
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -0,0 +1,27 @@
+//===--- CIRGenTypeCache.h - Commonly used LLVM types and info -*- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This structure provides a set of common types useful during CIR emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
+#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
+
+namespace cir {
+
+/// This structure provides a set of types that are commonly used
+/// during IR emission. It's initialized once in CodeGenModule's
+/// constructor and then copied around into new CIRGenFunction's.
+struct CIRGenTypeCache {
+ CIRGenTypeCache() = default;
+};
+
+} // namespace cir
+
+#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTYPECACHE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
new file mode 100644
index 00000000000000..159355a99ece80
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -0,0 +1,43 @@
+//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This builds an AST and converts it to CIR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenModule.h"
+
+#include "clang/AST/DeclGroup.h"
+#include "clang/CIR/CIRGenerator.h"
+
+using namespace cir;
+using namespace clang;
+
+void CIRGenerator::anchor() {}
+
+CIRGenerator::CIRGenerator(clang::DiagnosticsEngine &diags,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
+ const CodeGenOptions &cgo)
+ : diags(diags), fs(std::move(vfs)), codeGenOpts{cgo} {}
+CIRGenerator::~CIRGenerator() = default;
+
+void CIRGenerator::Initialize(ASTContext &astCtx) {
+ using namespace llvm;
+
+ this->astCtx = &astCtx;
+
+ cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
+}
+
+bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
+
+ for (Decl *decl : group)
+ cgm->buildTopLevelDecl(decl);
+
+ return true;
+}
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
new file mode 100644
index 00000000000000..17a3aabfbd7f0e
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(
+ LLVM_LINK_COMPONENTS
+ Core
+ Support
+)
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIR
+ CIRGenerator.cpp
+ CIRGenModule.cpp
+
+ DEPENDS
+ MLIRCIR
+ ${dialect_libs}
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangLex
+ ${dialect_libs}
+ MLIRCIR
+)
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
new file mode 100644
index 00000000000000..72b9fa0c13c595
--- /dev/null
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -0,0 +1,72 @@
+//===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/FrontendAction/CIRGenAction.h"
+#include "clang/CIR/CIRGenerator.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OwningOpRef.h"
+
+using namespace cir;
+using namespace clang;
+
+namespace cir {
+
+class CIRGenConsumer : public clang::ASTConsumer {
+
+ virtual void anchor();
+
+ std::unique_ptr<raw_pwrite_stream> OutputStream;
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
+ std::unique_ptr<CIRGenerator> Gen;
+
+public:
+ CIRGenConsumer(CIRGenAction::OutputType Action,
+ DiagnosticsEngine &DiagnosticsEngine,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const HeaderSearchOptions &HeaderSearchOptions,
+ const CodeGenOptions &CodeGenOptions,
+ const TargetOptions &TargetOptions,
+ const LangOptions &LangOptions,
+ const FrontendOptions &FEOptions,
+ std::unique_ptr<raw_pwrite_stream> OS)
+ : OutputStream(std::move(OS)), FS(VFS),
+ Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS),
+ CodeGenOptions)) {}
+
+ bool HandleTopLevelDecl(DeclGroupRef D) override {
+ Gen->HandleTopLevelDecl(D);
+ return true;
+ }
+};
+} // namespace cir
+
+void CIRGenConsumer::anchor() {}
+
+CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
+ : MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {}
+
+CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
+
+std::unique_ptr<ASTConsumer>
+CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();
+
+ auto Result = std::make_unique<cir::CIRGenConsumer>(
+ Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
+ CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
+ CI.getLangOpts(), CI.getFrontendOpts(), std::move(Out));
+
+ return Result;
+}
+
+void EmitCIRAction::anchor() {}
+EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
+ : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
new file mode 100644
index 00000000000000..b0616ab5d64b09
--- /dev/null
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ Support
+ )
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIRFrontendAction
+ CIRGenAction.cpp
+
+ LINK_LIBS
+ clangAST
+ clangFrontend
+ clangCIR
+ MLIRCIR
+ MLIRIR
+ )
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 5b09f97c40b485..49b07322a21a52 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5139,6 +5139,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (Args.hasArg(options::OPT_fclangir))
+ CmdArgs.push_back("-fclangir");
+
if (IsOpenMPDevice) {
// We have to pass the triple of the host if compiling for an OpenMP device.
std::string NormalizedTriple =
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 51c379ade2704c..bfc7652b4c118f 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -12,6 +12,15 @@ set(link_libs
clangRewriteFrontend
)
+set(deps)
+
+if(CLANG_ENABLE_CIR)
+ list(APPEND link_libs
+ clangCIRFrontendAction
+ MLIRIR
+ )
+endif()
+
if(CLANG_ENABLE_ARCMT)
list(APPEND link_libs
clangARCMigrate
@@ -29,7 +38,13 @@ add_clang_library(clangFrontendTool
DEPENDS
ClangDriverOptions
+ ${deps}
LINK_LIBS
${link_libs}
)
+
+if(CLANG_ENABLE_CIR)
+ target_include_directories(clangFrontendTool PRIVATE ${LLVM_MAIN_SRC_DIR}/../mlir/include)
+ target_include_directories(clangFrontendTool PRIVATE ${CMAKE_BINARY_DIR}/tools/mlir/include)
+endif()
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 7476b1076d1038..60fde03289cf35 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -31,6 +31,11 @@
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
+
+#if CLANG_ENABLE_CIR
+#include "clang/CIR/FrontendAction/CIRGenAction.h"
+#endif
+
using namespace clang;
using namespace llvm::opt;
@@ -42,6 +47,13 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
StringRef Action("unknown");
(void)Action;
+ unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline;
+ frontend::ActionKind Act = CI.getFrontendOpts().ProgramAction;
+ bool EmitsCIR = Act == EmitCIR;
+
+ if (!UseCIR && EmitsCIR)
+ llvm::report_fatal_error("-emit-cir and only valid when using -fclangir");
+
switch (CI.getFrontendOpts().ProgramAction) {
case ASTDeclList: return std::make_unique<ASTDeclListAction>();
case ASTDump: return std::make_unique<ASTDumpAction>();
@@ -54,7 +66,11 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case EmitAssembly: return std::make_unique<EmitAssemblyAction>();
case EmitBC: return std::make_unique<EmitBCAction>();
case EmitCIR:
+#if CLANG_ENABLE_CIR
+ return std::make_unique<::cir::EmitCIRAction>();
+#else
llvm_unreachable("CIR suppport not built into clang");
+#endif
case EmitHTML: return std::make_unique<HTMLPrintAction>();
case EmitLLVM: return std::make_unique<EmitLLVMAction>();
case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
diff --git a/clang/test/CIR/hello.c b/clang/test/CIR/hello.c
new file mode 100644
index 00000000000000..61f38d0a5bd01a
--- /dev/null
+++ b/clang/test/CIR/hello.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s | FileCheck --allow-empty %s
+
+// just confirm that we don't crash
+// CHECK-NOT: *
+void foo() {}
diff --git a/clang/test/CIR/lit.local.cfg b/clang/test/CIR/lit.local.cfg
new file mode 100644
index 00000000000000..6afd60f47bff90
--- /dev/null
+++ b/clang/test/CIR/lit.local.cfg
@@ -0,0 +1,2 @@
+if not config.root.clang_enable_cir:
+ config.unsupported = True
|
Build out the necessary infrastructure for the main entry point into
ClangIR generation -- CIRGenModule. A set of boilerplate classes exist
to facilitate this -- CIRGenerator, CIRGenAction, EmitCIRAction and
CIRGenConsumer. These all mirror the corresponding types from LLVM
generation by Clang's CodeGen.
The main entry point to CIR generation is
CIRGenModule::buildTopLevelDecl. It is currently just an emptyfunction. We've added a test to ensure that the pipeline reaches this
point and doesn't fail, but does nothing else. This will be removed in
one of the subsequent patches that'll add basic
cir.funcemission.This patch also re-adds
-emit-cirto the driver. lib/Driver/Driver.cpprequires that a driver flag exists to facilirate the selection of the
right actions for the driver to create. Without a driver flag you get
the standard behaviors of
-S,-c, etc. If we want to emit CIR IRand, eventually, bytecode we'll need a driver flag to force this. This
is why
-emit-llvmis a driver flag. Notably,-emit-llvm-bcas a cc1flag doesn't ever do the right thing. Without a driver flag it is
incorrectly ignored and an executable is emitted. With
-Sa file namedsomething.sis emitted which actually contains bitcode.