
The buildX naming convention originated when the CIRGen implementation was planned to be substantially different from original CodeGen. CIRGen is now a much closer adaption of CodeGen, and the emitX to buildX renaming just makes things more confusing, since CodeGen also has some helper functions whose names start with build or Build, so it's not immediately clear which CodeGen function corresponds to a CIRGen buildX function. Rename the buildX functions back to emitX to fix this.
163 lines
5.8 KiB
C++
163 lines
5.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 &context,
|
|
clang::ASTContext &astctx,
|
|
const clang::CodeGenOptions &cgo,
|
|
DiagnosticsEngine &diags)
|
|
: builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()),
|
|
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))},
|
|
diags(diags), target(astCtx.getTargetInfo()) {}
|
|
|
|
mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
|
|
assert(cLoc.isValid() && "expected valid source location");
|
|
const SourceManager &sm = astCtx.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 {
|
|
errorNYI(global->getSourceRange(), "global variable declaration");
|
|
}
|
|
|
|
// 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());
|
|
auto funcOp = builder.create<cir::FuncOp>(
|
|
getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName());
|
|
theModule.push_back(funcOp);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) {
|
|
unsigned diagID = diags.getCustomDiagID(
|
|
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
|
|
return diags.Report(diagID) << feature;
|
|
}
|
|
|
|
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(SourceLocation loc,
|
|
llvm::StringRef feature,
|
|
llvm::StringRef name) {
|
|
unsigned diagID = diags.getCustomDiagID(
|
|
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0: %1");
|
|
return diags.Report(loc, diagID) << feature << name;
|
|
}
|
|
|
|
DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
|
|
llvm::StringRef feature) {
|
|
return errorNYI(loc.getBegin(), feature) << loc;
|
|
}
|
|
|
|
DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
|
|
llvm::StringRef feature,
|
|
llvm::StringRef name) {
|
|
return errorNYI(loc.getBegin(), feature, name) << loc;
|
|
}
|