Clang Project

clang_source_code/lib/CodeGen/CGCall.h
1//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
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 LLVM_CLANG_LIB_CODEGEN_CGCALL_H
15#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
16
17#include "CGValue.h"
18#include "EHScopeStack.h"
19#include "clang/AST/CanonicalType.h"
20#include "clang/AST/GlobalDecl.h"
21#include "clang/AST/Type.h"
22#include "llvm/IR/Value.h"
23
24// FIXME: Restructure so we don't have to expose so much stuff.
25#include "ABIInfo.h"
26
27namespace llvm {
28class AttributeList;
29class Function;
30class Type;
31class Value;
32}
33
34namespace clang {
35  class ASTContext;
36  class Decl;
37  class FunctionDecl;
38  class ObjCMethodDecl;
39  class VarDecl;
40
41namespace CodeGen {
42
43/// Abstract information about a function or function prototype.
44class CGCalleeInfo {
45  /// The function prototype of the callee.
46  const FunctionProtoType *CalleeProtoTy;
47  /// The function declaration of the callee.
48  GlobalDecl CalleeDecl;
49
50public:
51  explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {}
52  CGCalleeInfo(const FunctionProtoType *calleeProtoTyGlobalDecl calleeDecl)
53      : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
54  CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
55      : CalleeProtoTy(calleeProtoTy), CalleeDecl() {}
56  CGCalleeInfo(GlobalDecl calleeDecl)
57      : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
58
59  const FunctionProtoType *getCalleeFunctionProtoType() const {
60    return CalleeProtoTy;
61  }
62  const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
63  };
64
65  /// All available information about a concrete callee.
66  class CGCallee {
67    enum class SpecialKind : uintptr_t {
68      Invalid,
69      Builtin,
70      PseudoDestructor,
71      Virtual,
72
73      Last = Virtual
74    };
75
76    struct BuiltinInfoStorage {
77      const FunctionDecl *Decl;
78      unsigned ID;
79    };
80    struct PseudoDestructorInfoStorage {
81      const CXXPseudoDestructorExpr *Expr;
82    };
83    struct VirtualInfoStorage {
84      const CallExpr *CE;
85      GlobalDecl MD;
86      Address Addr;
87      llvm::FunctionType *FTy;
88    };
89
90    SpecialKind KindOrFunctionPointer;
91    union {
92      CGCalleeInfo AbstractInfo;
93      BuiltinInfoStorage BuiltinInfo;
94      PseudoDestructorInfoStorage PseudoDestructorInfo;
95      VirtualInfoStorage VirtualInfo;
96    };
97
98    explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
99
100    CGCallee(const FunctionDecl *builtinDeclunsigned builtinID)
101        : KindOrFunctionPointer(SpecialKind::Builtin) {
102      BuiltinInfo.Decl = builtinDecl;
103      BuiltinInfo.ID = builtinID;
104    }
105
106  public:
107    CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
108
109    /// Construct a callee.  Call this constructor directly when this
110    /// isn't a direct call.
111    CGCallee(const CGCalleeInfo &abstractInfollvm::Value *functionPtr)
112        : KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) {
113      AbstractInfo = abstractInfo;
114       (0) . __assert_fail ("functionPtr && \"configuring callee without function pointer\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 114, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(functionPtr && "configuring callee without function pointer");
115      getType()->isPointerTy()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 115, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(functionPtr->getType()->isPointerTy());
116      getType()->getPointerElementType()->isFunctionTy()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 116, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(functionPtr->getType()->getPointerElementType()->isFunctionTy());
117    }
118
119    static CGCallee forBuiltin(unsigned builtinID,
120                               const FunctionDecl *builtinDecl) {
121      CGCallee result(SpecialKind::Builtin);
122      result.BuiltinInfo.Decl = builtinDecl;
123      result.BuiltinInfo.ID = builtinID;
124      return result;
125    }
126
127    static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
128      CGCallee result(SpecialKind::PseudoDestructor);
129      result.PseudoDestructorInfo.Expr = E;
130      return result;
131    }
132
133    static CGCallee forDirect(llvm::Constant *functionPtr,
134                        const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
135      return CGCallee(abstractInfofunctionPtr);
136    }
137
138    static CGCallee
139    forDirect(llvm::FunctionCallee functionPtr,
140              const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
141      return CGCallee(abstractInfo, functionPtr.getCallee());
142    }
143
144    static CGCallee forVirtual(const CallExpr *CEGlobalDecl MDAddress Addr,
145                               llvm::FunctionType *FTy) {
146      CGCallee result(SpecialKind::Virtual);
147      result.VirtualInfo.CE = CE;
148      result.VirtualInfo.MD = MD;
149      result.VirtualInfo.Addr = Addr;
150      result.VirtualInfo.FTy = FTy;
151      return result;
152    }
153
154    bool isBuiltin() const {
155      return KindOrFunctionPointer == SpecialKind::Builtin;
156    }
157    const FunctionDecl *getBuiltinDecl() const {
158      assert(isBuiltin());
159      return BuiltinInfo.Decl;
160    }
161    unsigned getBuiltinID() const {
162      assert(isBuiltin());
163      return BuiltinInfo.ID;
164    }
165
166    bool isPseudoDestructor() const {
167      return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
168    }
169    const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
170      assert(isPseudoDestructor());
171      return PseudoDestructorInfo.Expr;
172    }
173
174    bool isOrdinary() const {
175      return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
176    }
177    CGCalleeInfo getAbstractInfo() const {
178      if (isVirtual())
179        return VirtualInfo.MD;
180      assert(isOrdinary());
181      return AbstractInfo;
182    }
183    llvm::Value *getFunctionPointer() const {
184      assert(isOrdinary());
185      return reinterpret_cast<llvm::Value*>(uintptr_t(KindOrFunctionPointer));
186    }
187    void setFunctionPointer(llvm::Value *functionPtr) {
188      assert(isOrdinary());
189      KindOrFunctionPointer = SpecialKind(uintptr_t(functionPtr));
190    }
191
192    bool isVirtual() const {
193      return KindOrFunctionPointer == SpecialKind::Virtual;
194    }
195    const CallExpr *getVirtualCallExpr() const {
196      assert(isVirtual());
197      return VirtualInfo.CE;
198    }
199    GlobalDecl getVirtualMethodDecl() const {
200      assert(isVirtual());
201      return VirtualInfo.MD;
202    }
203    Address getThisAddress() const {
204      assert(isVirtual());
205      return VirtualInfo.Addr;
206    }
207    llvm::FunctionType *getVirtualFunctionType() const {
208      assert(isVirtual());
209      return VirtualInfo.FTy;
210    }
211
212    /// If this is a delayed callee computation of some sort, prepare
213    /// a concrete callee.
214    CGCallee prepareConcreteCallee(CodeGenFunction &CGFconst;
215  };
216
217  struct CallArg {
218  private:
219    union {
220      RValue RV;
221      LValue LV/// The argument is semantically a load from this l-value.
222    };
223    bool HasLV;
224
225    /// A data-flow flag to make sure getRValue and/or copyInto are not
226    /// called twice for duplicated IR emission.
227    mutable bool IsUsed;
228
229  public:
230    QualType Ty;
231    CallArg(RValue rvQualType ty)
232        : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
233    CallArg(LValue lvQualType ty)
234        : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
235    bool hasLValue() const { return HasLV; }
236    QualType getType() const { return Ty; }
237
238    /// \returns an independent RValue. If the CallArg contains an LValue,
239    /// a temporary copy is returned.
240    RValue getRValue(CodeGenFunction &CGFconst;
241
242    LValue getKnownLValue() const {
243      assert(HasLV && !IsUsed);
244      return LV;
245    }
246    RValue getKnownRValue() const {
247      assert(!HasLV && !IsUsed);
248      return RV;
249    }
250    void setRValue(RValue _RV) {
251      assert(!HasLV);
252      RV = _RV;
253    }
254
255    bool isAggregate() const { return HasLV || RV.isAggregate(); }
256
257    void copyInto(CodeGenFunction &CGFAddress Aconst;
258  };
259
260  /// CallArgList - Type for representing both the value and type of
261  /// arguments in a call.
262  class CallArgList :
263    public SmallVector<CallArg, 8> {
264  public:
265    CallArgList() : StackBase(nullptr) {}
266
267    struct Writeback {
268      /// The original argument.  Note that the argument l-value
269      /// is potentially null.
270      LValue Source;
271
272      /// The temporary alloca.
273      Address Temporary;
274
275      /// A value to "use" after the writeback, or null.
276      llvm::Value *ToUse;
277    };
278
279    struct CallArgCleanup {
280      EHScopeStack::stable_iterator Cleanup;
281
282      /// The "is active" insertion point.  This instruction is temporary and
283      /// will be removed after insertion.
284      llvm::Instruction *IsActiveIP;
285    };
286
287    void add(RValue rvalueQualType type) { push_back(CallArg(rvaluetype)); }
288
289    void addUncopiedAggregate(LValue LVQualType type) {
290      push_back(CallArg(LVtype));
291    }
292
293    /// Add all the arguments from another CallArgList to this one. After doing
294    /// this, the old CallArgList retains its list of arguments, but must not
295    /// be used to emit a call.
296    void addFrom(const CallArgList &other) {
297      insert(end(), other.begin(), other.end());
298      Writebacks.insert(Writebacks.end(),
299                        other.Writebacks.begin(), other.Writebacks.end());
300      CleanupsToDeactivate.insert(CleanupsToDeactivate.end(),
301                                  other.CleanupsToDeactivate.begin(),
302                                  other.CleanupsToDeactivate.end());
303       (0) . __assert_fail ("!(StackBase && other.StackBase) && \"can't merge stackbases\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCall.h", 303, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!(StackBase && other.StackBase) && "can't merge stackbases");
304      if (!StackBase)
305        StackBase = other.StackBase;
306    }
307
308    void addWriteback(LValue srcLVAddress temporary,
309                      llvm::Value *toUse) {
310      Writeback writeback = { srcLVtemporarytoUse };
311      Writebacks.push_back(writeback);
312    }
313
314    bool hasWritebacks() const { return !Writebacks.empty(); }
315
316    typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>
317      writeback_const_range;
318
319    writeback_const_range writebacks() const {
320      return writeback_const_range(Writebacks.begin(), Writebacks.end());
321    }
322
323    void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,
324                                   llvm::Instruction *IsActiveIP) {
325      CallArgCleanup ArgCleanup;
326      ArgCleanup.Cleanup = Cleanup;
327      ArgCleanup.IsActiveIP = IsActiveIP;
328      CleanupsToDeactivate.push_back(ArgCleanup);
329    }
330
331    ArrayRef<CallArgCleanupgetCleanupsToDeactivate() const {
332      return CleanupsToDeactivate;
333    }
334
335    void allocateArgumentMemory(CodeGenFunction &CGF);
336    llvm::Instruction *getStackBase() const { return StackBase; }
337    void freeArgumentMemory(CodeGenFunction &CGFconst;
338
339    /// Returns if we're using an inalloca struct to pass arguments in
340    /// memory.
341    bool isUsingInAlloca() const { return StackBase; }
342
343  private:
344    SmallVector<Writeback1Writebacks;
345
346    /// Deactivate these cleanups immediately before making the call.  This
347    /// is used to cleanup objects that are owned by the callee once the call
348    /// occurs.
349    SmallVector<CallArgCleanup1CleanupsToDeactivate;
350
351    /// The stacksave call.  It dominates all of the argument evaluation.
352    llvm::CallInst *StackBase;
353  };
354
355  /// FunctionArgList - Type for representing both the decl and type
356  /// of parameters to a function. The decl must be either a
357  /// ParmVarDecl or ImplicitParamDecl.
358  class FunctionArgList : public SmallVector<const VarDecl*, 16> {
359  };
360
361  /// ReturnValueSlot - Contains the address where the return value of a
362  /// function can be stored, and whether the address is volatile or not.
363  class ReturnValueSlot {
364    llvm::PointerIntPair<llvm::Value *, 2unsigned intValue;
365    CharUnits Alignment;
366
367    // Return value slot flags
368    enum Flags {
369      IS_VOLATILE = 0x1,
370      IS_UNUSED = 0x2,
371    };
372
373  public:
374    ReturnValueSlot() {}
375    ReturnValueSlot(Address Addrbool IsVolatilebool IsUnused = false)
376      : Value(Addr.isValid() ? Addr.getPointer() : nullptr,
377              (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)),
378        Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}
379
380    bool isNull() const { return !getValue().isValid(); }
381
382    bool isVolatile() const { return Value.getInt() & IS_VOLATILE; }
383    Address getValue() const { return Address(Value.getPointer(), Alignment); }
384    bool isUnused() const { return Value.getInt() & IS_UNUSED; }
385  };
386
387}  // end namespace CodeGen
388}  // end namespace clang
389
390#endif
391
clang::CodeGen::CGCalleeInfo::CalleeProtoTy
clang::CodeGen::CGCalleeInfo::CalleeDecl
clang::CodeGen::CGCalleeInfo::getCalleeFunctionProtoType
clang::CodeGen::CGCalleeInfo::getCalleeDecl
clang::CodeGen::CGCallee::SpecialKind
clang::CodeGen::CGCallee::BuiltinInfoStorage
clang::CodeGen::CGCallee::BuiltinInfoStorage::Decl
clang::CodeGen::CGCallee::BuiltinInfoStorage::ID
clang::CodeGen::CGCallee::PseudoDestructorInfoStorage
clang::CodeGen::CGCallee::PseudoDestructorInfoStorage::Expr
clang::CodeGen::CGCallee::VirtualInfoStorage
clang::CodeGen::CGCallee::VirtualInfoStorage::CE
clang::CodeGen::CGCallee::VirtualInfoStorage::MD
clang::CodeGen::CGCallee::VirtualInfoStorage::Addr
clang::CodeGen::CGCallee::VirtualInfoStorage::FTy
clang::CodeGen::CGCallee::KindOrFunctionPointer
clang::CodeGen::CGCallee::(anonymous union)::AbstractInfo
clang::CodeGen::CGCallee::(anonymous union)::BuiltinInfo
clang::CodeGen::CGCallee::(anonymous union)::PseudoDestructorInfo
clang::CodeGen::CGCallee::(anonymous union)::VirtualInfo
clang::CodeGen::CGCallee::forBuiltin
clang::CodeGen::CGCallee::forPseudoDestructor
clang::CodeGen::CGCallee::forDirect
clang::CodeGen::CGCallee::forDirect
clang::CodeGen::CGCallee::forVirtual
clang::CodeGen::CGCallee::isBuiltin
clang::CodeGen::CGCallee::getBuiltinDecl
clang::CodeGen::CGCallee::getBuiltinID
clang::CodeGen::CGCallee::isPseudoDestructor
clang::CodeGen::CGCallee::getPseudoDestructorExpr
clang::CodeGen::CGCallee::isOrdinary
clang::CodeGen::CGCallee::getAbstractInfo
clang::CodeGen::CGCallee::getFunctionPointer
clang::CodeGen::CGCallee::setFunctionPointer
clang::CodeGen::CGCallee::isVirtual
clang::CodeGen::CGCallee::getVirtualCallExpr
clang::CodeGen::CGCallee::getVirtualMethodDecl
clang::CodeGen::CGCallee::getThisAddress
clang::CodeGen::CGCallee::getVirtualFunctionType
clang::CodeGen::CGCallee::prepareConcreteCallee
clang::CodeGen::CallArg::(anonymous union)::RV
clang::CodeGen::CallArg::(anonymous union)::LV
clang::CodeGen::CallArg::HasLV
clang::CodeGen::CallArg::IsUsed
clang::CodeGen::CallArg::Ty
clang::CodeGen::CallArg::hasLValue
clang::CodeGen::CallArg::getType
clang::CodeGen::CallArg::getRValue
clang::CodeGen::CallArg::getKnownLValue
clang::CodeGen::CallArg::getKnownRValue
clang::CodeGen::CallArg::setRValue
clang::CodeGen::CallArg::isAggregate
clang::CodeGen::CallArg::copyInto
clang::CodeGen::CallArgList::Writeback
clang::CodeGen::CallArgList::Writeback::Source
clang::CodeGen::CallArgList::Writeback::Temporary
clang::CodeGen::CallArgList::Writeback::ToUse
clang::CodeGen::CallArgList::CallArgCleanup
clang::CodeGen::CallArgList::CallArgCleanup::Cleanup
clang::CodeGen::CallArgList::CallArgCleanup::IsActiveIP
clang::CodeGen::CallArgList::add
clang::CodeGen::CallArgList::addUncopiedAggregate
clang::CodeGen::CallArgList::addFrom
clang::CodeGen::CallArgList::addWriteback
clang::CodeGen::CallArgList::hasWritebacks
clang::CodeGen::CallArgList::writebacks
clang::CodeGen::CallArgList::addArgCleanupDeactivation
clang::CodeGen::CallArgList::getCleanupsToDeactivate
clang::CodeGen::CallArgList::allocateArgumentMemory
clang::CodeGen::CallArgList::getStackBase
clang::CodeGen::CallArgList::freeArgumentMemory
clang::CodeGen::CallArgList::isUsingInAlloca
clang::CodeGen::CallArgList::Writebacks
clang::CodeGen::CallArgList::CleanupsToDeactivate
clang::CodeGen::CallArgList::StackBase
clang::CodeGen::ReturnValueSlot::Value
clang::CodeGen::ReturnValueSlot::Alignment
clang::CodeGen::ReturnValueSlot::Flags
clang::CodeGen::ReturnValueSlot::isNull
clang::CodeGen::ReturnValueSlot::isVolatile
clang::CodeGen::ReturnValueSlot::getValue
clang::CodeGen::ReturnValueSlot::isUnused
clang::CodeGen::CallArgList::addArgCleanupDeactivation
clang::CodeGen::CGCallee::forVirtual