[ELF] Reorder target-specific error messaes
[llvm-project.git] / clang / lib / CIR / CodeGen / CIRGenModule.cpp
blob2615ae382cb8b538dd4cacb3b9972175be5ed280
1 //===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
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 // This is the internal per-translation-unit state used for CIR translation.
11 //===----------------------------------------------------------------------===//
13 #include "CIRGenModule.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/DeclBase.h"
17 #include "clang/AST/GlobalDecl.h"
18 #include "clang/Basic/SourceManager.h"
19 #include "clang/CIR/Dialect/IR/CIRDialect.h"
21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/IR/Location.h"
23 #include "mlir/IR/MLIRContext.h"
25 using namespace clang;
26 using namespace clang::CIRGen;
28 CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
29 clang::ASTContext &astContext,
30 const clang::CodeGenOptions &cgo,
31 DiagnosticsEngine &diags)
32 : builder(mlirContext, *this), astContext(astContext),
33 langOpts(astContext.getLangOpts()),
34 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
35 diags(diags), target(astContext.getTargetInfo()), genTypes(*this) {
37 // Initialize cached types
38 VoidTy = cir::VoidType::get(&getMLIRContext());
39 SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
40 SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
41 SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
42 SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
43 SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
44 UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
45 UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
46 UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
47 UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
48 UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
49 FP16Ty = cir::FP16Type::get(&getMLIRContext());
50 BFloat16Ty = cir::BF16Type::get(&getMLIRContext());
51 FloatTy = cir::SingleType::get(&getMLIRContext());
52 DoubleTy = cir::DoubleType::get(&getMLIRContext());
53 FP80Ty = cir::FP80Type::get(&getMLIRContext());
54 FP128Ty = cir::FP128Type::get(&getMLIRContext());
57 mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
58 assert(cLoc.isValid() && "expected valid source location");
59 const SourceManager &sm = astContext.getSourceManager();
60 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
61 StringRef filename = pLoc.getFilename();
62 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
63 pLoc.getLine(), pLoc.getColumn());
66 mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
67 assert(cRange.isValid() && "expected a valid source range");
68 mlir::Location begin = getLoc(cRange.getBegin());
69 mlir::Location end = getLoc(cRange.getEnd());
70 mlir::Attribute metadata;
71 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
74 void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
75 const auto *global = cast<ValueDecl>(gd.getDecl());
77 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
78 // Update deferred annotations with the latest declaration if the function
79 // was already used or defined.
80 if (fd->hasAttr<AnnotateAttr>())
81 errorNYI(fd->getSourceRange(), "deferredAnnotations");
82 if (!fd->doesThisDeclarationHaveABody()) {
83 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
84 return;
86 errorNYI(fd->getSourceRange(),
87 "function declaration that forces code gen");
88 return;
90 } else {
91 assert(cast<VarDecl>(global)->isFileVarDecl() &&
92 "Cannot emit local var decl as global");
95 // TODO(CIR): Defer emitting some global definitions until later
96 emitGlobalDefinition(gd);
99 void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
100 mlir::Operation *op) {
101 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
102 if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) {
103 auto funcOp = builder.create<cir::FuncOp>(
104 getLoc(funcDecl->getSourceRange()), identifier->getName());
105 theModule.push_back(funcOp);
106 } else {
107 errorNYI(funcDecl->getSourceRange().getBegin(),
108 "function definition with a non-identifier for a name");
112 void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
113 bool isTentative) {
114 mlir::Type type = getTypes().convertType(vd->getType());
115 if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
116 auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
117 identifier->getName(), type);
118 // TODO(CIR): This code for processing initial values is a placeholder
119 // until class ConstantEmitter is upstreamed and the code for processing
120 // constant expressions is filled out. Only the most basic handling of
121 // certain constant expressions is implemented for now.
122 const VarDecl *initDecl;
123 const Expr *initExpr = vd->getAnyInitializer(initDecl);
124 if (initExpr) {
125 mlir::Attribute initializer;
126 if (APValue *value = initDecl->evaluateValue()) {
127 switch (value->getKind()) {
128 case APValue::Int: {
129 initializer = builder.getAttr<cir::IntAttr>(type, value->getInt());
130 break;
132 case APValue::Float: {
133 initializer = builder.getAttr<cir::FPAttr>(type, value->getFloat());
134 break;
136 case APValue::LValue: {
137 if (value->getLValueBase()) {
138 errorNYI(initExpr->getSourceRange(),
139 "non-null pointer initialization");
140 } else {
141 if (auto ptrType = mlir::dyn_cast<cir::PointerType>(type)) {
142 initializer = builder.getConstPtrAttr(
143 ptrType, value->getLValueOffset().getQuantity());
144 } else {
145 llvm_unreachable(
146 "non-pointer variable initialized with a pointer");
149 break;
151 default:
152 errorNYI(initExpr->getSourceRange(), "unsupported initializer kind");
153 break;
155 } else {
156 errorNYI(initExpr->getSourceRange(), "non-constant initializer");
158 varOp.setInitialValueAttr(initializer);
160 theModule.push_back(varOp);
161 } else {
162 errorNYI(vd->getSourceRange().getBegin(),
163 "variable definition with a non-identifier for a name");
167 void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
168 mlir::Operation *op) {
169 const auto *decl = cast<ValueDecl>(gd.getDecl());
170 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
171 // TODO(CIR): Skip generation of CIR for functions with available_externally
172 // linkage at -O0.
174 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
175 // Make sure to emit the definition(s) before we emit the thunks. This is
176 // necessary for the generation of certain thunks.
177 (void)method;
178 errorNYI(method->getSourceRange(), "member function");
179 return;
182 if (fd->isMultiVersion())
183 errorNYI(fd->getSourceRange(), "multiversion functions");
184 emitGlobalFunctionDefinition(gd, op);
185 return;
188 if (const auto *vd = dyn_cast<VarDecl>(decl))
189 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
191 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
194 // Emit code for a single top level declaration.
195 void CIRGenModule::emitTopLevelDecl(Decl *decl) {
197 // Ignore dependent declarations.
198 if (decl->isTemplated())
199 return;
201 switch (decl->getKind()) {
202 default:
203 errorNYI(decl->getBeginLoc(), "declaration of kind",
204 decl->getDeclKindName());
205 break;
207 case Decl::Function: {
208 auto *fd = cast<FunctionDecl>(decl);
209 // Consteval functions shouldn't be emitted.
210 if (!fd->isConsteval())
211 emitGlobal(fd);
212 break;
215 case Decl::Var: {
216 auto *vd = cast<VarDecl>(decl);
217 emitGlobal(vd);
218 break;
223 DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
224 llvm::StringRef feature) {
225 unsigned diagID = diags.getCustomDiagID(
226 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
227 return diags.Report(loc, diagID) << feature;
230 DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
231 llvm::StringRef feature) {
232 return errorNYI(loc.getBegin(), feature) << loc;