Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGCall.h
35233 views
//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// These classes wrap the information about a call or function9// definition used to handle ABI compliancy.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H14#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H1516#include "CGPointerAuthInfo.h"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/ADT/STLForwardCompat.h"24#include "llvm/IR/Value.h"2526namespace llvm {27class Type;28class Value;29} // namespace llvm3031namespace clang {32class Decl;33class FunctionDecl;34class TargetOptions;35class VarDecl;3637namespace CodeGen {3839/// Abstract information about a function or function prototype.40class CGCalleeInfo {41/// The function prototype of the callee.42const FunctionProtoType *CalleeProtoTy;43/// The function declaration of the callee.44GlobalDecl CalleeDecl;4546public:47explicit CGCalleeInfo() : CalleeProtoTy(nullptr) {}48CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)49: CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}50CGCalleeInfo(const FunctionProtoType *calleeProtoTy)51: CalleeProtoTy(calleeProtoTy) {}52CGCalleeInfo(GlobalDecl calleeDecl)53: CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}5455const FunctionProtoType *getCalleeFunctionProtoType() const {56return CalleeProtoTy;57}58const GlobalDecl getCalleeDecl() const { return CalleeDecl; }59};6061/// All available information about a concrete callee.62class CGCallee {63enum class SpecialKind : uintptr_t {64Invalid,65Builtin,66PseudoDestructor,67Virtual,6869Last = Virtual70};7172struct OrdinaryInfoStorage {73CGCalleeInfo AbstractInfo;74CGPointerAuthInfo PointerAuthInfo;75};76struct BuiltinInfoStorage {77const FunctionDecl *Decl;78unsigned ID;79};80struct PseudoDestructorInfoStorage {81const CXXPseudoDestructorExpr *Expr;82};83struct VirtualInfoStorage {84const CallExpr *CE;85GlobalDecl MD;86Address Addr;87llvm::FunctionType *FTy;88};8990SpecialKind KindOrFunctionPointer;91union {92OrdinaryInfoStorage OrdinaryInfo;93BuiltinInfoStorage BuiltinInfo;94PseudoDestructorInfoStorage PseudoDestructorInfo;95VirtualInfoStorage VirtualInfo;96};9798explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}99100CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)101: KindOrFunctionPointer(SpecialKind::Builtin) {102BuiltinInfo.Decl = builtinDecl;103BuiltinInfo.ID = builtinID;104}105106public:107CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}108109/// Construct a callee. Call this constructor directly when this110/// isn't a direct call.111CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,112/* FIXME: make parameter pointerAuthInfo mandatory */113const CGPointerAuthInfo &pointerAuthInfo = CGPointerAuthInfo())114: KindOrFunctionPointer(115SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {116OrdinaryInfo.AbstractInfo = abstractInfo;117OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;118assert(functionPtr && "configuring callee without function pointer");119assert(functionPtr->getType()->isPointerTy());120}121122static CGCallee forBuiltin(unsigned builtinID,123const FunctionDecl *builtinDecl) {124CGCallee result(SpecialKind::Builtin);125result.BuiltinInfo.Decl = builtinDecl;126result.BuiltinInfo.ID = builtinID;127return result;128}129130static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {131CGCallee result(SpecialKind::PseudoDestructor);132result.PseudoDestructorInfo.Expr = E;133return result;134}135136static CGCallee forDirect(llvm::Constant *functionPtr,137const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {138return CGCallee(abstractInfo, functionPtr);139}140141static CGCallee forDirect(llvm::FunctionCallee functionPtr,142const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {143return CGCallee(abstractInfo, functionPtr.getCallee());144}145146static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,147llvm::FunctionType *FTy) {148CGCallee result(SpecialKind::Virtual);149result.VirtualInfo.CE = CE;150result.VirtualInfo.MD = MD;151result.VirtualInfo.Addr = Addr;152result.VirtualInfo.FTy = FTy;153return result;154}155156bool isBuiltin() const {157return KindOrFunctionPointer == SpecialKind::Builtin;158}159const FunctionDecl *getBuiltinDecl() const {160assert(isBuiltin());161return BuiltinInfo.Decl;162}163unsigned getBuiltinID() const {164assert(isBuiltin());165return BuiltinInfo.ID;166}167168bool isPseudoDestructor() const {169return KindOrFunctionPointer == SpecialKind::PseudoDestructor;170}171const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {172assert(isPseudoDestructor());173return PseudoDestructorInfo.Expr;174}175176bool isOrdinary() const {177return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);178}179CGCalleeInfo getAbstractInfo() const {180if (isVirtual())181return VirtualInfo.MD;182assert(isOrdinary());183return OrdinaryInfo.AbstractInfo;184}185const CGPointerAuthInfo &getPointerAuthInfo() const {186assert(isOrdinary());187return OrdinaryInfo.PointerAuthInfo;188}189llvm::Value *getFunctionPointer() const {190assert(isOrdinary());191return reinterpret_cast<llvm::Value *>(uintptr_t(KindOrFunctionPointer));192}193void setFunctionPointer(llvm::Value *functionPtr) {194assert(isOrdinary());195KindOrFunctionPointer =196SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));197}198void setPointerAuthInfo(CGPointerAuthInfo PointerAuth) {199assert(isOrdinary());200OrdinaryInfo.PointerAuthInfo = PointerAuth;201}202203bool isVirtual() const {204return KindOrFunctionPointer == SpecialKind::Virtual;205}206const CallExpr *getVirtualCallExpr() const {207assert(isVirtual());208return VirtualInfo.CE;209}210GlobalDecl getVirtualMethodDecl() const {211assert(isVirtual());212return VirtualInfo.MD;213}214Address getThisAddress() const {215assert(isVirtual());216return VirtualInfo.Addr;217}218llvm::FunctionType *getVirtualFunctionType() const {219assert(isVirtual());220return VirtualInfo.FTy;221}222223/// If this is a delayed callee computation of some sort, prepare224/// a concrete callee.225CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;226};227228struct CallArg {229private:230union {231RValue RV;232LValue LV; /// The argument is semantically a load from this l-value.233};234bool HasLV;235236/// A data-flow flag to make sure getRValue and/or copyInto are not237/// called twice for duplicated IR emission.238mutable bool IsUsed;239240public:241QualType Ty;242CallArg(RValue rv, QualType ty)243: RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}244CallArg(LValue lv, QualType ty)245: LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}246bool hasLValue() const { return HasLV; }247QualType getType() const { return Ty; }248249/// \returns an independent RValue. If the CallArg contains an LValue,250/// a temporary copy is returned.251RValue getRValue(CodeGenFunction &CGF) const;252253LValue getKnownLValue() const {254assert(HasLV && !IsUsed);255return LV;256}257RValue getKnownRValue() const {258assert(!HasLV && !IsUsed);259return RV;260}261void setRValue(RValue _RV) {262assert(!HasLV);263RV = _RV;264}265266bool isAggregate() const { return HasLV || RV.isAggregate(); }267268void copyInto(CodeGenFunction &CGF, Address A) const;269};270271/// CallArgList - Type for representing both the value and type of272/// arguments in a call.273class CallArgList : public SmallVector<CallArg, 8> {274public:275CallArgList() = default;276277struct Writeback {278/// The original argument. Note that the argument l-value279/// is potentially null.280LValue Source;281282/// The temporary alloca.283Address Temporary;284285/// A value to "use" after the writeback, or null.286llvm::Value *ToUse;287};288289struct CallArgCleanup {290EHScopeStack::stable_iterator Cleanup;291292/// The "is active" insertion point. This instruction is temporary and293/// will be removed after insertion.294llvm::Instruction *IsActiveIP;295};296297void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }298299void addUncopiedAggregate(LValue LV, QualType type) {300push_back(CallArg(LV, type));301}302303/// Add all the arguments from another CallArgList to this one. After doing304/// this, the old CallArgList retains its list of arguments, but must not305/// be used to emit a call.306void addFrom(const CallArgList &other) {307insert(end(), other.begin(), other.end());308Writebacks.insert(Writebacks.end(), other.Writebacks.begin(),309other.Writebacks.end());310CleanupsToDeactivate.insert(CleanupsToDeactivate.end(),311other.CleanupsToDeactivate.begin(),312other.CleanupsToDeactivate.end());313assert(!(StackBase && other.StackBase) && "can't merge stackbases");314if (!StackBase)315StackBase = other.StackBase;316}317318void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse) {319Writeback writeback = {srcLV, temporary, toUse};320Writebacks.push_back(writeback);321}322323bool hasWritebacks() const { return !Writebacks.empty(); }324325typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>326writeback_const_range;327328writeback_const_range writebacks() const {329return writeback_const_range(Writebacks.begin(), Writebacks.end());330}331332void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,333llvm::Instruction *IsActiveIP) {334CallArgCleanup ArgCleanup;335ArgCleanup.Cleanup = Cleanup;336ArgCleanup.IsActiveIP = IsActiveIP;337CleanupsToDeactivate.push_back(ArgCleanup);338}339340ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {341return CleanupsToDeactivate;342}343344void allocateArgumentMemory(CodeGenFunction &CGF);345llvm::Instruction *getStackBase() const { return StackBase; }346void freeArgumentMemory(CodeGenFunction &CGF) const;347348/// Returns if we're using an inalloca struct to pass arguments in349/// memory.350bool isUsingInAlloca() const { return StackBase; }351352private:353SmallVector<Writeback, 1> Writebacks;354355/// Deactivate these cleanups immediately before making the call. This356/// is used to cleanup objects that are owned by the callee once the call357/// occurs.358SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;359360/// The stacksave call. It dominates all of the argument evaluation.361llvm::CallInst *StackBase = nullptr;362};363364/// FunctionArgList - Type for representing both the decl and type365/// of parameters to a function. The decl must be either a366/// ParmVarDecl or ImplicitParamDecl.367class FunctionArgList : public SmallVector<const VarDecl *, 16> {};368369/// ReturnValueSlot - Contains the address where the return value of a370/// function can be stored, and whether the address is volatile or not.371class ReturnValueSlot {372Address Addr = Address::invalid();373374// Return value slot flags375LLVM_PREFERRED_TYPE(bool)376unsigned IsVolatile : 1;377LLVM_PREFERRED_TYPE(bool)378unsigned IsUnused : 1;379LLVM_PREFERRED_TYPE(bool)380unsigned IsExternallyDestructed : 1;381382public:383ReturnValueSlot()384: IsVolatile(false), IsUnused(false), IsExternallyDestructed(false) {}385ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false,386bool IsExternallyDestructed = false)387: Addr(Addr), IsVolatile(IsVolatile), IsUnused(IsUnused),388IsExternallyDestructed(IsExternallyDestructed) {}389390bool isNull() const { return !Addr.isValid(); }391bool isVolatile() const { return IsVolatile; }392Address getValue() const { return Addr; }393bool isUnused() const { return IsUnused; }394bool isExternallyDestructed() const { return IsExternallyDestructed; }395Address getAddress() const { return Addr; }396};397398/// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as399/// though we had emitted it ourselves. We remove any attributes on F that400/// conflict with the attributes we add here.401///402/// This is useful for adding attrs to bitcode modules that you want to link403/// with but don't control, such as CUDA's libdevice. When linking with such404/// a bitcode library, you might want to set e.g. its functions'405/// "unsafe-fp-math" attribute to match the attr of the functions you're406/// codegen'ing. Otherwise, LLVM will interpret the bitcode module's lack of407/// unsafe-fp-math attrs as tantamount to unsafe-fp-math=false, and then LLVM408/// will propagate unsafe-fp-math=false up to every transitive caller of a409/// function in the bitcode library!410///411/// With the exception of fast-math attrs, this will only make the attributes412/// on the function more conservative. But it's unsafe to call this on a413/// function which relies on particular fast-math attributes for correctness.414/// It's up to you to ensure that this is safe.415void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F,416const CodeGenOptions &CodeGenOpts,417const LangOptions &LangOpts,418const TargetOptions &TargetOpts,419bool WillInternalize);420421enum class FnInfoOpts {422None = 0,423IsInstanceMethod = 1 << 0,424IsChainCall = 1 << 1,425IsDelegateCall = 1 << 2,426};427428inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) {429return static_cast<FnInfoOpts>(llvm::to_underlying(A) |430llvm::to_underlying(B));431}432433inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) {434return static_cast<FnInfoOpts>(llvm::to_underlying(A) &435llvm::to_underlying(B));436}437438inline FnInfoOpts operator|=(FnInfoOpts A, FnInfoOpts B) {439A = A | B;440return A;441}442443inline FnInfoOpts operator&=(FnInfoOpts A, FnInfoOpts B) {444A = A & B;445return A;446}447448} // end namespace CodeGen449} // end namespace clang450451#endif452453454