//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // These classes wrap the information about a call or function // definition used to handle ABI compliancy. // //===----------------------------------------------------------------------===// #ifndef CLANG_CODEGEN_CGCALL_H #define CLANG_CODEGEN_CGCALL_H #include "CGValue.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/Type.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/IR/Value.h" // FIXME: Restructure so we don't have to expose so much stuff. #include "ABIInfo.h" namespace llvm { class AttributeSet; class Function; class Type; class Value; } namespace clang { class ASTContext; class Decl; class FunctionDecl; class ObjCMethodDecl; class VarDecl; namespace CodeGen { typedef SmallVector AttributeListType; struct CallArg { RValue RV; QualType Ty; bool NeedsCopy; CallArg(RValue rv, QualType ty, bool needscopy) : RV(rv), Ty(ty), NeedsCopy(needscopy) { } }; /// CallArgList - Type for representing both the value and type of /// arguments in a call. class CallArgList : public SmallVector { public: struct Writeback { /// The original argument. Note that the argument l-value /// is potentially null. LValue Source; /// The temporary alloca. llvm::Value *Temporary; /// A value to "use" after the writeback, or null. llvm::Value *ToUse; }; void add(RValue rvalue, QualType type, bool needscopy = false) { push_back(CallArg(rvalue, type, needscopy)); } void addFrom(const CallArgList &other) { insert(end(), other.begin(), other.end()); Writebacks.insert(Writebacks.end(), other.Writebacks.begin(), other.Writebacks.end()); } void addWriteback(LValue srcLV, llvm::Value *temporary, llvm::Value *toUse) { Writeback writeback; writeback.Source = srcLV; writeback.Temporary = temporary; writeback.ToUse = toUse; Writebacks.push_back(writeback); } bool hasWritebacks() const { return !Writebacks.empty(); } typedef SmallVectorImpl::const_iterator writeback_iterator; writeback_iterator writeback_begin() const { return Writebacks.begin(); } writeback_iterator writeback_end() const { return Writebacks.end(); } private: SmallVector Writebacks; }; /// A class for recording the number of arguments that a function /// signature requires. class RequiredArgs { /// The number of required arguments, or ~0 if the signature does /// not permit optional arguments. unsigned NumRequired; public: enum All_t { All }; RequiredArgs(All_t _) : NumRequired(~0U) {} explicit RequiredArgs(unsigned n) : NumRequired(n) { assert(n != ~0U); } /// Compute the arguments required by the given formal prototype, /// given that there may be some additional, non-formal arguments /// in play. static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional) { if (!prototype->isVariadic()) return All; return RequiredArgs(prototype->getNumArgs() + additional); } static RequiredArgs forPrototype(const FunctionProtoType *prototype) { return forPrototypePlus(prototype, 0); } static RequiredArgs forPrototype(CanQual prototype) { return forPrototype(prototype.getTypePtr()); } static RequiredArgs forPrototypePlus(CanQual prototype, unsigned additional) { return forPrototypePlus(prototype.getTypePtr(), additional); } bool allowsOptionalArgs() const { return NumRequired != ~0U; } unsigned getNumRequiredArgs() const { assert(allowsOptionalArgs()); return NumRequired; } unsigned getOpaqueData() const { return NumRequired; } static RequiredArgs getFromOpaqueData(unsigned value) { if (value == ~0U) return All; return RequiredArgs(value); } }; /// FunctionArgList - Type for representing both the decl and type /// of parameters to a function. The decl must be either a /// ParmVarDecl or ImplicitParamDecl. class FunctionArgList : public SmallVector { }; /// CGFunctionInfo - Class to encapsulate the information about a /// function definition. class CGFunctionInfo : public llvm::FoldingSetNode { struct ArgInfo { CanQualType type; ABIArgInfo info; }; /// The LLVM::CallingConv to use for this function (as specified by the /// user). unsigned CallingConvention : 8; /// The LLVM::CallingConv to actually use for this function, which may /// depend on the ABI. unsigned EffectiveCallingConvention : 8; /// The clang::CallingConv that this was originally created with. unsigned ASTCallingConvention : 8; /// Whether this function is noreturn. unsigned NoReturn : 1; /// Whether this function is returns-retained. unsigned ReturnsRetained : 1; /// How many arguments to pass inreg. unsigned HasRegParm : 1; unsigned RegParm : 4; RequiredArgs Required; unsigned NumArgs; ArgInfo *getArgsBuffer() { return reinterpret_cast(this+1); } const ArgInfo *getArgsBuffer() const { return reinterpret_cast(this + 1); } CGFunctionInfo() : Required(RequiredArgs::All) {} public: static CGFunctionInfo *create(unsigned llvmCC, const FunctionType::ExtInfo &extInfo, CanQualType resultType, ArrayRef argTypes, RequiredArgs required); typedef const ArgInfo *const_arg_iterator; typedef ArgInfo *arg_iterator; const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } arg_iterator arg_begin() { return getArgsBuffer() + 1; } arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } unsigned arg_size() const { return NumArgs; } bool isVariadic() const { return Required.allowsOptionalArgs(); } RequiredArgs getRequiredArgs() const { return Required; } bool isNoReturn() const { return NoReturn; } /// In ARC, whether this function retains its return value. This /// is not always reliable for call sites. bool isReturnsRetained() const { return ReturnsRetained; } /// getASTCallingConvention() - Return the AST-specified calling /// convention. CallingConv getASTCallingConvention() const { return CallingConv(ASTCallingConvention); } /// getCallingConvention - Return the user specified calling /// convention, which has been translated into an LLVM CC. unsigned getCallingConvention() const { return CallingConvention; } /// getEffectiveCallingConvention - Return the actual calling convention to /// use, which may depend on the ABI. unsigned getEffectiveCallingConvention() const { return EffectiveCallingConvention; } void setEffectiveCallingConvention(unsigned Value) { EffectiveCallingConvention = Value; } bool getHasRegParm() const { return HasRegParm; } unsigned getRegParm() const { return RegParm; } FunctionType::ExtInfo getExtInfo() const { return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(), getASTCallingConvention(), isReturnsRetained()); } CanQualType getReturnType() const { return getArgsBuffer()[0].type; } ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } void Profile(llvm::FoldingSetNodeID &ID) { ID.AddInteger(getASTCallingConvention()); ID.AddBoolean(NoReturn); ID.AddBoolean(ReturnsRetained); ID.AddBoolean(HasRegParm); ID.AddInteger(RegParm); ID.AddInteger(Required.getOpaqueData()); getReturnType().Profile(ID); for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it) it->type.Profile(ID); } static void Profile(llvm::FoldingSetNodeID &ID, const FunctionType::ExtInfo &info, RequiredArgs required, CanQualType resultType, ArrayRef argTypes) { ID.AddInteger(info.getCC()); ID.AddBoolean(info.getNoReturn()); ID.AddBoolean(info.getProducesResult()); ID.AddBoolean(info.getHasRegParm()); ID.AddInteger(info.getRegParm()); ID.AddInteger(required.getOpaqueData()); resultType.Profile(ID); for (ArrayRef::iterator i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { i->Profile(ID); } } }; /// ReturnValueSlot - Contains the address where the return value of a /// function can be stored, and whether the address is volatile or not. class ReturnValueSlot { llvm::PointerIntPair Value; public: ReturnValueSlot() {} ReturnValueSlot(llvm::Value *Value, bool IsVolatile) : Value(Value, IsVolatile) {} bool isNull() const { return !getValue(); } bool isVolatile() const { return Value.getInt(); } llvm::Value *getValue() const { return Value.getPointer(); } }; } // end namespace CodeGen } // end namespace clang #endif