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