aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Driver/Options.td4
-rw-r--r--flang/include/flang/Frontend/FrontendActions.h4
-rw-r--r--flang/include/flang/Frontend/FrontendOptions.h3
-rw-r--r--flang/lib/Frontend/CMakeLists.txt1
-rw-r--r--flang/lib/Frontend/CompilerInvocation.cpp3
-rw-r--r--flang/lib/Frontend/FrontendActions.cpp43
-rw-r--r--flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp2
-rw-r--r--flang/test/CMakeLists.txt1
-rw-r--r--flang/test/Driver/driver-help.f901
-rw-r--r--flang/test/Driver/emit-llvm-bc.f9019
10 files changed, 79 insertions, 2 deletions
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 9ffc79a..483f0cc 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5678,8 +5678,6 @@ def emit_header_unit : Flag<["-"], "emit-header-unit">,
HelpText<"Generate C++20 header units from header files">;
def emit_pch : Flag<["-"], "emit-pch">,
HelpText<"Generate pre-compiled header file">;
-def emit_llvm_bc : Flag<["-"], "emit-llvm-bc">,
- HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
def emit_llvm_only : Flag<["-"], "emit-llvm-only">,
HelpText<"Build ASTs and convert to LLVM, discarding output">;
def emit_codegen_only : Flag<["-"], "emit-codegen-only">,
@@ -6143,6 +6141,8 @@ def emit_obj : Flag<["-"], "emit-obj">,
HelpText<"Emit native object files">;
def init_only : Flag<["-"], "init-only">,
HelpText<"Only execute frontend initialization">;
+def emit_llvm_bc : Flag<["-"], "emit-llvm-bc">,
+ HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
} // let Group = Action_Group
diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 34cabea..48836c6 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -192,6 +192,10 @@ class EmitLLVMAction : public CodeGenAction {
void ExecuteAction() override;
};
+class EmitLLVMBitcodeAction : public CodeGenAction {
+ void ExecuteAction() override;
+};
+
class BackendAction : public CodeGenAction {
public:
enum class BackendActionTy {
diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index 5d97580..d0459e4b 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -37,6 +37,9 @@ enum ActionKind {
/// Emit an .ll file
EmitLLVM,
+ /// Emit a .bc file
+ EmitLLVMBitcode,
+
/// Emit a .o file.
EmitObj,
diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index d6520e7..45692a5 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -32,6 +32,7 @@ add_flang_library(flangFrontend
FIRBuilder
FIRCodeGen
FIRTransforms
+ LLVMPasses
MLIRTransforms
MLIRLLVMToLLVMIRTranslation
MLIRSCFToControlFlow
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index d1f427a..ea5accd7 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -148,6 +148,9 @@ static bool ParseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
case clang::driver::options::OPT_emit_llvm:
opts.programAction = EmitLLVM;
break;
+ case clang::driver::options::OPT_emit_llvm_bc:
+ opts.programAction = EmitLLVMBitcode;
+ break;
case clang::driver::options::OPT_emit_obj:
opts.programAction = EmitObj;
break;
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index e30f6af..e93781e 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -33,6 +33,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
@@ -472,6 +473,48 @@ void EmitLLVMAction::ExecuteAction() {
llvmModule->print(*os, /*AssemblyAnnotationWriter=*/nullptr);
}
+void EmitLLVMBitcodeAction::ExecuteAction() {
+ CompilerInstance &ci = this->instance();
+ // Generate an LLVM module if it's not already present (it will already be
+ // present if the input file is an LLVM IR/BC file).
+ if (!llvmModule)
+ GenerateLLVMIR();
+
+ // Create and configure `Target`
+ std::string error;
+ std::string theTriple = llvmModule->getTargetTriple();
+ const llvm::Target *theTarget =
+ llvm::TargetRegistry::lookupTarget(theTriple, error);
+ assert(theTarget && "Failed to create Target");
+
+ // Create and configure `TargetMachine`
+ std::unique_ptr<llvm::TargetMachine> TM(
+ theTarget->createTargetMachine(theTriple, /*CPU=*/"",
+ /*Features=*/"", llvm::TargetOptions(), llvm::None));
+ assert(TM && "Failed to create TargetMachine");
+ llvmModule->setDataLayout(TM->createDataLayout());
+
+ // Generate an output file
+ std::unique_ptr<llvm::raw_ostream> os = ci.CreateDefaultOutputFile(
+ /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "bc");
+ if (!os) {
+ unsigned diagID = ci.diagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "failed to create the output file");
+ ci.diagnostics().Report(diagID);
+ return;
+ }
+
+ // Set-up the pass manager
+ llvm::ModulePassManager MPM;
+ llvm::ModuleAnalysisManager MAM;
+ llvm::PassBuilder PB(TM.get());
+ PB.registerModuleAnalyses(MAM);
+ MPM.addPass(llvm::BitcodeWriterPass(*os));
+
+ // Run the passes
+ MPM.run(*llvmModule, MAM);
+}
+
void EmitMLIRAction::ExecuteAction() {
CompilerInstance &ci = this->instance();
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 0f91d6e..04e00e5 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -37,6 +37,8 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
return std::make_unique<EmitMLIRAction>();
case EmitLLVM:
return std::make_unique<EmitLLVMAction>();
+ case EmitLLVMBitcode:
+ return std::make_unique<EmitLLVMBitcodeAction>();
case EmitObj:
return std::make_unique<BackendAction>(
BackendAction::BackendActionTy::Backend_EmitObj);
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index cd2cae2..850b545 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -55,6 +55,7 @@ set(FLANG_TEST_DEPENDS
fir-opt
tco
bbc
+ llvm-dis
llvm-objdump
split-file
)
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index e020fa3..3ebc620 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -71,6 +71,7 @@
! HELP-FC1-NEXT:OPTIONS:
! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros
! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
+! HELP-FC1-NEXT: -emit-llvm-bc Build ASTs then convert to LLVM, emit .bc file
! HELP-FC1-NEXT: -emit-llvm Use the LLVM representation for assembler and object files
! HELP-FC1-NEXT: -emit-mlir Build the parse tree, then lower it to MLIR
! HELP-FC1-NEXT: -emit-obj Emit native object files
diff --git a/flang/test/Driver/emit-llvm-bc.f90 b/flang/test/Driver/emit-llvm-bc.f90
new file mode 100644
index 0000000..6634a11
--- /dev/null
+++ b/flang/test/Driver/emit-llvm-bc.f90
@@ -0,0 +1,19 @@
+! Test the options for generating LLVM byte-code `-emit-llvm-bc` option
+
+!-------------
+! RUN COMMANDS
+!-------------
+! RUN: %flang -emit-llvm -c %s -o - | llvm-dis -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-llvm-bc %s -o - | llvm-dis -o - | FileCheck %s
+
+!----------------
+! EXPECTED OUTPUT
+!----------------
+! CHECK: define void @_QQmain()
+! CHECK-NEXT: ret void
+! CHECK-NEXT: }
+
+!------
+! INPUT
+!------
+end program