Home | History | Annotate | Line # | Download | only in CodeGen
      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/ASTFwd.h"
     20 #include "clang/AST/CanonicalType.h"
     21 #include "clang/AST/GlobalDecl.h"
     22 #include "clang/AST/Type.h"
     23 #include "llvm/IR/Value.h"
     24 
     25 // FIXME: Restructure so we don't have to expose so much stuff.
     26 #include "ABIInfo.h"
     27 
     28 namespace llvm {
     29 class AttributeList;
     30 class Function;
     31 class Type;
     32 class Value;
     33 } // namespace llvm
     34 
     35 namespace clang {
     36 class ASTContext;
     37 class Decl;
     38 class FunctionDecl;
     39 class ObjCMethodDecl;
     40 class VarDecl;
     41 
     42 namespace CodeGen {
     43 
     44 /// Abstract information about a function or function prototype.
     45 class CGCalleeInfo {
     46   /// The function prototype of the callee.
     47   const FunctionProtoType *CalleeProtoTy;
     48   /// The function declaration of the callee.
     49   GlobalDecl CalleeDecl;
     50 
     51 public:
     52   explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {}
     53   CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)
     54       : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
     55   CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
     56       : CalleeProtoTy(calleeProtoTy), CalleeDecl() {}
     57   CGCalleeInfo(GlobalDecl calleeDecl)
     58       : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
     59 
     60   const FunctionProtoType *getCalleeFunctionProtoType() const {
     61     return CalleeProtoTy;
     62   }
     63   const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
     64 };
     65 
     66 /// All available information about a concrete callee.
     67 class CGCallee {
     68   enum class SpecialKind : uintptr_t {
     69     Invalid,
     70     Builtin,
     71     PseudoDestructor,
     72     Virtual,
     73 
     74     Last = Virtual
     75   };
     76 
     77   struct BuiltinInfoStorage {
     78     const FunctionDecl *Decl;
     79     unsigned ID;
     80   };
     81   struct PseudoDestructorInfoStorage {
     82     const CXXPseudoDestructorExpr *Expr;
     83   };
     84   struct VirtualInfoStorage {
     85     const CallExpr *CE;
     86     GlobalDecl MD;
     87     Address Addr;
     88     llvm::FunctionType *FTy;
     89   };
     90 
     91   SpecialKind KindOrFunctionPointer;
     92   union {
     93     CGCalleeInfo AbstractInfo;
     94     BuiltinInfoStorage BuiltinInfo;
     95     PseudoDestructorInfoStorage PseudoDestructorInfo;
     96     VirtualInfoStorage VirtualInfo;
     97   };
     98 
     99   explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
    100 
    101   CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)
    102       : KindOrFunctionPointer(SpecialKind::Builtin) {
    103     BuiltinInfo.Decl = builtinDecl;
    104     BuiltinInfo.ID = builtinID;
    105   }
    106 
    107 public:
    108   CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
    109 
    110   /// Construct a callee.  Call this constructor directly when this
    111   /// isn't a direct call.
    112   CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
    113       : KindOrFunctionPointer(
    114             SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
    115     AbstractInfo = abstractInfo;
    116     assert(functionPtr && "configuring callee without function pointer");
    117     assert(functionPtr->getType()->isPointerTy());
    118     assert(functionPtr->getType()->getPointerElementType()->isFunctionTy());
    119   }
    120 
    121   static CGCallee forBuiltin(unsigned builtinID,
    122                              const FunctionDecl *builtinDecl) {
    123     CGCallee result(SpecialKind::Builtin);
    124     result.BuiltinInfo.Decl = builtinDecl;
    125     result.BuiltinInfo.ID = builtinID;
    126     return result;
    127   }
    128 
    129   static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
    130     CGCallee result(SpecialKind::PseudoDestructor);
    131     result.PseudoDestructorInfo.Expr = E;
    132     return result;
    133   }
    134 
    135   static CGCallee forDirect(llvm::Constant *functionPtr,
    136                             const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
    137     return CGCallee(abstractInfo, functionPtr);
    138   }
    139 
    140   static CGCallee forDirect(llvm::FunctionCallee functionPtr,
    141                             const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
    142     return CGCallee(abstractInfo, functionPtr.getCallee());
    143   }
    144 
    145   static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
    146                              llvm::FunctionType *FTy) {
    147     CGCallee result(SpecialKind::Virtual);
    148     result.VirtualInfo.CE = CE;
    149     result.VirtualInfo.MD = MD;
    150     result.VirtualInfo.Addr = Addr;
    151     result.VirtualInfo.FTy = FTy;
    152     return result;
    153   }
    154 
    155   bool isBuiltin() const {
    156     return KindOrFunctionPointer == SpecialKind::Builtin;
    157   }
    158   const FunctionDecl *getBuiltinDecl() const {
    159     assert(isBuiltin());
    160     return BuiltinInfo.Decl;
    161   }
    162   unsigned getBuiltinID() const {
    163     assert(isBuiltin());
    164     return BuiltinInfo.ID;
    165   }
    166 
    167   bool isPseudoDestructor() const {
    168     return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
    169   }
    170   const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
    171     assert(isPseudoDestructor());
    172     return PseudoDestructorInfo.Expr;
    173   }
    174 
    175   bool isOrdinary() const {
    176     return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
    177   }
    178   CGCalleeInfo getAbstractInfo() const {
    179     if (isVirtual())
    180       return VirtualInfo.MD;
    181     assert(isOrdinary());
    182     return AbstractInfo;
    183   }
    184   llvm::Value *getFunctionPointer() const {
    185     assert(isOrdinary());
    186     return reinterpret_cast<llvm::Value *>(uintptr_t(KindOrFunctionPointer));
    187   }
    188   void setFunctionPointer(llvm::Value *functionPtr) {
    189     assert(isOrdinary());
    190     KindOrFunctionPointer =
    191         SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
    192   }
    193 
    194   bool isVirtual() const {
    195     return KindOrFunctionPointer == SpecialKind::Virtual;
    196   }
    197   const CallExpr *getVirtualCallExpr() const {
    198     assert(isVirtual());
    199     return VirtualInfo.CE;
    200   }
    201   GlobalDecl getVirtualMethodDecl() const {
    202     assert(isVirtual());
    203     return VirtualInfo.MD;
    204   }
    205   Address getThisAddress() const {
    206     assert(isVirtual());
    207     return VirtualInfo.Addr;
    208   }
    209   llvm::FunctionType *getVirtualFunctionType() const {
    210     assert(isVirtual());
    211     return VirtualInfo.FTy;
    212   }
    213 
    214   /// If this is a delayed callee computation of some sort, prepare
    215   /// a concrete callee.
    216   CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;
    217 };
    218 
    219 struct CallArg {
    220 private:
    221   union {
    222     RValue RV;
    223     LValue LV; /// The argument is semantically a load from this l-value.
    224   };
    225   bool HasLV;
    226 
    227   /// A data-flow flag to make sure getRValue and/or copyInto are not
    228   /// called twice for duplicated IR emission.
    229   mutable bool IsUsed;
    230 
    231 public:
    232   QualType Ty;
    233   CallArg(RValue rv, QualType ty)
    234       : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
    235   CallArg(LValue lv, QualType ty)
    236       : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
    237   bool hasLValue() const { return HasLV; }
    238   QualType getType() const { return Ty; }
    239 
    240   /// \returns an independent RValue. If the CallArg contains an LValue,
    241   /// a temporary copy is returned.
    242   RValue getRValue(CodeGenFunction &CGF) const;
    243 
    244   LValue getKnownLValue() const {
    245     assert(HasLV && !IsUsed);
    246     return LV;
    247   }
    248   RValue getKnownRValue() const {
    249     assert(!HasLV && !IsUsed);
    250     return RV;
    251   }
    252   void setRValue(RValue _RV) {
    253     assert(!HasLV);
    254     RV = _RV;
    255   }
    256 
    257   bool isAggregate() const { return HasLV || RV.isAggregate(); }
    258 
    259   void copyInto(CodeGenFunction &CGF, Address A) const;
    260 };
    261 
    262 /// CallArgList - Type for representing both the value and type of
    263 /// arguments in a call.
    264 class CallArgList : public SmallVector<CallArg, 8> {
    265 public:
    266   CallArgList() : StackBase(nullptr) {}
    267 
    268   struct Writeback {
    269     /// The original argument.  Note that the argument l-value
    270     /// is potentially null.
    271     LValue Source;
    272 
    273     /// The temporary alloca.
    274     Address Temporary;
    275 
    276     /// A value to "use" after the writeback, or null.
    277     llvm::Value *ToUse;
    278   };
    279 
    280   struct CallArgCleanup {
    281     EHScopeStack::stable_iterator Cleanup;
    282 
    283     /// The "is active" insertion point.  This instruction is temporary and
    284     /// will be removed after insertion.
    285     llvm::Instruction *IsActiveIP;
    286   };
    287 
    288   void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }
    289 
    290   void addUncopiedAggregate(LValue LV, QualType type) {
    291     push_back(CallArg(LV, type));
    292   }
    293 
    294   /// Add all the arguments from another CallArgList to this one. After doing
    295   /// this, the old CallArgList retains its list of arguments, but must not
    296   /// be used to emit a call.
    297   void addFrom(const CallArgList &other) {
    298     insert(end(), other.begin(), other.end());
    299     Writebacks.insert(Writebacks.end(), other.Writebacks.begin(),
    300                       other.Writebacks.end());
    301     CleanupsToDeactivate.insert(CleanupsToDeactivate.end(),
    302                                 other.CleanupsToDeactivate.begin(),
    303                                 other.CleanupsToDeactivate.end());
    304     assert(!(StackBase && other.StackBase) && "can't merge stackbases");
    305     if (!StackBase)
    306       StackBase = other.StackBase;
    307   }
    308 
    309   void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse) {
    310     Writeback writeback = {srcLV, temporary, toUse};
    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<CallArgCleanup> getCleanupsToDeactivate() const {
    332     return CleanupsToDeactivate;
    333   }
    334 
    335   void allocateArgumentMemory(CodeGenFunction &CGF);
    336   llvm::Instruction *getStackBase() const { return StackBase; }
    337   void freeArgumentMemory(CodeGenFunction &CGF) const;
    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<Writeback, 1> Writebacks;
    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<CallArgCleanup, 1> CleanupsToDeactivate;
    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 /// ReturnValueSlot - Contains the address where the return value of a
    361 /// function can be stored, and whether the address is volatile or not.
    362 class ReturnValueSlot {
    363   Address Addr = Address::invalid();
    364 
    365   // Return value slot flags
    366   unsigned IsVolatile : 1;
    367   unsigned IsUnused : 1;
    368   unsigned IsExternallyDestructed : 1;
    369 
    370 public:
    371   ReturnValueSlot()
    372       : IsVolatile(false), IsUnused(false), IsExternallyDestructed(false) {}
    373   ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false,
    374                   bool IsExternallyDestructed = false)
    375       : Addr(Addr), IsVolatile(IsVolatile), IsUnused(IsUnused),
    376         IsExternallyDestructed(IsExternallyDestructed) {}
    377 
    378   bool isNull() const { return !Addr.isValid(); }
    379   bool isVolatile() const { return IsVolatile; }
    380   Address getValue() const { return Addr; }
    381   bool isUnused() const { return IsUnused; }
    382   bool isExternallyDestructed() const { return IsExternallyDestructed; }
    383 };
    384 
    385 } // end namespace CodeGen
    386 } // end namespace clang
    387 
    388 #endif
    389