aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenModule.cpp
diff options
context:
space:
mode:
authorDavid Olsen <dolsen@nvidia.com>2025-02-19 19:58:12 -0800
committerGitHub <noreply@github.com>2025-02-19 19:58:12 -0800
commitf8bdbed5b3f12c5e1c38a29cd71df286a9e2725c (patch)
tree41d8287ec05c55a2dc344123a43c43253e0d7f30 /clang/lib/CIR/CodeGen/CIRGenModule.cpp
parent1fd280d0f2a31a41e74374c7757a8a4d01e116b5 (diff)
downloadllvm-f8bdbed5b3f12c5e1c38a29cd71df286a9e2725c.zip
llvm-f8bdbed5b3f12c5e1c38a29cd71df286a9e2725c.tar.gz
llvm-f8bdbed5b3f12c5e1c38a29cd71df286a9e2725c.tar.bz2
[CIR] Upstream simple function bodies (#127674)
Enable ClangIR generation for very simple functions. The functions have to return `void` or an integral type, contain only compound statements or `return` statements, and `return` statement expressions can only be integral literals of the correct type. The functions can have parameters, but those are currently ignored because there is no way to access them. This change intentionally focuses on breadth (introducing scopes, statements, and expressions) rather than depth, because it enables people to work on upstreaming in parallel without interference. The new ClangIR ops in this change are `ReturnOp`, `YieldOp`, `ScopeOp`, and `TrapOp`. These operations are complete (except for the `ParentOneOf` property) and shouldn't require further upstreaming changes. Significant additions were made to `FuncOp`, adding a type and a region, but that operation is still far from complete. The classes `ScalarExprEmitter` and `CIRGenFunction`, along with the `emit*` functions in `CIRGenFunction` that generate ClangIR for statements, are new in this change. All of these are very incomplete and will be filled out in later upstreaming patches. Existing test `hello.c` is removed and replaced by the new test `func-simple.cpp`. This tests all forms of functions that are currently supported.
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenModule.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp74
1 files changed, 68 insertions, 6 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index cbecdf9..c1d3265 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CIRGenModule.h"
+#include "CIRGenFunction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
@@ -102,19 +103,30 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl 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 {
+ if (funcDecl->getIdentifier() == nullptr) {
errorNYI(funcDecl->getSourceRange().getBegin(),
"function definition with a non-identifier for a name");
+ return;
+ }
+ cir::FuncType funcType =
+ cast<cir::FuncType>(convertType(funcDecl->getType()));
+
+ cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
+ if (!funcOp || funcOp.getFunctionType() != funcType) {
+ funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
+ /*DontDefer=*/true, ForDefinition);
+ }
+
+ CIRGenFunction cgf(*this, builder);
+ {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ cgf.generateCode(gd, funcOp, funcType);
}
}
void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
- mlir::Type type = getTypes().convertType(vd->getType());
+ mlir::Type type = convertType(vd->getType());
if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
identifier->getName(), type);
@@ -223,6 +235,56 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
}
}
+cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
+ mlir::Type funcType, bool forVTable,
+ bool dontDefer,
+ ForDefinition_t isForDefinition) {
+ assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
+ "consteval function should never be emitted");
+
+ if (!funcType) {
+ const auto *fd = cast<FunctionDecl>(gd.getDecl());
+ funcType = convertType(fd->getType());
+ }
+
+ cir::FuncOp func = getOrCreateCIRFunction(
+ cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName(), funcType, gd,
+ forVTable, dontDefer, /*isThunk=*/false, isForDefinition);
+ return func;
+}
+
+cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
+ StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
+ bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
+ mlir::ArrayAttr extraAttrs) {
+ auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
+ bool invalidLoc = !funcDecl ||
+ funcDecl->getSourceRange().getBegin().isInvalid() ||
+ funcDecl->getSourceRange().getEnd().isInvalid();
+ cir::FuncOp funcOp = createCIRFunction(
+ invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
+ mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
+ return funcOp;
+}
+
+cir::FuncOp
+CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
+ cir::FuncType funcType,
+ const clang::FunctionDecl *funcDecl) {
+ cir::FuncOp func;
+ {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+
+ func = builder.create<cir::FuncOp>(loc, name, funcType);
+ theModule.push_back(func);
+ }
+ return func;
+}
+
+mlir::Type CIRGenModule::convertType(QualType type) {
+ return genTypes.convertType(type);
+}
+
DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
llvm::StringRef feature) {
unsigned diagID = diags.getCustomDiagID(