[clang] [CIR] Upstream simple function bodies (PR #127674)

David Olsen via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 18 14:57:47 PST 2025


================
@@ -0,0 +1,203 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Internal per-function state used for AST-to-ClangIR code gen
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+
+#include "clang/AST/GlobalDecl.h"
+
+#include <cassert>
+
+namespace clang::CIRGen {
+
+CIRGenFunction::CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder,
+                               bool suppressNewContext)
+    : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {}
+
+CIRGenFunction::~CIRGenFunction() {}
+
+// This is copied from clang/lib/CodeGen/CodeGenFunction.cpp
+cir::TypeEvaluationKind CIRGenFunction::getEvaluationKind(QualType type) {
+  type = type.getCanonicalType();
+  while (true) {
+    switch (type->getTypeClass()) {
+#define TYPE(name, parent)
+#define ABSTRACT_TYPE(name, parent)
+#define NON_CANONICAL_TYPE(name, parent) case Type::name:
+#define DEPENDENT_TYPE(name, parent) case Type::name:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
+#include "clang/AST/TypeNodes.inc"
+      llvm_unreachable("non-canonical or dependent type in IR-generation");
+
+    case Type::ArrayParameter:
+    case Type::HLSLAttributedResource:
+      llvm_unreachable("NYI");
+
+    case Type::Auto:
+    case Type::DeducedTemplateSpecialization:
+      llvm_unreachable("undeduced type in IR-generation");
+
+    // Various scalar types.
+    case Type::Builtin:
+    case Type::Pointer:
+    case Type::BlockPointer:
+    case Type::LValueReference:
+    case Type::RValueReference:
+    case Type::MemberPointer:
+    case Type::Vector:
+    case Type::ExtVector:
+    case Type::ConstantMatrix:
+    case Type::FunctionProto:
+    case Type::FunctionNoProto:
+    case Type::Enum:
+    case Type::ObjCObjectPointer:
+    case Type::Pipe:
+    case Type::BitInt:
+      return cir::TEK_Scalar;
+
+    // Complexes.
+    case Type::Complex:
+      return cir::TEK_Complex;
+
+    // Arrays, records, and Objective-C objects.
+    case Type::ConstantArray:
+    case Type::IncompleteArray:
+    case Type::VariableArray:
+    case Type::Record:
+    case Type::ObjCObject:
+    case Type::ObjCInterface:
+      return cir::TEK_Aggregate;
+
+    // We operate on atomic values according to their underlying type.
+    case Type::Atomic:
+      type = cast<AtomicType>(type)->getValueType();
+      continue;
+    }
+    llvm_unreachable("unknown type kind!");
+  }
+}
+
+mlir::Type CIRGenFunction::convertTypeForMem(QualType t) {
+  return cgm.getTypes().convertTypeForMem(t);
+}
+
+mlir::Type CIRGenFunction::convertType(QualType t) {
+  return cgm.getTypes().convertType(t);
+}
+
+mlir::Location CIRGenFunction::getLoc(SourceLocation srcLoc) {
+  // Some AST nodes might contain invalid source locations (e.g.
+  // CXXDefaultArgExpr), workaround that to still get something out.
+  if (srcLoc.isValid()) {
+    const SourceManager &sm = getContext().getSourceManager();
+    PresumedLoc pLoc = sm.getPresumedLoc(srcLoc);
+    StringRef filename = pLoc.getFilename();
+    return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
+                                     pLoc.getLine(), pLoc.getColumn());
+  } else {
+    // Do our best...
+    assert(currSrcLoc && "expected to inherit some source location");
+    return *currSrcLoc;
+  }
+}
+
+mlir::Location CIRGenFunction::getLoc(SourceRange srcLoc) {
+  // Some AST nodes might contain invalid source locations (e.g.
+  // CXXDefaultArgExpr), workaround that to still get something out.
+  if (srcLoc.isValid()) {
+    mlir::Location beg = getLoc(srcLoc.getBegin());
+    mlir::Location end = getLoc(srcLoc.getEnd());
+    SmallVector<mlir::Location, 2> locs = {beg, end};
+    mlir::Attribute metadata;
+    return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
+  } else if (currSrcLoc) {
+    return *currSrcLoc;
+  }
+
+  // We're brave, but time to give up.
+  return builder.getUnknownLoc();
+}
+
+mlir::Location CIRGenFunction::getLoc(mlir::Location lhs, mlir::Location rhs) {
+  SmallVector<mlir::Location, 2> locs = {lhs, rhs};
+  mlir::Attribute metadata;
+  return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
+}
+
+void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
+                                   cir::FuncOp fn, cir::FuncType funcType,
+                                   SourceLocation loc,
+                                   SourceLocation startLoc) {
+  assert(!curFn &&
+         "CIRGenFunction can only be used for one function at a time");
+
+  fnRetTy = returnType;
+  curFn = fn;
+
+  mlir::Block *entryBB = &fn.getBlocks().front();
+  builder.setInsertionPointToStart(entryBB);
+}
+
+void CIRGenFunction::finishFunction(SourceLocation endLoc) {}
+
+mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {
+  auto result = mlir::LogicalResult::success();
+  if (const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
+    emitCompoundStmtWithoutScope(*block);
+  else
+    result = emitStmt(body, /*useCurrentScope=*/true);
+  return result;
+}
+
+cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
+                                         cir::FuncType funcType) {
+  const auto funcDecl = cast<FunctionDecl>(gd.getDecl());
+  SourceLocation loc = funcDecl->getLocation();
+  Stmt *body = funcDecl->getBody();
+  SourceRange bodyRange =
+      body ? body->getSourceRange() : funcDecl->getLocation();
----------------
dkolsen-pgi wrote:

Good point.  I'll have to look into this a little more, to see what the incubator does here.  I think the code only gets here if there is a function body (because this is only used for function definitions, not declarations).  So it may be that the check here for a nullptr `body` should be an assert.  But I'll have to confirm that.


https://github.com/llvm/llvm-project/pull/127674


More information about the cfe-commits mailing list