Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
213799 views
1
//===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "clang/CIR/FrontendAction/CIRGenAction.h"
10
#include "mlir/IR/MLIRContext.h"
11
#include "mlir/IR/OwningOpRef.h"
12
#include "clang/Basic/DiagnosticFrontend.h"
13
#include "clang/CIR/CIRGenerator.h"
14
#include "clang/CIR/CIRToCIRPasses.h"
15
#include "clang/CIR/LowerToLLVM.h"
16
#include "clang/CodeGen/BackendUtil.h"
17
#include "clang/Frontend/CompilerInstance.h"
18
#include "llvm/IR/Module.h"
19
20
using namespace cir;
21
using namespace clang;
22
23
namespace cir {
24
25
static BackendAction
26
getBackendActionFromOutputType(CIRGenAction::OutputType Action) {
27
switch (Action) {
28
case CIRGenAction::OutputType::EmitCIR:
29
assert(false &&
30
"Unsupported output type for getBackendActionFromOutputType!");
31
break; // Unreachable, but fall through to report that
32
case CIRGenAction::OutputType::EmitAssembly:
33
return BackendAction::Backend_EmitAssembly;
34
case CIRGenAction::OutputType::EmitBC:
35
return BackendAction::Backend_EmitBC;
36
case CIRGenAction::OutputType::EmitLLVM:
37
return BackendAction::Backend_EmitLL;
38
case CIRGenAction::OutputType::EmitObj:
39
return BackendAction::Backend_EmitObj;
40
}
41
// We should only get here if a non-enum value is passed in or we went through
42
// the assert(false) case above
43
llvm_unreachable("Unsupported output type!");
44
}
45
46
static std::unique_ptr<llvm::Module>
47
lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx) {
48
return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx);
49
}
50
51
class CIRGenConsumer : public clang::ASTConsumer {
52
53
virtual void anchor();
54
55
CIRGenAction::OutputType Action;
56
57
CompilerInstance &CI;
58
59
std::unique_ptr<raw_pwrite_stream> OutputStream;
60
61
ASTContext *Context{nullptr};
62
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
63
std::unique_ptr<CIRGenerator> Gen;
64
const FrontendOptions &FEOptions;
65
CodeGenOptions &CGO;
66
67
public:
68
CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI,
69
CodeGenOptions &CGO, std::unique_ptr<raw_pwrite_stream> OS)
70
: Action(Action), CI(CI), OutputStream(std::move(OS)),
71
FS(&CI.getVirtualFileSystem()),
72
Gen(std::make_unique<CIRGenerator>(CI.getDiagnostics(), std::move(FS),
73
CI.getCodeGenOpts())),
74
FEOptions(CI.getFrontendOpts()), CGO(CGO) {}
75
76
void Initialize(ASTContext &Ctx) override {
77
assert(!Context && "initialized multiple times");
78
Context = &Ctx;
79
Gen->Initialize(Ctx);
80
}
81
82
bool HandleTopLevelDecl(DeclGroupRef D) override {
83
Gen->HandleTopLevelDecl(D);
84
return true;
85
}
86
87
void HandleInlineFunctionDefinition(FunctionDecl *D) override {
88
Gen->HandleInlineFunctionDefinition(D);
89
}
90
91
void HandleTranslationUnit(ASTContext &C) override {
92
Gen->HandleTranslationUnit(C);
93
94
if (!FEOptions.ClangIRDisableCIRVerifier) {
95
if (!Gen->verifyModule()) {
96
CI.getDiagnostics().Report(
97
diag::err_cir_verification_failed_pre_passes);
98
llvm::report_fatal_error(
99
"CIR codegen: module verification error before running CIR passes");
100
return;
101
}
102
}
103
104
mlir::ModuleOp MlirModule = Gen->getModule();
105
mlir::MLIRContext &MlirCtx = Gen->getMLIRContext();
106
107
if (!FEOptions.ClangIRDisablePasses) {
108
// Setup and run CIR pipeline.
109
if (runCIRToCIRPasses(MlirModule, MlirCtx, C,
110
!FEOptions.ClangIRDisableCIRVerifier,
111
CGO.OptimizationLevel > 0)
112
.failed()) {
113
CI.getDiagnostics().Report(diag::err_cir_to_cir_transform_failed);
114
return;
115
}
116
}
117
118
switch (Action) {
119
case CIRGenAction::OutputType::EmitCIR:
120
if (OutputStream && MlirModule) {
121
mlir::OpPrintingFlags Flags;
122
Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false);
123
MlirModule->print(*OutputStream, Flags);
124
}
125
break;
126
case CIRGenAction::OutputType::EmitLLVM:
127
case CIRGenAction::OutputType::EmitBC:
128
case CIRGenAction::OutputType::EmitObj:
129
case CIRGenAction::OutputType::EmitAssembly: {
130
llvm::LLVMContext LLVMCtx;
131
std::unique_ptr<llvm::Module> LLVMModule =
132
lowerFromCIRToLLVMIR(MlirModule, LLVMCtx);
133
134
BackendAction BEAction = getBackendActionFromOutputType(Action);
135
emitBackendOutput(
136
CI, CI.getCodeGenOpts(), C.getTargetInfo().getDataLayoutString(),
137
LLVMModule.get(), BEAction, FS, std::move(OutputStream));
138
break;
139
}
140
}
141
}
142
143
void HandleTagDeclDefinition(TagDecl *D) override {
144
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
145
Context->getSourceManager(),
146
"CIR generation of declaration");
147
Gen->HandleTagDeclDefinition(D);
148
}
149
150
void CompleteTentativeDefinition(VarDecl *D) override {
151
Gen->CompleteTentativeDefinition(D);
152
}
153
};
154
} // namespace cir
155
156
void CIRGenConsumer::anchor() {}
157
158
CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
159
: MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {}
160
161
CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
162
163
static std::unique_ptr<raw_pwrite_stream>
164
getOutputStream(CompilerInstance &CI, StringRef InFile,
165
CIRGenAction::OutputType Action) {
166
switch (Action) {
167
case CIRGenAction::OutputType::EmitAssembly:
168
return CI.createDefaultOutputFile(false, InFile, "s");
169
case CIRGenAction::OutputType::EmitCIR:
170
return CI.createDefaultOutputFile(false, InFile, "cir");
171
case CIRGenAction::OutputType::EmitLLVM:
172
return CI.createDefaultOutputFile(false, InFile, "ll");
173
case CIRGenAction::OutputType::EmitBC:
174
return CI.createDefaultOutputFile(true, InFile, "bc");
175
case CIRGenAction::OutputType::EmitObj:
176
return CI.createDefaultOutputFile(true, InFile, "o");
177
}
178
llvm_unreachable("Invalid CIRGenAction::OutputType");
179
}
180
181
std::unique_ptr<ASTConsumer>
182
CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
183
std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();
184
185
if (!Out)
186
Out = getOutputStream(CI, InFile, Action);
187
188
auto Result = std::make_unique<cir::CIRGenConsumer>(
189
Action, CI, CI.getCodeGenOpts(), std::move(Out));
190
191
return Result;
192
}
193
194
void EmitAssemblyAction::anchor() {}
195
EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *MLIRCtx)
196
: CIRGenAction(OutputType::EmitAssembly, MLIRCtx) {}
197
198
void EmitCIRAction::anchor() {}
199
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
200
: CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
201
202
void EmitLLVMAction::anchor() {}
203
EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx)
204
: CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {}
205
206
void EmitBCAction::anchor() {}
207
EmitBCAction::EmitBCAction(mlir::MLIRContext *MLIRCtx)
208
: CIRGenAction(OutputType::EmitBC, MLIRCtx) {}
209
210
void EmitObjAction::anchor() {}
211
EmitObjAction::EmitObjAction(mlir::MLIRContext *MLIRCtx)
212
: CIRGenAction(OutputType::EmitObj, MLIRCtx) {}
213
214