1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// These classes wrap the information about a call or function
10// definition used to handle ABI compliancy.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CLANG_LIB_CODEGEN_CIRGENCALL_H
15#define CLANG_LIB_CODEGEN_CIRGENCALL_H
16
17#include "CIRGenValue.h"
18#include "mlir/IR/Operation.h"
19#include "clang/AST/GlobalDecl.h"
20#include "llvm/ADT/SmallVector.h"
21
22namespace clang::CIRGen {
23
24class CIRGenFunction;
25
26/// Abstract information about a function or function prototype.
27class CIRGenCalleeInfo {
28 const clang::FunctionProtoType *calleeProtoTy;
29 clang::GlobalDecl calleeDecl;
30
31public:
32 explicit CIRGenCalleeInfo() : calleeProtoTy(nullptr), calleeDecl() {}
33 CIRGenCalleeInfo(const clang::FunctionProtoType *calleeProtoTy,
34 clang::GlobalDecl calleeDecl)
35 : calleeProtoTy(calleeProtoTy), calleeDecl(calleeDecl) {}
36 CIRGenCalleeInfo(clang::GlobalDecl calleeDecl) : calleeDecl(calleeDecl) {}
37
38 const clang::FunctionProtoType *getCalleeFunctionProtoType() const {
39 return calleeProtoTy;
40 }
41 clang::GlobalDecl getCalleeDecl() const { return calleeDecl; }
42};
43
44class CIRGenCallee {
45 enum class SpecialKind : uintptr_t {
46 Invalid,
47 Builtin,
48
49 Last = Builtin,
50 };
51
52 struct BuiltinInfoStorage {
53 const clang::FunctionDecl *decl;
54 unsigned id;
55 };
56
57 SpecialKind kindOrFunctionPtr;
58
59 union {
60 CIRGenCalleeInfo abstractInfo;
61 BuiltinInfoStorage builtinInfo;
62 };
63
64 explicit CIRGenCallee(SpecialKind kind) : kindOrFunctionPtr(kind) {}
65
66public:
67 CIRGenCallee() : kindOrFunctionPtr(SpecialKind::Invalid) {}
68
69 CIRGenCallee(const CIRGenCalleeInfo &abstractInfo, mlir::Operation *funcPtr)
70 : kindOrFunctionPtr(SpecialKind(reinterpret_cast<uintptr_t>(funcPtr))),
71 abstractInfo(abstractInfo) {
72 assert(funcPtr && "configuring callee without function pointer");
73 }
74
75 static CIRGenCallee
76 forDirect(mlir::Operation *funcPtr,
77 const CIRGenCalleeInfo &abstractInfo = CIRGenCalleeInfo()) {
78 return CIRGenCallee(abstractInfo, funcPtr);
79 }
80
81 bool isBuiltin() const { return kindOrFunctionPtr == SpecialKind::Builtin; }
82
83 const clang::FunctionDecl *getBuiltinDecl() const {
84 assert(isBuiltin());
85 return builtinInfo.decl;
86 }
87 unsigned getBuiltinID() const {
88 assert(isBuiltin());
89 return builtinInfo.id;
90 }
91
92 static CIRGenCallee forBuiltin(unsigned builtinID,
93 const clang::FunctionDecl *builtinDecl) {
94 CIRGenCallee result(SpecialKind::Builtin);
95 result.builtinInfo.decl = builtinDecl;
96 result.builtinInfo.id = builtinID;
97 return result;
98 }
99
100 bool isOrdinary() const {
101 return uintptr_t(kindOrFunctionPtr) > uintptr_t(SpecialKind::Last);
102 }
103
104 /// If this is a delayed callee computation of some sort, prepare a concrete
105 /// callee
106 CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const;
107
108 mlir::Operation *getFunctionPointer() const {
109 assert(isOrdinary());
110 return reinterpret_cast<mlir::Operation *>(kindOrFunctionPtr);
111 }
112};
113
114/// Type for representing both the decl and type of parameters to a function.
115/// The decl must be either a ParmVarDecl or ImplicitParamDecl.
116class FunctionArgList : public llvm::SmallVector<const clang::VarDecl *, 16> {};
117
118struct CallArg {
119private:
120 union {
121 RValue rv;
122 LValue lv; // This argument is semantically a load from this l-value
123 };
124 bool hasLV;
125
126 /// A data-flow flag to make sure getRValue and/or copyInto are not
127 /// called twice for duplicated IR emission.
128 mutable bool isUsed;
129
130public:
131 clang::QualType ty;
132
133 CallArg(RValue rv, clang::QualType ty)
134 : rv(rv), hasLV(false), isUsed(false), ty(ty) {}
135
136 bool hasLValue() const { return hasLV; }
137
138 RValue getKnownRValue() const {
139 assert(!hasLV && !isUsed);
140 return rv;
141 }
142
143 bool isAggregate() const { return hasLV || rv.isAggregate(); }
144};
145
146class CallArgList : public llvm::SmallVector<CallArg, 8> {
147public:
148 void add(RValue rvalue, clang::QualType type) { emplace_back(Args&: rvalue, Args&: type); }
149
150 /// Add all the arguments from another CallArgList to this one. After doing
151 /// this, the old CallArgList retains its list of arguments, but must not
152 /// be used to emit a call.
153 void addFrom(const CallArgList &other) {
154 insert(I: end(), From: other.begin(), To: other.end());
155 // Classic codegen has handling for these here. We may not need it here for
156 // CIR, but if not we should implement equivalent handling in lowering.
157 assert(!cir::MissingFeatures::writebacks());
158 assert(!cir::MissingFeatures::cleanupsToDeactivate());
159 assert(!cir::MissingFeatures::stackBase());
160 }
161};
162
163/// Contains the address where the return value of a function can be stored, and
164/// whether the address is volatile or not.
165class ReturnValueSlot {};
166
167} // namespace clang::CIRGen
168
169#endif // CLANG_LIB_CODEGEN_CIRGENCALL_H
170

source code of clang/lib/CIR/CodeGen/CIRGenCall.h