-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CIR] Upstream initial function call support #134673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Sirui Mu (Lancern) ChangesThis PR upstreams initial support for making function calls in CIR. Function arguments and return values are not included to keep the patch small for review. Related to #132487 Patch is 27.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/134673.diff 17 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c1e93fe790c08..dda3ecf492506 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -201,6 +201,19 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return create<cir::PtrStrideOp>(loc, base.getType(), base, stride);
}
+ //===--------------------------------------------------------------------===//
+ // Call operators
+ //===--------------------------------------------------------------------===//
+
+ cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee) {
+ auto op = create<cir::CallOp>(loc, callee);
+ return op;
+ }
+
+ cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee) {
+ return createCallOp(loc, mlir::SymbolRefAttr::get(callee));
+ }
+
//===--------------------------------------------------------------------===//
// Cast/Conversion Operators
//===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 609e60ca74b49..aa805ee4108da 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1242,6 +1242,43 @@ def FuncOp : CIR_Op<"func", [
let hasVerifier = 1;
}
+//===----------------------------------------------------------------------===//
+// CallOp
+//===----------------------------------------------------------------------===//
+
+class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []>
+ : Op<CIR_Dialect, mnemonic,
+ !listconcat(extra_traits,
+ [DeclareOpInterfaceMethods<CIRCallOpInterface>,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>])> {
+ let hasCustomAssemblyFormat = 1;
+ let skipDefaultBuilders = 1;
+ let hasVerifier = 0;
+
+ dag commonArgs = (ins FlatSymbolRefAttr:$callee);
+}
+
+def CallOp : CIR_CallOp<"call", [NoRegionArguments]> {
+ let summary = "call a function";
+ let description = [{
+ The `cir.call` operation represents a direct call to a function that is
+ within the same symbol scope as the call. The callee is encoded as a symbol
+ reference attribute named `callee`.
+
+ Example:
+
+ ```mlir
+ %0 = cir.call @foo()
+ ```
+ }];
+
+ let arguments = commonArgs;
+
+ let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee), [{
+ $_state.addAttribute("callee", callee);
+ }]>];
+}
+
//===----------------------------------------------------------------------===//
// UnreachableOp
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index 39ef402c59e43..c6c6356118ac6 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -15,8 +15,17 @@
include "mlir/IR/OpBase.td"
include "mlir/IR/SymbolInterfaces.td"
+include "mlir/Interfaces/CallInterfaces.td"
let cppNamespace = "::cir" in {
+ // The CIRCallOpInterface must be used instead of CallOpInterface when looking
+ // at arguments and other bits of CallOp. This creates a level of abstraction
+ // that's useful for handling indirect calls and other details.
+ def CIRCallOpInterface : OpInterface<"CIRCallOpInterface", []> {
+ // Currently we don't have any methods defined in CIRCallOpInterface. We'll
+ // add more methods as the upstreaming proceeds.
+ }
+
def CIRGlobalValueInterface
: OpInterface<"CIRGlobalValueInterface", [Symbol]> {
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 86fdaf1ddaf51..491fb31c4b7e2 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -72,6 +72,24 @@ struct MissingFeatures {
static bool opFuncLinkage() { return false; }
static bool opFuncVisibility() { return false; }
+ // CallOp handling
+ static bool opCallBuiltinFunc() { return false; }
+ static bool opCallPseudoDtor() { return false; }
+ static bool opCallArgs() { return false; }
+ static bool opCallReturn() { return false; }
+ static bool opCallArgEvaluationOrder() { return false; }
+ static bool opCallCallConv() { return false; }
+ static bool opCallSideEffect() { return false; }
+ static bool opCallChainCall() { return false; }
+ static bool opCallNoPrototypeFunc() { return false; }
+ static bool opCallMustTail() { return false; }
+ static bool opCallIndirect() { return false; }
+ static bool opCallVirtual() { return false; }
+ static bool opCallInAlloca() { return false; }
+ static bool opCallAttrs() { return false; }
+ static bool opCallSurroundingTry() { return false; }
+ static bool opCallASTAttr() { return false; }
+
// ScopeOp handling
static bool opScopeCleanupRegion() { return false; }
@@ -90,7 +108,10 @@ struct MissingFeatures {
static bool opTBAA() { return false; }
static bool opCmp() { return false; }
static bool objCLifetime() { return false; }
+ static bool objCBlocks() { return false; }
static bool emitNullabilityCheck() { return false; }
+ static bool emitLValueAlignmentAssumption() { return false; }
+ static bool emitLifetimeMarkers() { return false; }
static bool astVarDeclInterface() { return false; }
static bool stackSaveOp() { return false; }
static bool aggValueSlot() { return false; }
@@ -108,6 +129,8 @@ struct MissingFeatures {
static bool cgFPOptionsRAII() { return false; }
static bool metaDataNode() { return false; }
static bool fastMathFlags() { return false; }
+ static bool weakRefReference() { return false; }
+ static bool hip() { return false; }
// Missing types
static bool dataMemberType() { return false; }
@@ -127,6 +150,7 @@ struct MissingFeatures {
static bool complexImagOp() { return false; }
static bool complexRealOp() { return false; }
static bool ifOp() { return false; }
+ static bool invokeOp() { return false; }
static bool labelOp() { return false; }
static bool ptrDiffOp() { return false; }
static bool ptrStrideOp() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
new file mode 100644
index 0000000000000..1a936458782ea
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -0,0 +1,95 @@
+//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function definition used
+// to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenCall.h"
+#include "CIRGenFunction.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+CIRGenFunctionInfo *CIRGenFunctionInfo::create() {
+ // For now we just create an empty CIRGenFunctionInfo.
+ CIRGenFunctionInfo *fi = new CIRGenFunctionInfo();
+ return fi;
+}
+
+CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
+ assert(!cir::MissingFeatures::opCallVirtual());
+ return *this;
+}
+
+static const CIRGenFunctionInfo &arrangeFreeFunctionLikeCall(CIRGenTypes &cgt) {
+ assert(!cir::MissingFeatures::opCallArgs());
+ return cgt.arrangeCIRFunctionInfo();
+}
+
+const CIRGenFunctionInfo &CIRGenTypes::arrangeFreeFunctionCall() {
+ return arrangeFreeFunctionLikeCall(*this);
+}
+
+static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
+ mlir::Location callLoc,
+ cir::FuncOp directFuncOp) {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+
+ assert(!cir::MissingFeatures::opCallSurroundingTry());
+ assert(!cir::MissingFeatures::invokeOp());
+
+ assert(builder.getInsertionBlock() && "expected valid basic block");
+ assert(!cir::MissingFeatures::opCallIndirect());
+
+ return builder.createCallOp(callLoc, directFuncOp);
+}
+
+RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
+ const CIRGenCallee &callee,
+ cir::CIRCallOpInterface *callOp,
+ mlir::Location loc) {
+ assert(!cir::MissingFeatures::opCallArgs());
+ assert(!cir::MissingFeatures::emitLifetimeMarkers());
+
+ const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
+ mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
+
+ assert(!cir::MissingFeatures::opCallInAlloca());
+
+ mlir::NamedAttrList attrs;
+ StringRef funcName;
+ if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
+ funcName = calleeFuncOp.getName();
+
+ assert(!cir::MissingFeatures::opCallCallConv());
+ assert(!cir::MissingFeatures::opCallSideEffect());
+ assert(!cir::MissingFeatures::opCallAttrs());
+
+ assert(!cir::MissingFeatures::invokeOp());
+
+ auto directFuncOp = dyn_cast<cir::FuncOp>(calleePtr);
+ assert(!cir::MissingFeatures::opCallIndirect());
+ assert(!cir::MissingFeatures::opCallAttrs());
+
+ cir::CIRCallOpInterface theCall = emitCallLikeOp(*this, loc, directFuncOp);
+
+ if (callOp)
+ *callOp = theCall;
+
+ assert(!cir::MissingFeatures::opCallMustTail());
+ assert(!cir::MissingFeatures::opCallReturn());
+
+ // For now we just return nothing because we don't have support for return
+ // values yet.
+ RValue ret = RValue::get(nullptr);
+
+ return ret;
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 0996167feeef6..76fefdca9e45e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -14,15 +14,73 @@
#ifndef CLANG_LIB_CODEGEN_CIRGENCALL_H
#define CLANG_LIB_CODEGEN_CIRGENCALL_H
+#include "mlir/IR/Operation.h"
#include "clang/AST/GlobalDecl.h"
#include "llvm/ADT/SmallVector.h"
namespace clang::CIRGen {
+class CIRGenFunction;
+
+/// Abstract information about a function or function prototype.
+class CIRGenCalleeInfo {
+ clang::GlobalDecl calleeDecl;
+
+public:
+ explicit CIRGenCalleeInfo() : calleeDecl() {}
+ CIRGenCalleeInfo(clang::GlobalDecl calleeDecl) : calleeDecl(calleeDecl) {}
+};
+
+class CIRGenCallee {
+ enum class SpecialKind : uintptr_t {
+ Invalid,
+
+ Last = Invalid,
+ };
+
+ SpecialKind kindOrFunctionPtr;
+
+ union {
+ CIRGenCalleeInfo abstractInfo;
+ };
+
+public:
+ CIRGenCallee() : kindOrFunctionPtr(SpecialKind::Invalid) {}
+
+ CIRGenCallee(const CIRGenCalleeInfo &abstractInfo, mlir::Operation *funcPtr)
+ : kindOrFunctionPtr(SpecialKind(reinterpret_cast<uintptr_t>(funcPtr))),
+ abstractInfo(abstractInfo) {
+ assert(funcPtr && "configuring callee without function pointer");
+ }
+
+ static CIRGenCallee
+ forDirect(mlir::Operation *funcPtr,
+ const CIRGenCalleeInfo &abstractInfo = CIRGenCalleeInfo()) {
+ return CIRGenCallee(abstractInfo, funcPtr);
+ }
+
+ bool isOrdinary() const {
+ return uintptr_t(kindOrFunctionPtr) > uintptr_t(SpecialKind::Last);
+ }
+
+ /// If this is a delayed callee computation of some sort, prepare a concrete
+ /// callee
+ CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const;
+
+ mlir::Operation *getFunctionPointer() const {
+ assert(isOrdinary());
+ return reinterpret_cast<mlir::Operation *>(kindOrFunctionPtr);
+ }
+};
+
/// Type for representing both the decl and type of parameters to a function.
/// The decl must be either a ParmVarDecl or ImplicitParamDecl.
class FunctionArgList : public llvm::SmallVector<const clang::VarDecl *, 16> {};
+struct CallArg {};
+
+class CallArgList : public llvm::SmallVector<CallArg, 8> {};
+
} // namespace clang::CIRGen
#endif // CLANG_LIB_CODEGEN_CIRGENCALL_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index f01e03a89981d..1e5fb985b0b8c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"
@@ -304,6 +305,102 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e) {
llvm_unreachable("bad evaluation kind");
}
+static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
+ assert(!cir::MissingFeatures::weakRefReference());
+ return cgm.getAddrOfFunction(gd);
+}
+
+static CIRGenCallee emitDirectCallee(CIRGenModule &cgm, GlobalDecl gd) {
+ assert(!cir::MissingFeatures::opCallBuiltinFunc());
+
+ cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
+
+ assert(!cir::MissingFeatures::hip());
+
+ return CIRGenCallee::forDirect(callee, gd);
+}
+
+RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
+ const CIRGenCallee &callee,
+ const clang::CallExpr *e) {
+ // Get the actual function type. The callee type will always be a pointer to
+ // function type or a block pointer type.
+ assert(calleeTy->isFunctionPointerType() &&
+ "Callee must have function pointer type!");
+
+ calleeTy = getContext().getCanonicalType(calleeTy);
+
+ if (getLangOpts().CPlusPlus)
+ assert(!cir::MissingFeatures::sanitizers());
+
+ assert(!cir::MissingFeatures::sanitizers());
+ assert(!cir::MissingFeatures::opCallArgs());
+
+ const CIRGenFunctionInfo &funcInfo = cgm.getTypes().arrangeFreeFunctionCall();
+
+ assert(!cir::MissingFeatures::opCallNoPrototypeFunc());
+ assert(!cir::MissingFeatures::opCallChainCall());
+ assert(!cir::MissingFeatures::hip());
+ assert(!cir::MissingFeatures::opCallMustTail());
+
+ cir::CIRCallOpInterface callOp;
+ RValue callResult =
+ emitCall(funcInfo, callee, &callOp, getLoc(e->getExprLoc()));
+
+ assert(!cir::MissingFeatures::generateDebugInfo());
+
+ return callResult;
+}
+
+CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *e) {
+ e = e->IgnoreParens();
+
+ // Look through function-to-pointer decay.
+ if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
+ if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
+ implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
+ return emitCallee(implicitCast->getSubExpr());
+ }
+ // Resolve direct calls.
+ } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
+ const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl());
+ assert(
+ funcDecl &&
+ "DeclRef referring to FunctionDecl is the only thing supported so far");
+ return emitDirectCallee(cgm, funcDecl);
+ }
+
+ llvm_unreachable("Nothing else supported yet!");
+}
+
+RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e) {
+ assert(!cir::MissingFeatures::objCBlocks());
+
+ if (isa<CXXMemberCallExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(), "call to member function");
+ return RValue::get(nullptr);
+ }
+
+ if (isa<CUDAKernelCallExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(), "call to CUDA kernel");
+ return RValue::get(nullptr);
+ }
+
+ if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
+ if (isa_and_nonnull<CXXMethodDecl>(operatorCall->getCalleeDecl())) {
+ cgm.errorNYI(e->getSourceRange(), "call to member operator");
+ return RValue::get(nullptr);
+ }
+ }
+
+ CIRGenCallee callee = emitCallee(e->getCallee());
+
+ assert(!cir::MissingFeatures::opCallBuiltinFunc());
+ assert(!cir::MissingFeatures::opCallPseudoDtor());
+
+ return emitCall(e->getCallee()->getType(), callee, e);
+}
+
/// Emit code to compute the specified expression, ignoring the result.
void CIRGenFunction::emitIgnoredExpr(const Expr *e) {
if (e->isPRValue()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 3863d21487531..ca6f35e0f7319 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -156,6 +156,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}
mlir::Value VisitCastExpr(CastExpr *e);
+ mlir::Value VisitCallExpr(const CallExpr *e);
mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
return VisitCastExpr(e);
@@ -1345,6 +1346,18 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
return {};
}
+mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
+ if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
+ cgf.getCIRGenModule().errorNYI(
+ e->getSourceRange(), "call to function with non-void return type");
+ return {};
+ }
+
+ auto v = cgf.emitCallExpr(e).getScalarVal();
+ assert(!cir::MissingFeatures::emitLValueAlignmentAssumption());
+ return v;
+}
+
mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
QualType srcTy, QualType dstTy,
SourceLocation loc) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 1bedbe28ae625..1a0ab51c759f5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -403,6 +403,26 @@ class CIRGenFunction : public CIRGenTypeCache {
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
+ /// An abstract representation of regular/ObjC call/message targets.
+ class AbstractCallee {
+ /// The function declaration of the callee.
+ const clang::Decl *calleeDecl;
+
+ public:
+ AbstractCallee() : calleeDecl(nullptr) {}
+ AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
+ };
+
+ RValue emitCall(const CIRGenFunctionInfo &funcInfo,
+ const CIRGenCallee &callee, cir::CIRCallOpInterface *callOp,
+ mlir::Location loc);
+ RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
+ const clang::CallExpr *e);
+
+ CIRGenCallee emitCallee(const clang::Expr *e);
+
+ RValue emitCallExpr(const clang::CallExpr *e);
+
/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location. The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
new file mode 100644
index 0000000000000..37191ee300eda
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -0,0 +1,34 @@
+//==-- CIRGenFunctionInfo.h - Representation of fn argument/return types ---==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines CIRGenFunctionInfo and associated types used in representing the
+// CIR source types and ABI-coerced types for function arguments and
+// return values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
+#define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
+
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang::CIRGen {
+
+class CIRGenFunctionInfo final : public llvm::FoldingSetNode {
+public:
+ static CIRGenFunctionInfo *create();
+
+ // NOLINTNEXTLINE(readability-identifier-naming)
+ static void Profile(llvm::FoldingSetNodeID &id) {
+ // We don't have anything to profile yet.
+ }
+};
+
+} // namespace clang::CIRGen
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index d3b3b0632c2f0..a07a1e3d52e2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@...
[truncated]
|
@llvm/pr-subscribers-clangir Author: Sirui Mu (Lancern) ChangesThis PR upstreams initial support for making function calls in CIR. Function arguments and return values are not included to keep the patch small for review. Related to #132487 Patch is 27.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/134673.diff 17 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c1e93fe790c08..dda3ecf492506 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -201,6 +201,19 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return create<cir::PtrStrideOp>(loc, base.getType(), base, stride);
}
+ //===--------------------------------------------------------------------===//
+ // Call operators
+ //===--------------------------------------------------------------------===//
+
+ cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee) {
+ auto op = create<cir::CallOp>(loc, callee);
+ return op;
+ }
+
+ cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee) {
+ return createCallOp(loc, mlir::SymbolRefAttr::get(callee));
+ }
+
//===--------------------------------------------------------------------===//
// Cast/Conversion Operators
//===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 609e60ca74b49..aa805ee4108da 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1242,6 +1242,43 @@ def FuncOp : CIR_Op<"func", [
let hasVerifier = 1;
}
+//===----------------------------------------------------------------------===//
+// CallOp
+//===----------------------------------------------------------------------===//
+
+class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []>
+ : Op<CIR_Dialect, mnemonic,
+ !listconcat(extra_traits,
+ [DeclareOpInterfaceMethods<CIRCallOpInterface>,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>])> {
+ let hasCustomAssemblyFormat = 1;
+ let skipDefaultBuilders = 1;
+ let hasVerifier = 0;
+
+ dag commonArgs = (ins FlatSymbolRefAttr:$callee);
+}
+
+def CallOp : CIR_CallOp<"call", [NoRegionArguments]> {
+ let summary = "call a function";
+ let description = [{
+ The `cir.call` operation represents a direct call to a function that is
+ within the same symbol scope as the call. The callee is encoded as a symbol
+ reference attribute named `callee`.
+
+ Example:
+
+ ```mlir
+ %0 = cir.call @foo()
+ ```
+ }];
+
+ let arguments = commonArgs;
+
+ let builders = [OpBuilder<(ins "mlir::SymbolRefAttr":$callee), [{
+ $_state.addAttribute("callee", callee);
+ }]>];
+}
+
//===----------------------------------------------------------------------===//
// UnreachableOp
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index 39ef402c59e43..c6c6356118ac6 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -15,8 +15,17 @@
include "mlir/IR/OpBase.td"
include "mlir/IR/SymbolInterfaces.td"
+include "mlir/Interfaces/CallInterfaces.td"
let cppNamespace = "::cir" in {
+ // The CIRCallOpInterface must be used instead of CallOpInterface when looking
+ // at arguments and other bits of CallOp. This creates a level of abstraction
+ // that's useful for handling indirect calls and other details.
+ def CIRCallOpInterface : OpInterface<"CIRCallOpInterface", []> {
+ // Currently we don't have any methods defined in CIRCallOpInterface. We'll
+ // add more methods as the upstreaming proceeds.
+ }
+
def CIRGlobalValueInterface
: OpInterface<"CIRGlobalValueInterface", [Symbol]> {
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 86fdaf1ddaf51..491fb31c4b7e2 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -72,6 +72,24 @@ struct MissingFeatures {
static bool opFuncLinkage() { return false; }
static bool opFuncVisibility() { return false; }
+ // CallOp handling
+ static bool opCallBuiltinFunc() { return false; }
+ static bool opCallPseudoDtor() { return false; }
+ static bool opCallArgs() { return false; }
+ static bool opCallReturn() { return false; }
+ static bool opCallArgEvaluationOrder() { return false; }
+ static bool opCallCallConv() { return false; }
+ static bool opCallSideEffect() { return false; }
+ static bool opCallChainCall() { return false; }
+ static bool opCallNoPrototypeFunc() { return false; }
+ static bool opCallMustTail() { return false; }
+ static bool opCallIndirect() { return false; }
+ static bool opCallVirtual() { return false; }
+ static bool opCallInAlloca() { return false; }
+ static bool opCallAttrs() { return false; }
+ static bool opCallSurroundingTry() { return false; }
+ static bool opCallASTAttr() { return false; }
+
// ScopeOp handling
static bool opScopeCleanupRegion() { return false; }
@@ -90,7 +108,10 @@ struct MissingFeatures {
static bool opTBAA() { return false; }
static bool opCmp() { return false; }
static bool objCLifetime() { return false; }
+ static bool objCBlocks() { return false; }
static bool emitNullabilityCheck() { return false; }
+ static bool emitLValueAlignmentAssumption() { return false; }
+ static bool emitLifetimeMarkers() { return false; }
static bool astVarDeclInterface() { return false; }
static bool stackSaveOp() { return false; }
static bool aggValueSlot() { return false; }
@@ -108,6 +129,8 @@ struct MissingFeatures {
static bool cgFPOptionsRAII() { return false; }
static bool metaDataNode() { return false; }
static bool fastMathFlags() { return false; }
+ static bool weakRefReference() { return false; }
+ static bool hip() { return false; }
// Missing types
static bool dataMemberType() { return false; }
@@ -127,6 +150,7 @@ struct MissingFeatures {
static bool complexImagOp() { return false; }
static bool complexRealOp() { return false; }
static bool ifOp() { return false; }
+ static bool invokeOp() { return false; }
static bool labelOp() { return false; }
static bool ptrDiffOp() { return false; }
static bool ptrStrideOp() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
new file mode 100644
index 0000000000000..1a936458782ea
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -0,0 +1,95 @@
+//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function definition used
+// to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenCall.h"
+#include "CIRGenFunction.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+CIRGenFunctionInfo *CIRGenFunctionInfo::create() {
+ // For now we just create an empty CIRGenFunctionInfo.
+ CIRGenFunctionInfo *fi = new CIRGenFunctionInfo();
+ return fi;
+}
+
+CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
+ assert(!cir::MissingFeatures::opCallVirtual());
+ return *this;
+}
+
+static const CIRGenFunctionInfo &arrangeFreeFunctionLikeCall(CIRGenTypes &cgt) {
+ assert(!cir::MissingFeatures::opCallArgs());
+ return cgt.arrangeCIRFunctionInfo();
+}
+
+const CIRGenFunctionInfo &CIRGenTypes::arrangeFreeFunctionCall() {
+ return arrangeFreeFunctionLikeCall(*this);
+}
+
+static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
+ mlir::Location callLoc,
+ cir::FuncOp directFuncOp) {
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+
+ assert(!cir::MissingFeatures::opCallSurroundingTry());
+ assert(!cir::MissingFeatures::invokeOp());
+
+ assert(builder.getInsertionBlock() && "expected valid basic block");
+ assert(!cir::MissingFeatures::opCallIndirect());
+
+ return builder.createCallOp(callLoc, directFuncOp);
+}
+
+RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
+ const CIRGenCallee &callee,
+ cir::CIRCallOpInterface *callOp,
+ mlir::Location loc) {
+ assert(!cir::MissingFeatures::opCallArgs());
+ assert(!cir::MissingFeatures::emitLifetimeMarkers());
+
+ const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
+ mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
+
+ assert(!cir::MissingFeatures::opCallInAlloca());
+
+ mlir::NamedAttrList attrs;
+ StringRef funcName;
+ if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
+ funcName = calleeFuncOp.getName();
+
+ assert(!cir::MissingFeatures::opCallCallConv());
+ assert(!cir::MissingFeatures::opCallSideEffect());
+ assert(!cir::MissingFeatures::opCallAttrs());
+
+ assert(!cir::MissingFeatures::invokeOp());
+
+ auto directFuncOp = dyn_cast<cir::FuncOp>(calleePtr);
+ assert(!cir::MissingFeatures::opCallIndirect());
+ assert(!cir::MissingFeatures::opCallAttrs());
+
+ cir::CIRCallOpInterface theCall = emitCallLikeOp(*this, loc, directFuncOp);
+
+ if (callOp)
+ *callOp = theCall;
+
+ assert(!cir::MissingFeatures::opCallMustTail());
+ assert(!cir::MissingFeatures::opCallReturn());
+
+ // For now we just return nothing because we don't have support for return
+ // values yet.
+ RValue ret = RValue::get(nullptr);
+
+ return ret;
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 0996167feeef6..76fefdca9e45e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -14,15 +14,73 @@
#ifndef CLANG_LIB_CODEGEN_CIRGENCALL_H
#define CLANG_LIB_CODEGEN_CIRGENCALL_H
+#include "mlir/IR/Operation.h"
#include "clang/AST/GlobalDecl.h"
#include "llvm/ADT/SmallVector.h"
namespace clang::CIRGen {
+class CIRGenFunction;
+
+/// Abstract information about a function or function prototype.
+class CIRGenCalleeInfo {
+ clang::GlobalDecl calleeDecl;
+
+public:
+ explicit CIRGenCalleeInfo() : calleeDecl() {}
+ CIRGenCalleeInfo(clang::GlobalDecl calleeDecl) : calleeDecl(calleeDecl) {}
+};
+
+class CIRGenCallee {
+ enum class SpecialKind : uintptr_t {
+ Invalid,
+
+ Last = Invalid,
+ };
+
+ SpecialKind kindOrFunctionPtr;
+
+ union {
+ CIRGenCalleeInfo abstractInfo;
+ };
+
+public:
+ CIRGenCallee() : kindOrFunctionPtr(SpecialKind::Invalid) {}
+
+ CIRGenCallee(const CIRGenCalleeInfo &abstractInfo, mlir::Operation *funcPtr)
+ : kindOrFunctionPtr(SpecialKind(reinterpret_cast<uintptr_t>(funcPtr))),
+ abstractInfo(abstractInfo) {
+ assert(funcPtr && "configuring callee without function pointer");
+ }
+
+ static CIRGenCallee
+ forDirect(mlir::Operation *funcPtr,
+ const CIRGenCalleeInfo &abstractInfo = CIRGenCalleeInfo()) {
+ return CIRGenCallee(abstractInfo, funcPtr);
+ }
+
+ bool isOrdinary() const {
+ return uintptr_t(kindOrFunctionPtr) > uintptr_t(SpecialKind::Last);
+ }
+
+ /// If this is a delayed callee computation of some sort, prepare a concrete
+ /// callee
+ CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const;
+
+ mlir::Operation *getFunctionPointer() const {
+ assert(isOrdinary());
+ return reinterpret_cast<mlir::Operation *>(kindOrFunctionPtr);
+ }
+};
+
/// Type for representing both the decl and type of parameters to a function.
/// The decl must be either a ParmVarDecl or ImplicitParamDecl.
class FunctionArgList : public llvm::SmallVector<const clang::VarDecl *, 16> {};
+struct CallArg {};
+
+class CallArgList : public llvm::SmallVector<CallArg, 8> {};
+
} // namespace clang::CIRGen
#endif // CLANG_LIB_CODEGEN_CIRGENCALL_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index f01e03a89981d..1e5fb985b0b8c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"
@@ -304,6 +305,102 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e) {
llvm_unreachable("bad evaluation kind");
}
+static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
+ assert(!cir::MissingFeatures::weakRefReference());
+ return cgm.getAddrOfFunction(gd);
+}
+
+static CIRGenCallee emitDirectCallee(CIRGenModule &cgm, GlobalDecl gd) {
+ assert(!cir::MissingFeatures::opCallBuiltinFunc());
+
+ cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
+
+ assert(!cir::MissingFeatures::hip());
+
+ return CIRGenCallee::forDirect(callee, gd);
+}
+
+RValue CIRGenFunction::emitCall(clang::QualType calleeTy,
+ const CIRGenCallee &callee,
+ const clang::CallExpr *e) {
+ // Get the actual function type. The callee type will always be a pointer to
+ // function type or a block pointer type.
+ assert(calleeTy->isFunctionPointerType() &&
+ "Callee must have function pointer type!");
+
+ calleeTy = getContext().getCanonicalType(calleeTy);
+
+ if (getLangOpts().CPlusPlus)
+ assert(!cir::MissingFeatures::sanitizers());
+
+ assert(!cir::MissingFeatures::sanitizers());
+ assert(!cir::MissingFeatures::opCallArgs());
+
+ const CIRGenFunctionInfo &funcInfo = cgm.getTypes().arrangeFreeFunctionCall();
+
+ assert(!cir::MissingFeatures::opCallNoPrototypeFunc());
+ assert(!cir::MissingFeatures::opCallChainCall());
+ assert(!cir::MissingFeatures::hip());
+ assert(!cir::MissingFeatures::opCallMustTail());
+
+ cir::CIRCallOpInterface callOp;
+ RValue callResult =
+ emitCall(funcInfo, callee, &callOp, getLoc(e->getExprLoc()));
+
+ assert(!cir::MissingFeatures::generateDebugInfo());
+
+ return callResult;
+}
+
+CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *e) {
+ e = e->IgnoreParens();
+
+ // Look through function-to-pointer decay.
+ if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
+ if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
+ implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
+ return emitCallee(implicitCast->getSubExpr());
+ }
+ // Resolve direct calls.
+ } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
+ const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl());
+ assert(
+ funcDecl &&
+ "DeclRef referring to FunctionDecl is the only thing supported so far");
+ return emitDirectCallee(cgm, funcDecl);
+ }
+
+ llvm_unreachable("Nothing else supported yet!");
+}
+
+RValue CIRGenFunction::emitCallExpr(const clang::CallExpr *e) {
+ assert(!cir::MissingFeatures::objCBlocks());
+
+ if (isa<CXXMemberCallExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(), "call to member function");
+ return RValue::get(nullptr);
+ }
+
+ if (isa<CUDAKernelCallExpr>(e)) {
+ cgm.errorNYI(e->getSourceRange(), "call to CUDA kernel");
+ return RValue::get(nullptr);
+ }
+
+ if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
+ if (isa_and_nonnull<CXXMethodDecl>(operatorCall->getCalleeDecl())) {
+ cgm.errorNYI(e->getSourceRange(), "call to member operator");
+ return RValue::get(nullptr);
+ }
+ }
+
+ CIRGenCallee callee = emitCallee(e->getCallee());
+
+ assert(!cir::MissingFeatures::opCallBuiltinFunc());
+ assert(!cir::MissingFeatures::opCallPseudoDtor());
+
+ return emitCall(e->getCallee()->getType(), callee, e);
+}
+
/// Emit code to compute the specified expression, ignoring the result.
void CIRGenFunction::emitIgnoredExpr(const Expr *e) {
if (e->isPRValue()) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 3863d21487531..ca6f35e0f7319 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -156,6 +156,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}
mlir::Value VisitCastExpr(CastExpr *e);
+ mlir::Value VisitCallExpr(const CallExpr *e);
mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
return VisitCastExpr(e);
@@ -1345,6 +1346,18 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
return {};
}
+mlir::Value ScalarExprEmitter::VisitCallExpr(const CallExpr *e) {
+ if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
+ cgf.getCIRGenModule().errorNYI(
+ e->getSourceRange(), "call to function with non-void return type");
+ return {};
+ }
+
+ auto v = cgf.emitCallExpr(e).getScalarVal();
+ assert(!cir::MissingFeatures::emitLValueAlignmentAssumption());
+ return v;
+}
+
mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src,
QualType srcTy, QualType dstTy,
SourceLocation loc) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 1bedbe28ae625..1a0ab51c759f5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -403,6 +403,26 @@ class CIRGenFunction : public CIRGenTypeCache {
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
+ /// An abstract representation of regular/ObjC call/message targets.
+ class AbstractCallee {
+ /// The function declaration of the callee.
+ const clang::Decl *calleeDecl;
+
+ public:
+ AbstractCallee() : calleeDecl(nullptr) {}
+ AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
+ };
+
+ RValue emitCall(const CIRGenFunctionInfo &funcInfo,
+ const CIRGenCallee &callee, cir::CIRCallOpInterface *callOp,
+ mlir::Location loc);
+ RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
+ const clang::CallExpr *e);
+
+ CIRGenCallee emitCallee(const clang::Expr *e);
+
+ RValue emitCallExpr(const clang::CallExpr *e);
+
/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location. The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
new file mode 100644
index 0000000000000..37191ee300eda
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -0,0 +1,34 @@
+//==-- CIRGenFunctionInfo.h - Representation of fn argument/return types ---==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines CIRGenFunctionInfo and associated types used in representing the
+// CIR source types and ABI-coerced types for function arguments and
+// return values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
+#define LLVM_CLANG_CIR_CIRGENFUNCTIONINFO_H
+
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang::CIRGen {
+
+class CIRGenFunctionInfo final : public llvm::FoldingSetNode {
+public:
+ static CIRGenFunctionInfo *create();
+
+ // NOLINTNEXTLINE(readability-identifier-naming)
+ static void Profile(llvm::FoldingSetNodeID &id) {
+ // We don't have anything to profile yet.
+ }
+};
+
+} // namespace clang::CIRGen
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index d3b3b0632c2f0..a07a1e3d52e2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. This PR introduces the skeleton and some basic support, kudos on the incremental approach, some inline comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a round trip test in clang/test/CIR/IR
to verify the parsing?
public: | ||
static CIRGenFunctionInfo *create(); | ||
|
||
// NOLINTNEXTLINE(readability-identifier-naming) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not make Profile
start with lowercase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required by llvm::FoldingSet
:
T must be a subclass of FoldingSetNode and implement a Profile function.
I'll add a brief comment explaining this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't generally insert comments like this for anything other than clang-format. It's not necessarily a bad thing to have here, but given that we're missing such support elsewhere I'm not sure how much value there is in having it here, especially since you added the comment explaining it.
8cd0b28
to
cd34ab6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, with one nit that you can choose to change or ignore.
public: | ||
static CIRGenFunctionInfo *create(); | ||
|
||
// NOLINTNEXTLINE(readability-identifier-naming) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't generally insert comments like this for anything other than clang-format. It's not necessarily a bad thing to have here, but given that we're missing such support elsewhere I'm not sure how much value there is in having it here, especially since you added the comment explaining it.
cd34ab6
to
6995ca5
Compare
Resolved conflicts. |
@bcardosolopes Are your concerns addressed with the latest version? |
@@ -0,0 +1,17 @@ | |||
// RUN: cir-opt %s | FileCheck %s | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a review item, more like a general "it will be nice comment": mlir-opt
has a --verify-roundtrip
flag, which we should add at some point to cir-opt
to make such tests can be even more robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after few extra nits
6995ca5
to
88a41a8
Compare
I'm going to merge this once the CI is green. |
This patch upstreams initial support for making function calls in CIR. Function arguments and return values are not included to keep the patch small for review. Related to llvm#132487
This PR upstreams initial support for making function calls in CIR. Function arguments and return values are not included to keep the patch small for review.
Related to #132487