1259701Sdim//==-- CGFunctionInfo.h - Representation of function argument/return types -==// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim// 10259701Sdim// Defines CGFunctionInfo and associated types used in representing the 11259701Sdim// LLVM source types and ABI-coerced types for function arguments and 12259701Sdim// return values. 13259701Sdim// 14259701Sdim//===----------------------------------------------------------------------===// 15259701Sdim 16259701Sdim#ifndef LLVM_CLANG_CODEGEN_FUNCTION_INFO_H 17259701Sdim#define LLVM_CLANG_CODEGEN_FUNCTION_INFO_H 18259701Sdim 19259701Sdim#include "clang/AST/CanonicalType.h" 20259701Sdim#include "clang/AST/Type.h" 21259701Sdim#include "llvm/ADT/FoldingSet.h" 22259701Sdim 23259701Sdim#include <cassert> 24259701Sdim 25259701Sdimnamespace llvm { 26259701Sdim class Type; 27259701Sdim} 28259701Sdim 29259701Sdimnamespace clang { 30259701Sdimnamespace CodeGen { 31259701Sdim 32259701Sdim/// ABIArgInfo - Helper class to encapsulate information about how a 33259701Sdim/// specific C type should be passed to or returned from a function. 34259701Sdimclass ABIArgInfo { 35259701Sdimpublic: 36259701Sdim enum Kind { 37259701Sdim /// Direct - Pass the argument directly using the normal converted LLVM 38259701Sdim /// type, or by coercing to another specified type stored in 39259701Sdim /// 'CoerceToType'). If an offset is specified (in UIntData), then the 40259701Sdim /// argument passed is offset by some number of bytes in the memory 41259701Sdim /// representation. A dummy argument is emitted before the real argument 42259701Sdim /// if the specified type stored in "PaddingType" is not zero. 43259701Sdim Direct, 44259701Sdim 45259701Sdim /// Extend - Valid only for integer argument types. Same as 'direct' 46259701Sdim /// but also emit a zero/sign extension attribute. 47259701Sdim Extend, 48259701Sdim 49259701Sdim /// Indirect - Pass the argument indirectly via a hidden pointer 50259701Sdim /// with the specified alignment (0 indicates default alignment). 51259701Sdim Indirect, 52259701Sdim 53259701Sdim /// Ignore - Ignore the argument (treat as void). Useful for void and 54259701Sdim /// empty structs. 55259701Sdim Ignore, 56259701Sdim 57259701Sdim /// Expand - Only valid for aggregate argument types. The structure should 58259701Sdim /// be expanded into consecutive arguments for its constituent fields. 59259701Sdim /// Currently expand is only allowed on structures whose fields 60259701Sdim /// are all scalar types or are themselves expandable types. 61259701Sdim Expand, 62259701Sdim 63259701Sdim KindFirst=Direct, KindLast=Expand 64259701Sdim }; 65259701Sdim 66259701Sdimprivate: 67259701Sdim Kind TheKind; 68259701Sdim llvm::Type *TypeData; 69259701Sdim llvm::Type *PaddingType; 70259701Sdim unsigned UIntData; 71259701Sdim bool BoolData0; 72259701Sdim bool BoolData1; 73259701Sdim bool InReg; 74259701Sdim bool PaddingInReg; 75259701Sdim 76259701Sdim ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR, 77259701Sdim bool PIR, llvm::Type* P) 78259701Sdim : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0), 79259701Sdim BoolData1(B1), InReg(IR), PaddingInReg(PIR) {} 80259701Sdim 81259701Sdimpublic: 82259701Sdim ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {} 83259701Sdim 84259701Sdim static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0, 85259701Sdim llvm::Type *Padding = 0) { 86259701Sdim return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding); 87259701Sdim } 88259701Sdim static ABIArgInfo getDirectInReg(llvm::Type *T = 0) { 89259701Sdim return ABIArgInfo(Direct, T, 0, false, false, true, false, 0); 90259701Sdim } 91259701Sdim static ABIArgInfo getExtend(llvm::Type *T = 0) { 92259701Sdim return ABIArgInfo(Extend, T, 0, false, false, false, false, 0); 93259701Sdim } 94259701Sdim static ABIArgInfo getExtendInReg(llvm::Type *T = 0) { 95259701Sdim return ABIArgInfo(Extend, T, 0, false, false, true, false, 0); 96259701Sdim } 97259701Sdim static ABIArgInfo getIgnore() { 98259701Sdim return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0); 99259701Sdim } 100259701Sdim static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true 101259701Sdim , bool Realign = false 102259701Sdim , llvm::Type *Padding = 0) { 103259701Sdim return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false, 104259701Sdim Padding); 105259701Sdim } 106259701Sdim static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true 107259701Sdim , bool Realign = false) { 108259701Sdim return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0); 109259701Sdim } 110259701Sdim static ABIArgInfo getExpand() { 111259701Sdim return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0); 112259701Sdim } 113259701Sdim static ABIArgInfo getExpandWithPadding(bool PaddingInReg, 114259701Sdim llvm::Type *Padding) { 115259701Sdim return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg, 116259701Sdim Padding); 117259701Sdim } 118259701Sdim 119259701Sdim Kind getKind() const { return TheKind; } 120259701Sdim bool isDirect() const { return TheKind == Direct; } 121259701Sdim bool isExtend() const { return TheKind == Extend; } 122259701Sdim bool isIgnore() const { return TheKind == Ignore; } 123259701Sdim bool isIndirect() const { return TheKind == Indirect; } 124259701Sdim bool isExpand() const { return TheKind == Expand; } 125259701Sdim 126259701Sdim bool canHaveCoerceToType() const { 127259701Sdim return TheKind == Direct || TheKind == Extend; 128259701Sdim } 129259701Sdim 130259701Sdim // Direct/Extend accessors 131259701Sdim unsigned getDirectOffset() const { 132259701Sdim assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 133259701Sdim return UIntData; 134259701Sdim } 135259701Sdim 136259701Sdim llvm::Type *getPaddingType() const { 137259701Sdim return PaddingType; 138259701Sdim } 139259701Sdim 140259701Sdim bool getPaddingInReg() const { 141259701Sdim return PaddingInReg; 142259701Sdim } 143259701Sdim 144259701Sdim llvm::Type *getCoerceToType() const { 145259701Sdim assert(canHaveCoerceToType() && "Invalid kind!"); 146259701Sdim return TypeData; 147259701Sdim } 148259701Sdim 149259701Sdim void setCoerceToType(llvm::Type *T) { 150259701Sdim assert(canHaveCoerceToType() && "Invalid kind!"); 151259701Sdim TypeData = T; 152259701Sdim } 153259701Sdim 154259701Sdim bool getInReg() const { 155259701Sdim assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 156259701Sdim return InReg; 157259701Sdim } 158259701Sdim 159259701Sdim // Indirect accessors 160259701Sdim unsigned getIndirectAlign() const { 161259701Sdim assert(TheKind == Indirect && "Invalid kind!"); 162259701Sdim return UIntData; 163259701Sdim } 164259701Sdim 165259701Sdim bool getIndirectByVal() const { 166259701Sdim assert(TheKind == Indirect && "Invalid kind!"); 167259701Sdim return BoolData0; 168259701Sdim } 169259701Sdim 170259701Sdim bool getIndirectRealign() const { 171259701Sdim assert(TheKind == Indirect && "Invalid kind!"); 172259701Sdim return BoolData1; 173259701Sdim } 174259701Sdim 175259701Sdim void dump() const; 176259701Sdim}; 177259701Sdim 178259701Sdim/// A class for recording the number of arguments that a function 179259701Sdim/// signature requires. 180259701Sdimclass RequiredArgs { 181259701Sdim /// The number of required arguments, or ~0 if the signature does 182259701Sdim /// not permit optional arguments. 183259701Sdim unsigned NumRequired; 184259701Sdimpublic: 185259701Sdim enum All_t { All }; 186259701Sdim 187259701Sdim RequiredArgs(All_t _) : NumRequired(~0U) {} 188259701Sdim explicit RequiredArgs(unsigned n) : NumRequired(n) { 189259701Sdim assert(n != ~0U); 190259701Sdim } 191259701Sdim 192259701Sdim /// Compute the arguments required by the given formal prototype, 193259701Sdim /// given that there may be some additional, non-formal arguments 194259701Sdim /// in play. 195259701Sdim static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, 196259701Sdim unsigned additional) { 197259701Sdim if (!prototype->isVariadic()) return All; 198259701Sdim return RequiredArgs(prototype->getNumArgs() + additional); 199259701Sdim } 200259701Sdim 201259701Sdim static RequiredArgs forPrototype(const FunctionProtoType *prototype) { 202259701Sdim return forPrototypePlus(prototype, 0); 203259701Sdim } 204259701Sdim 205259701Sdim static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) { 206259701Sdim return forPrototype(prototype.getTypePtr()); 207259701Sdim } 208259701Sdim 209259701Sdim static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, 210259701Sdim unsigned additional) { 211259701Sdim return forPrototypePlus(prototype.getTypePtr(), additional); 212259701Sdim } 213259701Sdim 214259701Sdim bool allowsOptionalArgs() const { return NumRequired != ~0U; } 215259701Sdim unsigned getNumRequiredArgs() const { 216259701Sdim assert(allowsOptionalArgs()); 217259701Sdim return NumRequired; 218259701Sdim } 219259701Sdim 220259701Sdim unsigned getOpaqueData() const { return NumRequired; } 221259701Sdim static RequiredArgs getFromOpaqueData(unsigned value) { 222259701Sdim if (value == ~0U) return All; 223259701Sdim return RequiredArgs(value); 224259701Sdim } 225259701Sdim}; 226259701Sdim 227259701Sdim/// CGFunctionInfo - Class to encapsulate the information about a 228259701Sdim/// function definition. 229259701Sdimclass CGFunctionInfo : public llvm::FoldingSetNode { 230259701Sdim struct ArgInfo { 231259701Sdim CanQualType type; 232259701Sdim ABIArgInfo info; 233259701Sdim }; 234259701Sdim 235259701Sdim /// The LLVM::CallingConv to use for this function (as specified by the 236259701Sdim /// user). 237259701Sdim unsigned CallingConvention : 8; 238259701Sdim 239259701Sdim /// The LLVM::CallingConv to actually use for this function, which may 240259701Sdim /// depend on the ABI. 241259701Sdim unsigned EffectiveCallingConvention : 8; 242259701Sdim 243259701Sdim /// The clang::CallingConv that this was originally created with. 244259701Sdim unsigned ASTCallingConvention : 8; 245259701Sdim 246259701Sdim /// Whether this function is noreturn. 247259701Sdim unsigned NoReturn : 1; 248259701Sdim 249259701Sdim /// Whether this function is returns-retained. 250259701Sdim unsigned ReturnsRetained : 1; 251259701Sdim 252259701Sdim /// How many arguments to pass inreg. 253259701Sdim unsigned HasRegParm : 1; 254259701Sdim unsigned RegParm : 4; 255259701Sdim 256259701Sdim RequiredArgs Required; 257259701Sdim 258259701Sdim unsigned NumArgs; 259259701Sdim ArgInfo *getArgsBuffer() { 260259701Sdim return reinterpret_cast<ArgInfo*>(this+1); 261259701Sdim } 262259701Sdim const ArgInfo *getArgsBuffer() const { 263259701Sdim return reinterpret_cast<const ArgInfo*>(this + 1); 264259701Sdim } 265259701Sdim 266259701Sdim CGFunctionInfo() : Required(RequiredArgs::All) {} 267259701Sdim 268259701Sdimpublic: 269259701Sdim static CGFunctionInfo *create(unsigned llvmCC, 270259701Sdim const FunctionType::ExtInfo &extInfo, 271259701Sdim CanQualType resultType, 272259701Sdim ArrayRef<CanQualType> argTypes, 273259701Sdim RequiredArgs required); 274259701Sdim 275259701Sdim typedef const ArgInfo *const_arg_iterator; 276259701Sdim typedef ArgInfo *arg_iterator; 277259701Sdim 278259701Sdim const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } 279259701Sdim const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } 280259701Sdim arg_iterator arg_begin() { return getArgsBuffer() + 1; } 281259701Sdim arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } 282259701Sdim 283259701Sdim unsigned arg_size() const { return NumArgs; } 284259701Sdim 285259701Sdim bool isVariadic() const { return Required.allowsOptionalArgs(); } 286259701Sdim RequiredArgs getRequiredArgs() const { return Required; } 287259701Sdim 288259701Sdim bool isNoReturn() const { return NoReturn; } 289259701Sdim 290259701Sdim /// In ARC, whether this function retains its return value. This 291259701Sdim /// is not always reliable for call sites. 292259701Sdim bool isReturnsRetained() const { return ReturnsRetained; } 293259701Sdim 294259701Sdim /// getASTCallingConvention() - Return the AST-specified calling 295259701Sdim /// convention. 296259701Sdim CallingConv getASTCallingConvention() const { 297259701Sdim return CallingConv(ASTCallingConvention); 298259701Sdim } 299259701Sdim 300259701Sdim /// getCallingConvention - Return the user specified calling 301259701Sdim /// convention, which has been translated into an LLVM CC. 302259701Sdim unsigned getCallingConvention() const { return CallingConvention; } 303259701Sdim 304259701Sdim /// getEffectiveCallingConvention - Return the actual calling convention to 305259701Sdim /// use, which may depend on the ABI. 306259701Sdim unsigned getEffectiveCallingConvention() const { 307259701Sdim return EffectiveCallingConvention; 308259701Sdim } 309259701Sdim void setEffectiveCallingConvention(unsigned Value) { 310259701Sdim EffectiveCallingConvention = Value; 311259701Sdim } 312259701Sdim 313259701Sdim bool getHasRegParm() const { return HasRegParm; } 314259701Sdim unsigned getRegParm() const { return RegParm; } 315259701Sdim 316259701Sdim FunctionType::ExtInfo getExtInfo() const { 317259701Sdim return FunctionType::ExtInfo(isNoReturn(), 318259701Sdim getHasRegParm(), getRegParm(), 319259701Sdim getASTCallingConvention(), 320259701Sdim isReturnsRetained()); 321259701Sdim } 322259701Sdim 323259701Sdim CanQualType getReturnType() const { return getArgsBuffer()[0].type; } 324259701Sdim 325259701Sdim ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } 326259701Sdim const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } 327259701Sdim 328259701Sdim void Profile(llvm::FoldingSetNodeID &ID) { 329259701Sdim ID.AddInteger(getASTCallingConvention()); 330259701Sdim ID.AddBoolean(NoReturn); 331259701Sdim ID.AddBoolean(ReturnsRetained); 332259701Sdim ID.AddBoolean(HasRegParm); 333259701Sdim ID.AddInteger(RegParm); 334259701Sdim ID.AddInteger(Required.getOpaqueData()); 335259701Sdim getReturnType().Profile(ID); 336259701Sdim for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it) 337259701Sdim it->type.Profile(ID); 338259701Sdim } 339259701Sdim static void Profile(llvm::FoldingSetNodeID &ID, 340259701Sdim const FunctionType::ExtInfo &info, 341259701Sdim RequiredArgs required, 342259701Sdim CanQualType resultType, 343259701Sdim ArrayRef<CanQualType> argTypes) { 344259701Sdim ID.AddInteger(info.getCC()); 345259701Sdim ID.AddBoolean(info.getNoReturn()); 346259701Sdim ID.AddBoolean(info.getProducesResult()); 347259701Sdim ID.AddBoolean(info.getHasRegParm()); 348259701Sdim ID.AddInteger(info.getRegParm()); 349259701Sdim ID.AddInteger(required.getOpaqueData()); 350259701Sdim resultType.Profile(ID); 351259701Sdim for (ArrayRef<CanQualType>::iterator 352259701Sdim i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { 353259701Sdim i->Profile(ID); 354259701Sdim } 355259701Sdim } 356259701Sdim}; 357259701Sdim 358259701Sdim} // end namespace CodeGen 359259701Sdim} // end namespace clang 360259701Sdim 361259701Sdim#endif 362