1//==-- CGFunctionInfo.h - Representation of function argument/return types -==// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Defines CGFunctionInfo and associated types used in representing the 11// LLVM source types and ABI-coerced types for function arguments and 12// return values. 13// 14//===----------------------------------------------------------------------===// 15 16#ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H 17#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H 18 19#include "clang/AST/CanonicalType.h" 20#include "clang/AST/CharUnits.h" 21#include "clang/AST/Type.h" 22#include "llvm/ADT/FoldingSet.h" 23#include <cassert> 24 25namespace llvm { 26 class Type; 27 class StructType; 28} 29 30namespace clang { 31class Decl; 32 33namespace CodeGen { 34 35/// ABIArgInfo - Helper class to encapsulate information about how a 36/// specific C type should be passed to or returned from a function. 37class ABIArgInfo { 38public: 39 enum Kind : uint8_t { 40 /// Direct - Pass the argument directly using the normal converted LLVM 41 /// type, or by coercing to another specified type stored in 42 /// 'CoerceToType'). If an offset is specified (in UIntData), then the 43 /// argument passed is offset by some number of bytes in the memory 44 /// representation. A dummy argument is emitted before the real argument 45 /// if the specified type stored in "PaddingType" is not zero. 46 Direct, 47 48 /// Extend - Valid only for integer argument types. Same as 'direct' 49 /// but also emit a zero/sign extension attribute. 50 Extend, 51 52 /// Indirect - Pass the argument indirectly via a hidden pointer 53 /// with the specified alignment (0 indicates default alignment). 54 Indirect, 55 56 /// Ignore - Ignore the argument (treat as void). Useful for void and 57 /// empty structs. 58 Ignore, 59 60 /// Expand - Only valid for aggregate argument types. The structure should 61 /// be expanded into consecutive arguments for its constituent fields. 62 /// Currently expand is only allowed on structures whose fields 63 /// are all scalar types or are themselves expandable types. 64 Expand, 65 66 /// InAlloca - Pass the argument directly using the LLVM inalloca attribute. 67 /// This is similar to indirect with byval, except it only applies to 68 /// arguments stored in memory and forbids any implicit copies. When 69 /// applied to a return type, it means the value is returned indirectly via 70 /// an implicit sret parameter stored in the argument struct. 71 InAlloca, 72 KindFirst = Direct, 73 KindLast = InAlloca 74 }; 75 76private: 77 llvm::Type *TypeData; // isDirect() || isExtend() 78 llvm::Type *PaddingType; 79 union { 80 unsigned DirectOffset; // isDirect() || isExtend() 81 unsigned IndirectAlign; // isIndirect() 82 unsigned AllocaFieldIndex; // isInAlloca() 83 }; 84 Kind TheKind; 85 bool PaddingInReg : 1; 86 bool InAllocaSRet : 1; // isInAlloca() 87 bool IndirectByVal : 1; // isIndirect() 88 bool IndirectRealign : 1; // isIndirect() 89 bool SRetAfterThis : 1; // isIndirect() 90 bool InReg : 1; // isDirect() || isExtend() || isIndirect() 91 bool CanBeFlattened: 1; // isDirect() 92 93 ABIArgInfo(Kind K) 94 : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {} 95 96public: 97 ABIArgInfo() 98 : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), 99 TheKind(Direct), PaddingInReg(false), InReg(false) {} 100 101 static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, 102 llvm::Type *Padding = nullptr, 103 bool CanBeFlattened = true) { 104 auto AI = ABIArgInfo(Direct); 105 AI.setCoerceToType(T); 106 AI.setDirectOffset(Offset); 107 AI.setPaddingType(Padding); 108 AI.setCanBeFlattened(CanBeFlattened); 109 return AI; 110 } 111 static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { 112 auto AI = getDirect(T); 113 AI.setInReg(true); 114 return AI; 115 } 116 static ABIArgInfo getExtend(llvm::Type *T = nullptr) { 117 auto AI = ABIArgInfo(Extend); 118 AI.setCoerceToType(T); 119 AI.setDirectOffset(0); 120 return AI; 121 } 122 static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) { 123 auto AI = getExtend(T); 124 AI.setInReg(true); 125 return AI; 126 } 127 static ABIArgInfo getIgnore() { 128 return ABIArgInfo(Ignore); 129 } 130 static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true, 131 bool Realign = false, 132 llvm::Type *Padding = nullptr) { 133 auto AI = ABIArgInfo(Indirect); 134 AI.setIndirectAlign(Alignment); 135 AI.setIndirectByVal(ByVal); 136 AI.setIndirectRealign(Realign); 137 AI.setSRetAfterThis(false); 138 AI.setPaddingType(Padding); 139 return AI; 140 } 141 static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true, 142 bool Realign = false) { 143 auto AI = getIndirect(Alignment, ByVal, Realign); 144 AI.setInReg(true); 145 return AI; 146 } 147 static ABIArgInfo getInAlloca(unsigned FieldIndex) { 148 auto AI = ABIArgInfo(InAlloca); 149 AI.setInAllocaFieldIndex(FieldIndex); 150 return AI; 151 } 152 static ABIArgInfo getExpand() { 153 return ABIArgInfo(Expand); 154 } 155 static ABIArgInfo getExpandWithPadding(bool PaddingInReg, 156 llvm::Type *Padding) { 157 auto AI = getExpand(); 158 AI.setPaddingInReg(PaddingInReg); 159 AI.setPaddingType(Padding); 160 return AI; 161 } 162 163 Kind getKind() const { return TheKind; } 164 bool isDirect() const { return TheKind == Direct; } 165 bool isInAlloca() const { return TheKind == InAlloca; } 166 bool isExtend() const { return TheKind == Extend; } 167 bool isIgnore() const { return TheKind == Ignore; } 168 bool isIndirect() const { return TheKind == Indirect; } 169 bool isExpand() const { return TheKind == Expand; } 170 171 bool canHaveCoerceToType() const { return isDirect() || isExtend(); } 172 173 // Direct/Extend accessors 174 unsigned getDirectOffset() const { 175 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 176 return DirectOffset; 177 } 178 void setDirectOffset(unsigned Offset) { 179 assert((isDirect() || isExtend()) && "Not a direct or extend kind"); 180 DirectOffset = Offset; 181 } 182 183 llvm::Type *getPaddingType() const { return PaddingType; } 184 185 void setPaddingType(llvm::Type *T) { PaddingType = T; } 186 187 bool getPaddingInReg() const { 188 return PaddingInReg; 189 } 190 void setPaddingInReg(bool PIR) { 191 PaddingInReg = PIR; 192 } 193 194 llvm::Type *getCoerceToType() const { 195 assert(canHaveCoerceToType() && "Invalid kind!"); 196 return TypeData; 197 } 198 199 void setCoerceToType(llvm::Type *T) { 200 assert(canHaveCoerceToType() && "Invalid kind!"); 201 TypeData = T; 202 } 203 204 bool getInReg() const { 205 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 206 return InReg; 207 } 208 209 void setInReg(bool IR) { 210 assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!"); 211 InReg = IR; 212 } 213 214 // Indirect accessors 215 CharUnits getIndirectAlign() const { 216 assert(isIndirect() && "Invalid kind!"); 217 return CharUnits::fromQuantity(IndirectAlign); 218 } 219 void setIndirectAlign(CharUnits IA) { 220 assert(isIndirect() && "Invalid kind!"); 221 IndirectAlign = IA.getQuantity(); 222 } 223 224 bool getIndirectByVal() const { 225 assert(isIndirect() && "Invalid kind!"); 226 return IndirectByVal; 227 } 228 void setIndirectByVal(bool IBV) { 229 assert(isIndirect() && "Invalid kind!"); 230 IndirectByVal = IBV; 231 } 232 233 bool getIndirectRealign() const { 234 assert(isIndirect() && "Invalid kind!"); 235 return IndirectRealign; 236 } 237 void setIndirectRealign(bool IR) { 238 assert(isIndirect() && "Invalid kind!"); 239 IndirectRealign = IR; 240 } 241 242 bool isSRetAfterThis() const { 243 assert(isIndirect() && "Invalid kind!"); 244 return SRetAfterThis; 245 } 246 void setSRetAfterThis(bool AfterThis) { 247 assert(isIndirect() && "Invalid kind!"); 248 SRetAfterThis = AfterThis; 249 } 250 251 unsigned getInAllocaFieldIndex() const { 252 assert(isInAlloca() && "Invalid kind!"); 253 return AllocaFieldIndex; 254 } 255 void setInAllocaFieldIndex(unsigned FieldIndex) { 256 assert(isInAlloca() && "Invalid kind!"); 257 AllocaFieldIndex = FieldIndex; 258 } 259 260 /// \brief Return true if this field of an inalloca struct should be returned 261 /// to implement a struct return calling convention. 262 bool getInAllocaSRet() const { 263 assert(isInAlloca() && "Invalid kind!"); 264 return InAllocaSRet; 265 } 266 267 void setInAllocaSRet(bool SRet) { 268 assert(isInAlloca() && "Invalid kind!"); 269 InAllocaSRet = SRet; 270 } 271 272 bool getCanBeFlattened() const { 273 assert(isDirect() && "Invalid kind!"); 274 return CanBeFlattened; 275 } 276 277 void setCanBeFlattened(bool Flatten) { 278 assert(isDirect() && "Invalid kind!"); 279 CanBeFlattened = Flatten; 280 } 281 282 void dump() const; 283}; 284 285/// A class for recording the number of arguments that a function 286/// signature requires. 287class RequiredArgs { 288 /// The number of required arguments, or ~0 if the signature does 289 /// not permit optional arguments. 290 unsigned NumRequired; 291public: 292 enum All_t { All }; 293 294 RequiredArgs(All_t _) : NumRequired(~0U) {} 295 explicit RequiredArgs(unsigned n) : NumRequired(n) { 296 assert(n != ~0U); 297 } 298 299 /// Compute the arguments required by the given formal prototype, 300 /// given that there may be some additional, non-formal arguments 301 /// in play. 302 static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, 303 unsigned additional) { 304 if (!prototype->isVariadic()) return All; 305 return RequiredArgs(prototype->getNumParams() + additional); 306 } 307 308 static RequiredArgs forPrototype(const FunctionProtoType *prototype) { 309 return forPrototypePlus(prototype, 0); 310 } 311 312 static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) { 313 return forPrototype(prototype.getTypePtr()); 314 } 315 316 static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, 317 unsigned additional) { 318 return forPrototypePlus(prototype.getTypePtr(), additional); 319 } 320 321 bool allowsOptionalArgs() const { return NumRequired != ~0U; } 322 unsigned getNumRequiredArgs() const { 323 assert(allowsOptionalArgs()); 324 return NumRequired; 325 } 326 327 unsigned getOpaqueData() const { return NumRequired; } 328 static RequiredArgs getFromOpaqueData(unsigned value) { 329 if (value == ~0U) return All; 330 return RequiredArgs(value); 331 } 332}; 333 334/// CGFunctionInfo - Class to encapsulate the information about a 335/// function definition. 336class CGFunctionInfo : public llvm::FoldingSetNode { 337 struct ArgInfo { 338 CanQualType type; 339 ABIArgInfo info; 340 }; 341 342 /// The LLVM::CallingConv to use for this function (as specified by the 343 /// user). 344 unsigned CallingConvention : 8; 345 346 /// The LLVM::CallingConv to actually use for this function, which may 347 /// depend on the ABI. 348 unsigned EffectiveCallingConvention : 8; 349 350 /// The clang::CallingConv that this was originally created with. 351 unsigned ASTCallingConvention : 8; 352 353 /// Whether this is an instance method. 354 unsigned InstanceMethod : 1; 355 356 /// Whether this is a chain call. 357 unsigned ChainCall : 1; 358 359 /// Whether this function is noreturn. 360 unsigned NoReturn : 1; 361 362 /// Whether this function is returns-retained. 363 unsigned ReturnsRetained : 1; 364 365 /// How many arguments to pass inreg. 366 unsigned HasRegParm : 1; 367 unsigned RegParm : 3; 368 369 RequiredArgs Required; 370 371 /// The struct representing all arguments passed in memory. Only used when 372 /// passing non-trivial types with inalloca. Not part of the profile. 373 llvm::StructType *ArgStruct; 374 unsigned ArgStructAlign; 375 376 unsigned NumArgs; 377 ArgInfo *getArgsBuffer() { 378 return reinterpret_cast<ArgInfo*>(this+1); 379 } 380 const ArgInfo *getArgsBuffer() const { 381 return reinterpret_cast<const ArgInfo*>(this + 1); 382 } 383 384 CGFunctionInfo() : Required(RequiredArgs::All) {} 385 386public: 387 static CGFunctionInfo *create(unsigned llvmCC, 388 bool instanceMethod, 389 bool chainCall, 390 const FunctionType::ExtInfo &extInfo, 391 CanQualType resultType, 392 ArrayRef<CanQualType> argTypes, 393 RequiredArgs required); 394 395 typedef const ArgInfo *const_arg_iterator; 396 typedef ArgInfo *arg_iterator; 397 398 typedef llvm::iterator_range<arg_iterator> arg_range; 399 typedef llvm::iterator_range<const_arg_iterator> arg_const_range; 400 401 arg_range arguments() { return arg_range(arg_begin(), arg_end()); } 402 arg_const_range arguments() const { 403 return arg_const_range(arg_begin(), arg_end()); 404 } 405 406 const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } 407 const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } 408 arg_iterator arg_begin() { return getArgsBuffer() + 1; } 409 arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } 410 411 unsigned arg_size() const { return NumArgs; } 412 413 bool isVariadic() const { return Required.allowsOptionalArgs(); } 414 RequiredArgs getRequiredArgs() const { return Required; } 415 unsigned getNumRequiredArgs() const { 416 return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); 417 } 418 419 bool isInstanceMethod() const { return InstanceMethod; } 420 421 bool isChainCall() const { return ChainCall; } 422 423 bool isNoReturn() const { return NoReturn; } 424 425 /// In ARC, whether this function retains its return value. This 426 /// is not always reliable for call sites. 427 bool isReturnsRetained() const { return ReturnsRetained; } 428 429 /// getASTCallingConvention() - Return the AST-specified calling 430 /// convention. 431 CallingConv getASTCallingConvention() const { 432 return CallingConv(ASTCallingConvention); 433 } 434 435 /// getCallingConvention - Return the user specified calling 436 /// convention, which has been translated into an LLVM CC. 437 unsigned getCallingConvention() const { return CallingConvention; } 438 439 /// getEffectiveCallingConvention - Return the actual calling convention to 440 /// use, which may depend on the ABI. 441 unsigned getEffectiveCallingConvention() const { 442 return EffectiveCallingConvention; 443 } 444 void setEffectiveCallingConvention(unsigned Value) { 445 EffectiveCallingConvention = Value; 446 } 447 448 bool getHasRegParm() const { return HasRegParm; } 449 unsigned getRegParm() const { return RegParm; } 450 451 FunctionType::ExtInfo getExtInfo() const { 452 return FunctionType::ExtInfo(isNoReturn(), 453 getHasRegParm(), getRegParm(), 454 getASTCallingConvention(), 455 isReturnsRetained()); 456 } 457 458 CanQualType getReturnType() const { return getArgsBuffer()[0].type; } 459 460 ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } 461 const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } 462 463 /// \brief Return true if this function uses inalloca arguments. 464 bool usesInAlloca() const { return ArgStruct; } 465 466 /// \brief Get the struct type used to represent all the arguments in memory. 467 llvm::StructType *getArgStruct() const { return ArgStruct; } 468 CharUnits getArgStructAlignment() const { 469 return CharUnits::fromQuantity(ArgStructAlign); 470 } 471 void setArgStruct(llvm::StructType *Ty, CharUnits Align) { 472 ArgStruct = Ty; 473 ArgStructAlign = Align.getQuantity(); 474 } 475 476 void Profile(llvm::FoldingSetNodeID &ID) { 477 ID.AddInteger(getASTCallingConvention()); 478 ID.AddBoolean(InstanceMethod); 479 ID.AddBoolean(ChainCall); 480 ID.AddBoolean(NoReturn); 481 ID.AddBoolean(ReturnsRetained); 482 ID.AddBoolean(HasRegParm); 483 ID.AddInteger(RegParm); 484 ID.AddInteger(Required.getOpaqueData()); 485 getReturnType().Profile(ID); 486 for (const auto &I : arguments()) 487 I.type.Profile(ID); 488 } 489 static void Profile(llvm::FoldingSetNodeID &ID, 490 bool InstanceMethod, 491 bool ChainCall, 492 const FunctionType::ExtInfo &info, 493 RequiredArgs required, 494 CanQualType resultType, 495 ArrayRef<CanQualType> argTypes) { 496 ID.AddInteger(info.getCC()); 497 ID.AddBoolean(InstanceMethod); 498 ID.AddBoolean(ChainCall); 499 ID.AddBoolean(info.getNoReturn()); 500 ID.AddBoolean(info.getProducesResult()); 501 ID.AddBoolean(info.getHasRegParm()); 502 ID.AddInteger(info.getRegParm()); 503 ID.AddInteger(required.getOpaqueData()); 504 resultType.Profile(ID); 505 for (ArrayRef<CanQualType>::iterator 506 i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { 507 i->Profile(ID); 508 } 509 } 510}; 511 512/// CGCalleeInfo - Class to encapsulate the information about a callee to be 513/// used during the generation of call/invoke instructions. 514class CGCalleeInfo { 515 /// \brief The function proto type of the callee. 516 const FunctionProtoType *CalleeProtoTy; 517 /// \brief The function declaration of the callee. 518 const Decl *CalleeDecl; 519 520public: 521 explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {} 522 CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl) 523 : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} 524 CGCalleeInfo(const FunctionProtoType *calleeProtoTy) 525 : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {} 526 CGCalleeInfo(const Decl *calleeDecl) 527 : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} 528 529 const FunctionProtoType *getCalleeFunctionProtoType() { 530 return CalleeProtoTy; 531 } 532 const Decl *getCalleeDecl() { return CalleeDecl; } 533}; 534 535} // end namespace CodeGen 536} // end namespace clang 537 538#endif 539