
ClangIR CodeGen code uses both `mlir::MLIRContext` and `clang::ASTContext` objects extensively. Refering to either of those as just "context" can be confusing. Change the names of all variables, parameters, and fields in `clang/lib/CIR/CodeGen` that refer to `MLIRContext` or an `ASTContext` to be either `mlirContext` or `astContext`. This change is only the renaming of variables/parameters/fields. There are no behavior changes. So there are no new tests or changes to existing tests. This change mimics a recent change in the ClangIR incubator repository.
185 lines
6.8 KiB
C++
185 lines
6.8 KiB
C++
//===- 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 "clang/AST/GlobalDecl.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "clang/CIR/Dialect/IR/CIRDialect.h"
|
|
|
|
#include "mlir/IR/BuiltinOps.h"
|
|
#include "mlir/IR/Location.h"
|
|
#include "mlir/IR/MLIRContext.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::CIRGen;
|
|
|
|
CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
|
|
clang::ASTContext &astContext,
|
|
const clang::CodeGenOptions &cgo,
|
|
DiagnosticsEngine &diags)
|
|
: builder(mlirContext, *this), astContext(astContext),
|
|
langOpts(astContext.getLangOpts()),
|
|
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
|
|
diags(diags), target(astContext.getTargetInfo()), genTypes(*this) {
|
|
|
|
// Initialize cached types
|
|
SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
|
|
SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
|
|
SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
|
|
SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
|
|
SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
|
|
UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
|
|
UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
|
|
UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
|
|
UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
|
|
UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
|
|
}
|
|
|
|
mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
|
|
assert(cLoc.isValid() && "expected valid source location");
|
|
const SourceManager &sm = astContext.getSourceManager();
|
|
PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
|
|
StringRef filename = pLoc.getFilename();
|
|
return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
|
|
pLoc.getLine(), pLoc.getColumn());
|
|
}
|
|
|
|
mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
|
|
assert(cRange.isValid() && "expected a valid source range");
|
|
mlir::Location begin = getLoc(cRange.getBegin());
|
|
mlir::Location end = getLoc(cRange.getEnd());
|
|
mlir::Attribute metadata;
|
|
return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
|
|
}
|
|
|
|
void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
|
|
const auto *global = cast<ValueDecl>(gd.getDecl());
|
|
|
|
if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
|
|
// Update deferred annotations with the latest declaration if the function
|
|
// was already used or defined.
|
|
if (fd->hasAttr<AnnotateAttr>())
|
|
errorNYI(fd->getSourceRange(), "deferredAnnotations");
|
|
if (!fd->doesThisDeclarationHaveABody()) {
|
|
if (!fd->doesDeclarationForceExternallyVisibleDefinition())
|
|
return;
|
|
|
|
errorNYI(fd->getSourceRange(),
|
|
"function declaration that forces code gen");
|
|
return;
|
|
}
|
|
} else {
|
|
assert(cast<VarDecl>(global)->isFileVarDecl() &&
|
|
"Cannot emit local var decl as global");
|
|
}
|
|
|
|
// TODO(CIR): Defer emitting some global definitions until later
|
|
emitGlobalDefinition(gd);
|
|
}
|
|
|
|
void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
|
|
mlir::Operation *op) {
|
|
auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
|
|
if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) {
|
|
auto funcOp = builder.create<cir::FuncOp>(
|
|
getLoc(funcDecl->getSourceRange()), identifier->getName());
|
|
theModule.push_back(funcOp);
|
|
} else {
|
|
errorNYI(funcDecl->getSourceRange().getBegin(),
|
|
"function definition with a non-identifier for a name");
|
|
}
|
|
}
|
|
|
|
void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
|
|
bool isTentative) {
|
|
mlir::Type type = getTypes().convertType(vd->getType());
|
|
if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
|
|
auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
|
|
identifier->getName(), type);
|
|
theModule.push_back(varOp);
|
|
} else {
|
|
errorNYI(vd->getSourceRange().getBegin(),
|
|
"variable definition with a non-identifier for a name");
|
|
}
|
|
}
|
|
|
|
void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
|
|
mlir::Operation *op) {
|
|
const auto *decl = cast<ValueDecl>(gd.getDecl());
|
|
if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
|
|
// TODO(CIR): Skip generation of CIR for functions with available_externally
|
|
// linkage at -O0.
|
|
|
|
if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
|
|
// Make sure to emit the definition(s) before we emit the thunks. This is
|
|
// necessary for the generation of certain thunks.
|
|
(void)method;
|
|
errorNYI(method->getSourceRange(), "member function");
|
|
return;
|
|
}
|
|
|
|
if (fd->isMultiVersion())
|
|
errorNYI(fd->getSourceRange(), "multiversion functions");
|
|
emitGlobalFunctionDefinition(gd, op);
|
|
return;
|
|
}
|
|
|
|
if (const auto *vd = dyn_cast<VarDecl>(decl))
|
|
return emitGlobalVarDefinition(vd, !vd->hasDefinition());
|
|
|
|
llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
|
|
}
|
|
|
|
// Emit code for a single top level declaration.
|
|
void CIRGenModule::emitTopLevelDecl(Decl *decl) {
|
|
|
|
// Ignore dependent declarations.
|
|
if (decl->isTemplated())
|
|
return;
|
|
|
|
switch (decl->getKind()) {
|
|
default:
|
|
errorNYI(decl->getBeginLoc(), "declaration of kind",
|
|
decl->getDeclKindName());
|
|
break;
|
|
|
|
case Decl::Function: {
|
|
auto *fd = cast<FunctionDecl>(decl);
|
|
// Consteval functions shouldn't be emitted.
|
|
if (!fd->isConsteval())
|
|
emitGlobal(fd);
|
|
break;
|
|
}
|
|
|
|
case Decl::Var: {
|
|
auto *vd = cast<VarDecl>(decl);
|
|
emitGlobal(vd);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
|
|
llvm::StringRef feature) {
|
|
unsigned diagID = diags.getCustomDiagID(
|
|
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
|
|
return diags.Report(loc, diagID) << feature;
|
|
}
|
|
|
|
DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
|
|
llvm::StringRef feature) {
|
|
return errorNYI(loc.getBegin(), feature) << loc;
|
|
}
|