brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.5 KiB · 1ef8a3f Raw
466 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// These classes wrap the information about a call or function10// definition used to handle ABI compliancy.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H15#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H16 17#include "CGPointerAuthInfo.h"18#include "CGValue.h"19#include "EHScopeStack.h"20#include "clang/AST/ASTFwd.h"21#include "clang/AST/CanonicalType.h"22#include "clang/AST/GlobalDecl.h"23#include "clang/AST/Type.h"24#include "llvm/ADT/STLForwardCompat.h"25#include "llvm/IR/Value.h"26 27namespace llvm {28class Type;29class Value;30} // namespace llvm31 32namespace clang {33class Decl;34class FunctionDecl;35class TargetOptions;36class VarDecl;37 38namespace CodeGen {39 40/// Abstract information about a function or function prototype.41class CGCalleeInfo {42  /// The function prototype of the callee.43  const FunctionProtoType *CalleeProtoTy;44  /// The function declaration of the callee.45  GlobalDecl CalleeDecl;46 47public:48  explicit CGCalleeInfo() : CalleeProtoTy(nullptr) {}49  CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)50      : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}51  CGCalleeInfo(const FunctionProtoType *calleeProtoTy)52      : CalleeProtoTy(calleeProtoTy) {}53  CGCalleeInfo(GlobalDecl calleeDecl)54      : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}55 56  const FunctionProtoType *getCalleeFunctionProtoType() const {57    return CalleeProtoTy;58  }59  const GlobalDecl getCalleeDecl() const { return CalleeDecl; }60};61 62/// All available information about a concrete callee.63class CGCallee {64  enum class SpecialKind : uintptr_t {65    Invalid,66    Builtin,67    PseudoDestructor,68    Virtual,69 70    Last = Virtual71  };72 73  struct OrdinaryInfoStorage {74    CGCalleeInfo AbstractInfo;75    CGPointerAuthInfo PointerAuthInfo;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    OrdinaryInfoStorage OrdinaryInfo;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 107public:108  CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}109 110  /// Construct a callee.  Call this constructor directly when this111  /// isn't a direct call.112  CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,113           /* FIXME: make parameter pointerAuthInfo mandatory */114           const CGPointerAuthInfo &pointerAuthInfo = CGPointerAuthInfo())115      : KindOrFunctionPointer(116            SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {117    OrdinaryInfo.AbstractInfo = abstractInfo;118    OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;119    assert(functionPtr && "configuring callee without function pointer");120    assert(functionPtr->getType()->isPointerTy());121  }122 123  static CGCallee forBuiltin(unsigned builtinID,124                             const FunctionDecl *builtinDecl) {125    CGCallee result(SpecialKind::Builtin);126    result.BuiltinInfo.Decl = builtinDecl;127    result.BuiltinInfo.ID = builtinID;128    return result;129  }130 131  static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {132    CGCallee result(SpecialKind::PseudoDestructor);133    result.PseudoDestructorInfo.Expr = E;134    return result;135  }136 137  static CGCallee forDirect(llvm::Constant *functionPtr,138                            const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {139    return CGCallee(abstractInfo, functionPtr);140  }141 142  static CGCallee forDirect(llvm::FunctionCallee functionPtr,143                            const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {144    return CGCallee(abstractInfo, functionPtr.getCallee());145  }146 147  static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,148                             llvm::FunctionType *FTy) {149    CGCallee result(SpecialKind::Virtual);150    result.VirtualInfo.CE = CE;151    result.VirtualInfo.MD = MD;152    result.VirtualInfo.Addr = Addr;153    result.VirtualInfo.FTy = FTy;154    return result;155  }156 157  bool isBuiltin() const {158    return KindOrFunctionPointer == SpecialKind::Builtin;159  }160  const FunctionDecl *getBuiltinDecl() const {161    assert(isBuiltin());162    return BuiltinInfo.Decl;163  }164  unsigned getBuiltinID() const {165    assert(isBuiltin());166    return BuiltinInfo.ID;167  }168 169  bool isPseudoDestructor() const {170    return KindOrFunctionPointer == SpecialKind::PseudoDestructor;171  }172  const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {173    assert(isPseudoDestructor());174    return PseudoDestructorInfo.Expr;175  }176 177  bool isOrdinary() const {178    return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);179  }180  CGCalleeInfo getAbstractInfo() const {181    if (isVirtual())182      return VirtualInfo.MD;183    assert(isOrdinary());184    return OrdinaryInfo.AbstractInfo;185  }186  const CGPointerAuthInfo &getPointerAuthInfo() const {187    assert(isOrdinary());188    return OrdinaryInfo.PointerAuthInfo;189  }190  llvm::Value *getFunctionPointer() const {191    assert(isOrdinary());192    return reinterpret_cast<llvm::Value *>(uintptr_t(KindOrFunctionPointer));193  }194  void setFunctionPointer(llvm::Value *functionPtr) {195    assert(isOrdinary());196    KindOrFunctionPointer =197        SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));198  }199  void setPointerAuthInfo(CGPointerAuthInfo PointerAuth) {200    assert(isOrdinary());201    OrdinaryInfo.PointerAuthInfo = PointerAuth;202  }203 204  bool isVirtual() const {205    return KindOrFunctionPointer == SpecialKind::Virtual;206  }207  const CallExpr *getVirtualCallExpr() const {208    assert(isVirtual());209    return VirtualInfo.CE;210  }211  GlobalDecl getVirtualMethodDecl() const {212    assert(isVirtual());213    return VirtualInfo.MD;214  }215  Address getThisAddress() const {216    assert(isVirtual());217    return VirtualInfo.Addr;218  }219  llvm::FunctionType *getVirtualFunctionType() const {220    assert(isVirtual());221    return VirtualInfo.FTy;222  }223 224  /// If this is a delayed callee computation of some sort, prepare225  /// a concrete callee.226  CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;227};228 229struct CallArg {230private:231  union {232    RValue RV;233    LValue LV; /// The argument is semantically a load from this l-value.234  };235  bool HasLV;236 237  /// A data-flow flag to make sure getRValue and/or copyInto are not238  /// called twice for duplicated IR emission.239  mutable bool IsUsed;240 241public:242  QualType Ty;243  CallArg(RValue rv, QualType ty)244      : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}245  CallArg(LValue lv, QualType ty)246      : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}247  bool hasLValue() const { return HasLV; }248  QualType getType() const { return Ty; }249 250  /// \returns an independent RValue. If the CallArg contains an LValue,251  /// a temporary copy is returned.252  RValue getRValue(CodeGenFunction &CGF) const;253 254  LValue getKnownLValue() const {255    assert(HasLV && !IsUsed);256    return LV;257  }258  RValue getKnownRValue() const {259    assert(!HasLV && !IsUsed);260    return RV;261  }262  void setRValue(RValue _RV) {263    assert(!HasLV);264    RV = _RV;265  }266 267  bool isAggregate() const { return HasLV || RV.isAggregate(); }268 269  void copyInto(CodeGenFunction &CGF, Address A) const;270};271 272/// CallArgList - Type for representing both the value and type of273/// arguments in a call.274class CallArgList : public SmallVector<CallArg, 8> {275public:276  CallArgList() = default;277 278  struct Writeback {279    /// The original argument.  Note that the argument l-value280    /// is potentially null.281    LValue Source;282 283    /// The temporary alloca.284    Address Temporary;285 286    /// A value to "use" after the writeback, or null.287    llvm::Value *ToUse;288 289    /// An Expression (optional) that performs the writeback with any required290    /// casting.291    const Expr *WritebackExpr;292  };293 294  struct CallArgCleanup {295    EHScopeStack::stable_iterator Cleanup;296 297    /// The "is active" insertion point.  This instruction is temporary and298    /// will be removed after insertion.299    llvm::Instruction *IsActiveIP;300  };301 302  void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }303 304  void addUncopiedAggregate(LValue LV, QualType type) {305    push_back(CallArg(LV, type));306  }307 308  /// Add all the arguments from another CallArgList to this one. After doing309  /// this, the old CallArgList retains its list of arguments, but must not310  /// be used to emit a call.311  void addFrom(const CallArgList &other) {312    llvm::append_range(*this, other);313    llvm::append_range(Writebacks, other.Writebacks);314    llvm::append_range(CleanupsToDeactivate, other.CleanupsToDeactivate);315    assert(!(StackBase && other.StackBase) && "can't merge stackbases");316    if (!StackBase)317      StackBase = other.StackBase;318  }319 320  void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,321                    const Expr *writebackExpr = nullptr) {322    Writeback writeback = {srcLV, temporary, toUse, writebackExpr};323    Writebacks.push_back(writeback);324  }325 326  bool hasWritebacks() const { return !Writebacks.empty(); }327 328  typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>329      writeback_const_range;330 331  writeback_const_range writebacks() const {332    return writeback_const_range(Writebacks.begin(), Writebacks.end());333  }334 335  void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,336                                 llvm::Instruction *IsActiveIP) {337    CallArgCleanup ArgCleanup;338    ArgCleanup.Cleanup = Cleanup;339    ArgCleanup.IsActiveIP = IsActiveIP;340    CleanupsToDeactivate.push_back(ArgCleanup);341  }342 343  ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {344    return CleanupsToDeactivate;345  }346 347  void allocateArgumentMemory(CodeGenFunction &CGF);348  llvm::Instruction *getStackBase() const { return StackBase; }349  void freeArgumentMemory(CodeGenFunction &CGF) const;350 351  /// Returns if we're using an inalloca struct to pass arguments in352  /// memory.353  bool isUsingInAlloca() const { return StackBase; }354 355  // Support reversing writebacks for MSVC ABI.356  void reverseWritebacks() {357    std::reverse(Writebacks.begin(), Writebacks.end());358  }359 360private:361  SmallVector<Writeback, 1> Writebacks;362 363  /// Deactivate these cleanups immediately before making the call.  This364  /// is used to cleanup objects that are owned by the callee once the call365  /// occurs.366  SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;367 368  /// The stacksave call.  It dominates all of the argument evaluation.369  llvm::CallInst *StackBase = nullptr;370};371 372/// FunctionArgList - Type for representing both the decl and type373/// of parameters to a function. The decl must be either a374/// ParmVarDecl or ImplicitParamDecl.375class FunctionArgList : public SmallVector<const VarDecl *, 16> {};376 377/// ReturnValueSlot - Contains the address where the return value of a378/// function can be stored, and whether the address is volatile or not.379class ReturnValueSlot {380  Address Addr = Address::invalid();381 382  // Return value slot flags383  LLVM_PREFERRED_TYPE(bool)384  unsigned IsVolatile : 1;385  LLVM_PREFERRED_TYPE(bool)386  unsigned IsUnused : 1;387  LLVM_PREFERRED_TYPE(bool)388  unsigned IsExternallyDestructed : 1;389 390public:391  ReturnValueSlot()392      : IsVolatile(false), IsUnused(false), IsExternallyDestructed(false) {}393  ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false,394                  bool IsExternallyDestructed = false)395      : Addr(Addr), IsVolatile(IsVolatile), IsUnused(IsUnused),396        IsExternallyDestructed(IsExternallyDestructed) {}397 398  bool isNull() const { return !Addr.isValid(); }399  bool isVolatile() const { return IsVolatile; }400  Address getValue() const { return Addr; }401  bool isUnused() const { return IsUnused; }402  bool isExternallyDestructed() const { return IsExternallyDestructed; }403  Address getAddress() const { return Addr; }404};405 406/// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as407/// though we had emitted it ourselves. We remove any attributes on F that408/// conflict with the attributes we add here.409///410/// This is useful for adding attrs to bitcode modules that you want to link411/// with but don't control, such as CUDA's libdevice.  When linking with such412/// a bitcode library, you might want to set e.g. its functions'413/// "denormal-fp-math" attribute to match the attr of the functions you're414/// codegen'ing.  Otherwise, LLVM will interpret the bitcode module's lack of415/// denormal-fp-math attrs as tantamount to denormal-fp-math=ieee, and then LLVM416/// will propagate denormal-fp-math=ieee up to every transitive caller of a417/// function in the bitcode library!418///419/// With the exception of fast-math attrs, this will only make the attributes420/// on the function more conservative.  But it's unsafe to call this on a421/// function which relies on particular fast-math attributes for correctness.422/// It's up to you to ensure that this is safe.423void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F,424                                              const CodeGenOptions &CodeGenOpts,425                                              const LangOptions &LangOpts,426                                              const TargetOptions &TargetOpts,427                                              bool WillInternalize);428 429enum class FnInfoOpts {430  None = 0,431  IsInstanceMethod = 1 << 0,432  IsChainCall = 1 << 1,433  IsDelegateCall = 1 << 2,434};435 436inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) {437  return static_cast<FnInfoOpts>(llvm::to_underlying(A) |438                                 llvm::to_underlying(B));439}440 441inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) {442  return static_cast<FnInfoOpts>(llvm::to_underlying(A) &443                                 llvm::to_underlying(B));444}445 446inline FnInfoOpts &operator|=(FnInfoOpts &A, FnInfoOpts B) {447  A = A | B;448  return A;449}450 451inline FnInfoOpts &operator&=(FnInfoOpts &A, FnInfoOpts B) {452  A = A & B;453  return A;454}455 456struct DisableDebugLocationUpdates {457  CodeGenFunction &CGF;458  DisableDebugLocationUpdates(CodeGenFunction &CGF);459  ~DisableDebugLocationUpdates();460};461 462} // end namespace CodeGen463} // end namespace clang464 465#endif466