1 //===-- ExpandVariadicsPass.cpp --------------------------------*- C++ -*-=// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This is an optimization pass for variadic functions. If called from codegen, 10 // it can serve as the implementation of variadic functions for a given target. 11 // 12 // The strategy is to turn the ... part of a variadic function into a va_list 13 // and fix up the call sites. The majority of the pass is target independent. 14 // The exceptions are the va_list type itself and the rules for where to store 15 // variables in memory such that va_arg can iterate over them given a va_list. 16 // 17 // The majority of the plumbing is splitting the variadic function into a 18 // single basic block that packs the variadic arguments into a va_list and 19 // a second function that does the work of the original. That packing is 20 // exactly what is done by va_start. Further, the transform from ... to va_list 21 // replaced va_start with an operation to copy a va_list from the new argument, 22 // which is exactly a va_copy. This is useful for reducing target-dependence. 23 // 24 // A va_list instance is a forward iterator, where the primary operation va_arg 25 // is dereference-then-increment. This interface forces significant convergent 26 // evolution between target specific implementations. The variation in runtime 27 // data layout is limited to that representable by the iterator, parameterised 28 // by the type passed to the va_arg instruction. 29 // 30 // Therefore the majority of the target specific subtlety is packing arguments 31 // into a stack allocated buffer such that a va_list can be initialised with it 32 // and the va_arg expansion for the target will find the arguments at runtime. 33 // 34 // The aggregate effect is to unblock other transforms, most critically the 35 // general purpose inliner. Known calls to variadic functions become zero cost. 36 // 37 // Consistency with clang is primarily tested by emitting va_arg using clang 38 // then expanding the variadic functions using this pass, followed by trying 39 // to constant fold the functions to no-ops. 40 // 41 // Target specific behaviour is tested in IR - mainly checking that values are 42 // put into positions in call frames that make sense for that particular target. 43 // 44 // There is one "clever" invariant in use. va_start intrinsics that are not 45 // within a varidic functions are an error in the IR verifier. When this 46 // transform moves blocks from a variadic function into a fixed arity one, it 47 // moves va_start intrinsics along with everything else. That means that the 48 // va_start intrinsics that need to be rewritten to use the trailing argument 49 // are exactly those that are in non-variadic functions so no further state 50 // is needed to distinguish those that need to be rewritten. 51 // 52 //===----------------------------------------------------------------------===// 53 54 #include "llvm/Transforms/IPO/ExpandVariadics.h" 55 #include "llvm/ADT/SmallVector.h" 56 #include "llvm/IR/Constants.h" 57 #include "llvm/IR/IRBuilder.h" 58 #include "llvm/IR/IntrinsicInst.h" 59 #include "llvm/IR/Module.h" 60 #include "llvm/IR/PassManager.h" 61 #include "llvm/InitializePasses.h" 62 #include "llvm/Pass.h" 63 #include "llvm/Support/CommandLine.h" 64 #include "llvm/TargetParser/Triple.h" 65 #include "llvm/Transforms/Utils/ModuleUtils.h" 66 67 #define DEBUG_TYPE "expand-variadics" 68 69 using namespace llvm; 70 71 namespace { 72 73 cl::opt<ExpandVariadicsMode> ExpandVariadicsModeOption( 74 DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), 75 cl::init(ExpandVariadicsMode::Unspecified), 76 cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", 77 "Use the implementation defaults"), 78 clEnumValN(ExpandVariadicsMode::Disable, "disable", 79 "Disable the pass entirely"), 80 clEnumValN(ExpandVariadicsMode::Optimize, "optimize", 81 "Optimise without changing ABI"), 82 clEnumValN(ExpandVariadicsMode::Lowering, "lowering", 83 "Change variadic calling convention"))); 84 85 bool commandLineOverride() { 86 return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; 87 } 88 89 // Instances of this class encapsulate the target-dependant behaviour as a 90 // function of triple. Implementing a new ABI is adding a case to the switch 91 // in create(llvm::Triple) at the end of this file. 92 // This class may end up instantiated in TargetMachine instances, keeping it 93 // here for now until enough targets are implemented for the API to evolve. 94 class VariadicABIInfo { 95 protected: 96 VariadicABIInfo() = default; 97 98 public: 99 static std::unique_ptr<VariadicABIInfo> create(const Triple &T); 100 101 // Allow overriding whether the pass runs on a per-target basis 102 virtual bool enableForTarget() = 0; 103 104 // Whether a valist instance is passed by value or by address 105 // I.e. does it need to be alloca'ed and stored into, or can 106 // it be passed directly in a SSA register 107 virtual bool vaListPassedInSSARegister() = 0; 108 109 // The type of a va_list iterator object 110 virtual Type *vaListType(LLVMContext &Ctx) = 0; 111 112 // The type of a va_list as a function argument as lowered by C 113 virtual Type *vaListParameterType(Module &M) = 0; 114 115 // Initialize an allocated va_list object to point to an already 116 // initialized contiguous memory region. 117 // Return the value to pass as the va_list argument 118 virtual Value *initializeVaList(Module &M, LLVMContext &Ctx, 119 IRBuilder<> &Builder, AllocaInst *VaList, 120 Value *Buffer) = 0; 121 122 struct VAArgSlotInfo { 123 Align DataAlign; // With respect to the call frame 124 bool Indirect; // Passed via a pointer 125 }; 126 virtual VAArgSlotInfo slotInfo(const DataLayout &DL, Type *Parameter) = 0; 127 128 // Targets implemented so far all have the same trivial lowering for these 129 bool vaEndIsNop() { return true; } 130 bool vaCopyIsMemcpy() { return true; } 131 132 virtual ~VariadicABIInfo() = default; 133 }; 134 135 // Module implements getFunction() which returns nullptr on missing declaration 136 // and getOrInsertFunction which creates one when absent. Intrinsics.h only 137 // implements getDeclaration which creates one when missing. Checking whether 138 // an intrinsic exists thus inserts it in the module and it then needs to be 139 // deleted again to clean up. 140 // The right name for the two functions on intrinsics would match Module::, 141 // but doing that in a single change would introduce nullptr dereferences 142 // where currently there are none. The minimal collateral damage approach 143 // would split the change over a release to help downstream branches. As it 144 // is unclear what approach will be preferred, implementing the trivial 145 // function here in the meantime to decouple from that discussion. 146 Function *getPreexistingDeclaration(Module *M, Intrinsic::ID Id, 147 ArrayRef<Type *> Tys = {}) { 148 if (Tys.empty()) 149 return Intrinsic::getDeclarationIfExists(M, Id); 150 auto *FT = Intrinsic::getType(M->getContext(), Id, Tys); 151 return Intrinsic::getDeclarationIfExists(M, Id, Tys, FT); 152 } 153 154 class ExpandVariadics : public ModulePass { 155 156 // The pass construction sets the default to optimize when called from middle 157 // end and lowering when called from the backend. The command line variable 158 // overrides that. This is useful for testing and debugging. It also allows 159 // building an applications with variadic functions wholly removed if one 160 // has sufficient control over the dependencies, e.g. a statically linked 161 // clang that has no variadic function calls remaining in the binary. 162 163 public: 164 static char ID; 165 const ExpandVariadicsMode Mode; 166 std::unique_ptr<VariadicABIInfo> ABI; 167 168 ExpandVariadics(ExpandVariadicsMode Mode) 169 : ModulePass(ID), 170 Mode(commandLineOverride() ? ExpandVariadicsModeOption : Mode) {} 171 172 StringRef getPassName() const override { return "Expand variadic functions"; } 173 174 bool rewriteABI() { return Mode == ExpandVariadicsMode::Lowering; } 175 176 bool runOnModule(Module &M) override; 177 178 bool runOnFunction(Module &M, IRBuilder<> &Builder, Function *F); 179 180 Function *replaceAllUsesWithNewDeclaration(Module &M, 181 Function *OriginalFunction); 182 183 Function *deriveFixedArityReplacement(Module &M, IRBuilder<> &Builder, 184 Function *OriginalFunction); 185 186 Function *defineVariadicWrapper(Module &M, IRBuilder<> &Builder, 187 Function *VariadicWrapper, 188 Function *FixedArityReplacement); 189 190 bool expandCall(Module &M, IRBuilder<> &Builder, CallBase *CB, FunctionType *, 191 Function *NF); 192 193 // The intrinsic functions va_copy and va_end are removed unconditionally. 194 // They correspond to a memcpy and a no-op on all implemented targets. 195 // The va_start intrinsic is removed from basic blocks that were not created 196 // by this pass, some may remain if needed to maintain the external ABI. 197 198 template <Intrinsic::ID ID, typename InstructionType> 199 bool expandIntrinsicUsers(Module &M, IRBuilder<> &Builder, 200 PointerType *IntrinsicArgType) { 201 bool Changed = false; 202 const DataLayout &DL = M.getDataLayout(); 203 if (Function *Intrinsic = 204 getPreexistingDeclaration(&M, ID, {IntrinsicArgType})) { 205 for (User *U : make_early_inc_range(Intrinsic->users())) 206 if (auto *I = dyn_cast<InstructionType>(U)) 207 Changed |= expandVAIntrinsicCall(Builder, DL, I); 208 209 if (Intrinsic->use_empty()) 210 Intrinsic->eraseFromParent(); 211 } 212 return Changed; 213 } 214 215 bool expandVAIntrinsicUsersWithAddrspace(Module &M, IRBuilder<> &Builder, 216 unsigned Addrspace) { 217 auto &Ctx = M.getContext(); 218 PointerType *IntrinsicArgType = PointerType::get(Ctx, Addrspace); 219 bool Changed = false; 220 221 // expand vastart before vacopy as vastart may introduce a vacopy 222 Changed |= expandIntrinsicUsers<Intrinsic::vastart, VAStartInst>( 223 M, Builder, IntrinsicArgType); 224 Changed |= expandIntrinsicUsers<Intrinsic::vaend, VAEndInst>( 225 M, Builder, IntrinsicArgType); 226 Changed |= expandIntrinsicUsers<Intrinsic::vacopy, VACopyInst>( 227 M, Builder, IntrinsicArgType); 228 return Changed; 229 } 230 231 bool expandVAIntrinsicCall(IRBuilder<> &Builder, const DataLayout &DL, 232 VAStartInst *Inst); 233 234 bool expandVAIntrinsicCall(IRBuilder<> &, const DataLayout &, 235 VAEndInst *Inst); 236 237 bool expandVAIntrinsicCall(IRBuilder<> &Builder, const DataLayout &DL, 238 VACopyInst *Inst); 239 240 FunctionType *inlinableVariadicFunctionType(Module &M, FunctionType *FTy) { 241 // The type of "FTy" with the ... removed and a va_list appended 242 SmallVector<Type *> ArgTypes(FTy->params()); 243 ArgTypes.push_back(ABI->vaListParameterType(M)); 244 return FunctionType::get(FTy->getReturnType(), ArgTypes, 245 /*IsVarArgs=*/false); 246 } 247 248 static ConstantInt *sizeOfAlloca(LLVMContext &Ctx, const DataLayout &DL, 249 AllocaInst *Alloced) { 250 std::optional<TypeSize> AllocaTypeSize = Alloced->getAllocationSize(DL); 251 uint64_t AsInt = AllocaTypeSize ? AllocaTypeSize->getFixedValue() : 0; 252 return ConstantInt::get(Type::getInt64Ty(Ctx), AsInt); 253 } 254 255 bool expansionApplicableToFunction(Module &M, Function *F) { 256 if (F->isIntrinsic() || !F->isVarArg() || 257 F->hasFnAttribute(Attribute::Naked)) 258 return false; 259 260 if (F->getCallingConv() != CallingConv::C) 261 return false; 262 263 if (rewriteABI()) 264 return true; 265 266 if (!F->hasExactDefinition()) 267 return false; 268 269 return true; 270 } 271 272 bool expansionApplicableToFunctionCall(CallBase *CB) { 273 if (CallInst *CI = dyn_cast<CallInst>(CB)) { 274 if (CI->isMustTailCall()) { 275 // Cannot expand musttail calls 276 return false; 277 } 278 279 if (CI->getCallingConv() != CallingConv::C) 280 return false; 281 282 return true; 283 } 284 285 if (isa<InvokeInst>(CB)) { 286 // Invoke not implemented in initial implementation of pass 287 return false; 288 } 289 290 // Other unimplemented derivative of CallBase 291 return false; 292 } 293 294 class ExpandedCallFrame { 295 // Helper for constructing an alloca instance containing the arguments bound 296 // to the variadic ... parameter, rearranged to allow indexing through a 297 // va_list iterator 298 enum { N = 4 }; 299 SmallVector<Type *, N> FieldTypes; 300 enum Tag { Store, Memcpy, Padding }; 301 SmallVector<std::tuple<Value *, uint64_t, Tag>, N> Source; 302 303 template <Tag tag> void append(Type *FieldType, Value *V, uint64_t Bytes) { 304 FieldTypes.push_back(FieldType); 305 Source.push_back({V, Bytes, tag}); 306 } 307 308 public: 309 void store(LLVMContext &Ctx, Type *T, Value *V) { append<Store>(T, V, 0); } 310 311 void memcpy(LLVMContext &Ctx, Type *T, Value *V, uint64_t Bytes) { 312 append<Memcpy>(T, V, Bytes); 313 } 314 315 void padding(LLVMContext &Ctx, uint64_t By) { 316 append<Padding>(ArrayType::get(Type::getInt8Ty(Ctx), By), nullptr, 0); 317 } 318 319 size_t size() const { return FieldTypes.size(); } 320 bool empty() const { return FieldTypes.empty(); } 321 322 StructType *asStruct(LLVMContext &Ctx, StringRef Name) { 323 const bool IsPacked = true; 324 return StructType::create(Ctx, FieldTypes, 325 (Twine(Name) + ".vararg").str(), IsPacked); 326 } 327 328 void initializeStructAlloca(const DataLayout &DL, IRBuilder<> &Builder, 329 AllocaInst *Alloced) { 330 331 StructType *VarargsTy = cast<StructType>(Alloced->getAllocatedType()); 332 333 for (size_t I = 0; I < size(); I++) { 334 335 auto [V, bytes, tag] = Source[I]; 336 337 if (tag == Padding) { 338 assert(V == nullptr); 339 continue; 340 } 341 342 auto Dst = Builder.CreateStructGEP(VarargsTy, Alloced, I); 343 344 assert(V != nullptr); 345 346 if (tag == Store) 347 Builder.CreateStore(V, Dst); 348 349 if (tag == Memcpy) 350 Builder.CreateMemCpy(Dst, {}, V, {}, bytes); 351 } 352 } 353 }; 354 }; 355 356 bool ExpandVariadics::runOnModule(Module &M) { 357 bool Changed = false; 358 if (Mode == ExpandVariadicsMode::Disable) 359 return Changed; 360 361 Triple TT(M.getTargetTriple()); 362 ABI = VariadicABIInfo::create(TT); 363 if (!ABI) 364 return Changed; 365 366 if (!ABI->enableForTarget()) 367 return Changed; 368 369 auto &Ctx = M.getContext(); 370 const DataLayout &DL = M.getDataLayout(); 371 IRBuilder<> Builder(Ctx); 372 373 // Lowering needs to run on all functions exactly once. 374 // Optimize could run on functions containing va_start exactly once. 375 for (Function &F : make_early_inc_range(M)) 376 Changed |= runOnFunction(M, Builder, &F); 377 378 // After runOnFunction, all known calls to known variadic functions have been 379 // replaced. va_start intrinsics are presently (and invalidly!) only present 380 // in functions that used to be variadic and have now been replaced to take a 381 // va_list instead. If lowering as opposed to optimising, calls to unknown 382 // variadic functions have also been replaced. 383 384 { 385 // 0 and AllocaAddrSpace are sufficient for the targets implemented so far 386 unsigned Addrspace = 0; 387 Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, Addrspace); 388 389 Addrspace = DL.getAllocaAddrSpace(); 390 if (Addrspace != 0) 391 Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, Addrspace); 392 } 393 394 if (Mode != ExpandVariadicsMode::Lowering) 395 return Changed; 396 397 for (Function &F : make_early_inc_range(M)) { 398 if (F.isDeclaration()) 399 continue; 400 401 // Now need to track down indirect calls. Can't find those 402 // by walking uses of variadic functions, need to crawl the instruction 403 // stream. Fortunately this is only necessary for the ABI rewrite case. 404 for (BasicBlock &BB : F) { 405 for (Instruction &I : make_early_inc_range(BB)) { 406 if (CallBase *CB = dyn_cast<CallBase>(&I)) { 407 if (CB->isIndirectCall()) { 408 FunctionType *FTy = CB->getFunctionType(); 409 if (FTy->isVarArg()) 410 Changed |= expandCall(M, Builder, CB, FTy, 0); 411 } 412 } 413 } 414 } 415 } 416 417 return Changed; 418 } 419 420 bool ExpandVariadics::runOnFunction(Module &M, IRBuilder<> &Builder, 421 Function *OriginalFunction) { 422 bool Changed = false; 423 424 if (!expansionApplicableToFunction(M, OriginalFunction)) 425 return Changed; 426 427 [[maybe_unused]] const bool OriginalFunctionIsDeclaration = 428 OriginalFunction->isDeclaration(); 429 assert(rewriteABI() || !OriginalFunctionIsDeclaration); 430 431 // Declare a new function and redirect every use to that new function 432 Function *VariadicWrapper = 433 replaceAllUsesWithNewDeclaration(M, OriginalFunction); 434 assert(VariadicWrapper->isDeclaration()); 435 assert(OriginalFunction->use_empty()); 436 437 // Create a new function taking va_list containing the implementation of the 438 // original 439 Function *FixedArityReplacement = 440 deriveFixedArityReplacement(M, Builder, OriginalFunction); 441 assert(OriginalFunction->isDeclaration()); 442 assert(FixedArityReplacement->isDeclaration() == 443 OriginalFunctionIsDeclaration); 444 assert(VariadicWrapper->isDeclaration()); 445 446 // Create a single block forwarding wrapper that turns a ... into a va_list 447 [[maybe_unused]] Function *VariadicWrapperDefine = 448 defineVariadicWrapper(M, Builder, VariadicWrapper, FixedArityReplacement); 449 assert(VariadicWrapperDefine == VariadicWrapper); 450 assert(!VariadicWrapper->isDeclaration()); 451 452 // We now have: 453 // 1. the original function, now as a declaration with no uses 454 // 2. a variadic function that unconditionally calls a fixed arity replacement 455 // 3. a fixed arity function equivalent to the original function 456 457 // Replace known calls to the variadic with calls to the va_list equivalent 458 for (User *U : make_early_inc_range(VariadicWrapper->users())) { 459 if (CallBase *CB = dyn_cast<CallBase>(U)) { 460 Value *CalledOperand = CB->getCalledOperand(); 461 if (VariadicWrapper == CalledOperand) 462 Changed |= 463 expandCall(M, Builder, CB, VariadicWrapper->getFunctionType(), 464 FixedArityReplacement); 465 } 466 } 467 468 // The original function will be erased. 469 // One of the two new functions will become a replacement for the original. 470 // When preserving the ABI, the other is an internal implementation detail. 471 // When rewriting the ABI, RAUW then the variadic one. 472 Function *const ExternallyAccessible = 473 rewriteABI() ? FixedArityReplacement : VariadicWrapper; 474 Function *const InternalOnly = 475 rewriteABI() ? VariadicWrapper : FixedArityReplacement; 476 477 // The external function is the replacement for the original 478 ExternallyAccessible->setLinkage(OriginalFunction->getLinkage()); 479 ExternallyAccessible->setVisibility(OriginalFunction->getVisibility()); 480 ExternallyAccessible->setComdat(OriginalFunction->getComdat()); 481 ExternallyAccessible->takeName(OriginalFunction); 482 483 // Annotate the internal one as internal 484 InternalOnly->setVisibility(GlobalValue::DefaultVisibility); 485 InternalOnly->setLinkage(GlobalValue::InternalLinkage); 486 487 // The original is unused and obsolete 488 OriginalFunction->eraseFromParent(); 489 490 InternalOnly->removeDeadConstantUsers(); 491 492 if (rewriteABI()) { 493 // All known calls to the function have been removed by expandCall 494 // Resolve everything else by replaceAllUsesWith 495 VariadicWrapper->replaceAllUsesWith(FixedArityReplacement); 496 VariadicWrapper->eraseFromParent(); 497 } 498 499 return Changed; 500 } 501 502 Function * 503 ExpandVariadics::replaceAllUsesWithNewDeclaration(Module &M, 504 Function *OriginalFunction) { 505 auto &Ctx = M.getContext(); 506 Function &F = *OriginalFunction; 507 FunctionType *FTy = F.getFunctionType(); 508 Function *NF = Function::Create(FTy, F.getLinkage(), F.getAddressSpace()); 509 510 NF->setName(F.getName() + ".varargs"); 511 NF->IsNewDbgInfoFormat = F.IsNewDbgInfoFormat; 512 513 F.getParent()->getFunctionList().insert(F.getIterator(), NF); 514 515 AttrBuilder ParamAttrs(Ctx); 516 AttributeList Attrs = NF->getAttributes(); 517 Attrs = Attrs.addParamAttributes(Ctx, FTy->getNumParams(), ParamAttrs); 518 NF->setAttributes(Attrs); 519 520 OriginalFunction->replaceAllUsesWith(NF); 521 return NF; 522 } 523 524 Function * 525 ExpandVariadics::deriveFixedArityReplacement(Module &M, IRBuilder<> &Builder, 526 Function *OriginalFunction) { 527 Function &F = *OriginalFunction; 528 // The purpose here is split the variadic function F into two functions 529 // One is a variadic function that bundles the passed argument into a va_list 530 // and passes it to the second function. The second function does whatever 531 // the original F does, except that it takes a va_list instead of the ... 532 533 assert(expansionApplicableToFunction(M, &F)); 534 535 auto &Ctx = M.getContext(); 536 537 // Returned value isDeclaration() is equal to F.isDeclaration() 538 // but that property is not invariant throughout this function 539 const bool FunctionIsDefinition = !F.isDeclaration(); 540 541 FunctionType *FTy = F.getFunctionType(); 542 SmallVector<Type *> ArgTypes(FTy->params()); 543 ArgTypes.push_back(ABI->vaListParameterType(M)); 544 545 FunctionType *NFTy = inlinableVariadicFunctionType(M, FTy); 546 Function *NF = Function::Create(NFTy, F.getLinkage(), F.getAddressSpace()); 547 548 // Note - same attribute handling as DeadArgumentElimination 549 NF->copyAttributesFrom(&F); 550 NF->setComdat(F.getComdat()); 551 F.getParent()->getFunctionList().insert(F.getIterator(), NF); 552 NF->setName(F.getName() + ".valist"); 553 NF->IsNewDbgInfoFormat = F.IsNewDbgInfoFormat; 554 555 AttrBuilder ParamAttrs(Ctx); 556 557 AttributeList Attrs = NF->getAttributes(); 558 Attrs = Attrs.addParamAttributes(Ctx, NFTy->getNumParams() - 1, ParamAttrs); 559 NF->setAttributes(Attrs); 560 561 // Splice the implementation into the new function with minimal changes 562 if (FunctionIsDefinition) { 563 NF->splice(NF->begin(), &F); 564 565 auto NewArg = NF->arg_begin(); 566 for (Argument &Arg : F.args()) { 567 Arg.replaceAllUsesWith(NewArg); 568 NewArg->setName(Arg.getName()); // takeName without killing the old one 569 ++NewArg; 570 } 571 NewArg->setName("varargs"); 572 } 573 574 SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; 575 F.getAllMetadata(MDs); 576 for (auto [KindID, Node] : MDs) 577 NF->addMetadata(KindID, *Node); 578 F.clearMetadata(); 579 580 return NF; 581 } 582 583 Function * 584 ExpandVariadics::defineVariadicWrapper(Module &M, IRBuilder<> &Builder, 585 Function *VariadicWrapper, 586 Function *FixedArityReplacement) { 587 auto &Ctx = Builder.getContext(); 588 const DataLayout &DL = M.getDataLayout(); 589 assert(VariadicWrapper->isDeclaration()); 590 Function &F = *VariadicWrapper; 591 592 assert(F.isDeclaration()); 593 Type *VaListTy = ABI->vaListType(Ctx); 594 595 auto *BB = BasicBlock::Create(Ctx, "entry", &F); 596 Builder.SetInsertPoint(BB); 597 598 AllocaInst *VaListInstance = 599 Builder.CreateAlloca(VaListTy, nullptr, "va_start"); 600 601 Builder.CreateLifetimeStart(VaListInstance, 602 sizeOfAlloca(Ctx, DL, VaListInstance)); 603 604 Builder.CreateIntrinsic(Intrinsic::vastart, {DL.getAllocaPtrType(Ctx)}, 605 {VaListInstance}); 606 607 SmallVector<Value *> Args; 608 for (Argument &A : F.args()) 609 Args.push_back(&A); 610 611 Type *ParameterType = ABI->vaListParameterType(M); 612 if (ABI->vaListPassedInSSARegister()) 613 Args.push_back(Builder.CreateLoad(ParameterType, VaListInstance)); 614 else 615 Args.push_back(Builder.CreateAddrSpaceCast(VaListInstance, ParameterType)); 616 617 CallInst *Result = Builder.CreateCall(FixedArityReplacement, Args); 618 619 Builder.CreateIntrinsic(Intrinsic::vaend, {DL.getAllocaPtrType(Ctx)}, 620 {VaListInstance}); 621 Builder.CreateLifetimeEnd(VaListInstance, 622 sizeOfAlloca(Ctx, DL, VaListInstance)); 623 624 if (Result->getType()->isVoidTy()) 625 Builder.CreateRetVoid(); 626 else 627 Builder.CreateRet(Result); 628 629 return VariadicWrapper; 630 } 631 632 bool ExpandVariadics::expandCall(Module &M, IRBuilder<> &Builder, CallBase *CB, 633 FunctionType *VarargFunctionType, 634 Function *NF) { 635 bool Changed = false; 636 const DataLayout &DL = M.getDataLayout(); 637 638 if (!expansionApplicableToFunctionCall(CB)) { 639 if (rewriteABI()) 640 report_fatal_error("Cannot lower callbase instruction"); 641 return Changed; 642 } 643 644 // This is tricky. The call instruction's function type might not match 645 // the type of the caller. When optimising, can leave it unchanged. 646 // Webassembly detects that inconsistency and repairs it. 647 FunctionType *FuncType = CB->getFunctionType(); 648 if (FuncType != VarargFunctionType) { 649 if (!rewriteABI()) 650 return Changed; 651 FuncType = VarargFunctionType; 652 } 653 654 auto &Ctx = CB->getContext(); 655 656 Align MaxFieldAlign(1); 657 658 // The strategy is to allocate a call frame containing the variadic 659 // arguments laid out such that a target specific va_list can be initialized 660 // with it, such that target specific va_arg instructions will correctly 661 // iterate over it. This means getting the alignment right and sometimes 662 // embedding a pointer to the value instead of embedding the value itself. 663 664 Function *CBF = CB->getParent()->getParent(); 665 666 ExpandedCallFrame Frame; 667 668 uint64_t CurrentOffset = 0; 669 670 for (unsigned I = FuncType->getNumParams(), E = CB->arg_size(); I < E; ++I) { 671 Value *ArgVal = CB->getArgOperand(I); 672 const bool IsByVal = CB->paramHasAttr(I, Attribute::ByVal); 673 const bool IsByRef = CB->paramHasAttr(I, Attribute::ByRef); 674 675 // The type of the value being passed, decoded from byval/byref metadata if 676 // required 677 Type *const UnderlyingType = IsByVal ? CB->getParamByValType(I) 678 : IsByRef ? CB->getParamByRefType(I) 679 : ArgVal->getType(); 680 const uint64_t UnderlyingSize = 681 DL.getTypeAllocSize(UnderlyingType).getFixedValue(); 682 683 // The type to be written into the call frame 684 Type *FrameFieldType = UnderlyingType; 685 686 // The value to copy from when initialising the frame alloca 687 Value *SourceValue = ArgVal; 688 689 VariadicABIInfo::VAArgSlotInfo SlotInfo = ABI->slotInfo(DL, UnderlyingType); 690 691 if (SlotInfo.Indirect) { 692 // The va_arg lowering loads through a pointer. Set up an alloca to aim 693 // that pointer at. 694 Builder.SetInsertPointPastAllocas(CBF); 695 Builder.SetCurrentDebugLocation(CB->getStableDebugLoc()); 696 Value *CallerCopy = 697 Builder.CreateAlloca(UnderlyingType, nullptr, "IndirectAlloca"); 698 699 Builder.SetInsertPoint(CB); 700 if (IsByVal) 701 Builder.CreateMemCpy(CallerCopy, {}, ArgVal, {}, UnderlyingSize); 702 else 703 Builder.CreateStore(ArgVal, CallerCopy); 704 705 // Indirection now handled, pass the alloca ptr by value 706 FrameFieldType = DL.getAllocaPtrType(Ctx); 707 SourceValue = CallerCopy; 708 } 709 710 // Alignment of the value within the frame 711 // This probably needs to be controllable as a function of type 712 Align DataAlign = SlotInfo.DataAlign; 713 714 MaxFieldAlign = std::max(MaxFieldAlign, DataAlign); 715 716 uint64_t DataAlignV = DataAlign.value(); 717 if (uint64_t Rem = CurrentOffset % DataAlignV) { 718 // Inject explicit padding to deal with alignment requirements 719 uint64_t Padding = DataAlignV - Rem; 720 Frame.padding(Ctx, Padding); 721 CurrentOffset += Padding; 722 } 723 724 if (SlotInfo.Indirect) { 725 Frame.store(Ctx, FrameFieldType, SourceValue); 726 } else { 727 if (IsByVal) 728 Frame.memcpy(Ctx, FrameFieldType, SourceValue, UnderlyingSize); 729 else 730 Frame.store(Ctx, FrameFieldType, SourceValue); 731 } 732 733 CurrentOffset += DL.getTypeAllocSize(FrameFieldType).getFixedValue(); 734 } 735 736 if (Frame.empty()) { 737 // Not passing any arguments, hopefully va_arg won't try to read any 738 // Creating a single byte frame containing nothing to point the va_list 739 // instance as that is less special-casey in the compiler and probably 740 // easier to interpret in a debugger. 741 Frame.padding(Ctx, 1); 742 } 743 744 StructType *VarargsTy = Frame.asStruct(Ctx, CBF->getName()); 745 746 // The struct instance needs to be at least MaxFieldAlign for the alignment of 747 // the fields to be correct at runtime. Use the native stack alignment instead 748 // if that's greater as that tends to give better codegen. 749 // This is an awkward way to guess whether there is a known stack alignment 750 // without hitting an assert in DL.getStackAlignment, 1024 is an arbitrary 751 // number likely to be greater than the natural stack alignment. 752 Align AllocaAlign = MaxFieldAlign; 753 if (MaybeAlign StackAlign = DL.getStackAlignment(); 754 StackAlign && *StackAlign > AllocaAlign) 755 AllocaAlign = *StackAlign; 756 757 // Put the alloca to hold the variadic args in the entry basic block. 758 Builder.SetInsertPointPastAllocas(CBF); 759 760 // SetCurrentDebugLocation when the builder SetInsertPoint method does not 761 Builder.SetCurrentDebugLocation(CB->getStableDebugLoc()); 762 763 // The awkward construction here is to set the alignment on the instance 764 AllocaInst *Alloced = Builder.Insert( 765 new AllocaInst(VarargsTy, DL.getAllocaAddrSpace(), nullptr, AllocaAlign), 766 "vararg_buffer"); 767 Changed = true; 768 assert(Alloced->getAllocatedType() == VarargsTy); 769 770 // Initialize the fields in the struct 771 Builder.SetInsertPoint(CB); 772 Builder.CreateLifetimeStart(Alloced, sizeOfAlloca(Ctx, DL, Alloced)); 773 Frame.initializeStructAlloca(DL, Builder, Alloced); 774 775 const unsigned NumArgs = FuncType->getNumParams(); 776 SmallVector<Value *> Args(CB->arg_begin(), CB->arg_begin() + NumArgs); 777 778 // Initialize a va_list pointing to that struct and pass it as the last 779 // argument 780 AllocaInst *VaList = nullptr; 781 { 782 if (!ABI->vaListPassedInSSARegister()) { 783 Type *VaListTy = ABI->vaListType(Ctx); 784 Builder.SetInsertPointPastAllocas(CBF); 785 Builder.SetCurrentDebugLocation(CB->getStableDebugLoc()); 786 VaList = Builder.CreateAlloca(VaListTy, nullptr, "va_argument"); 787 Builder.SetInsertPoint(CB); 788 Builder.CreateLifetimeStart(VaList, sizeOfAlloca(Ctx, DL, VaList)); 789 } 790 Builder.SetInsertPoint(CB); 791 Args.push_back(ABI->initializeVaList(M, Ctx, Builder, VaList, Alloced)); 792 } 793 794 // Attributes excluding any on the vararg arguments 795 AttributeList PAL = CB->getAttributes(); 796 if (!PAL.isEmpty()) { 797 SmallVector<AttributeSet, 8> ArgAttrs; 798 for (unsigned ArgNo = 0; ArgNo < NumArgs; ArgNo++) 799 ArgAttrs.push_back(PAL.getParamAttrs(ArgNo)); 800 PAL = 801 AttributeList::get(Ctx, PAL.getFnAttrs(), PAL.getRetAttrs(), ArgAttrs); 802 } 803 804 SmallVector<OperandBundleDef, 1> OpBundles; 805 CB->getOperandBundlesAsDefs(OpBundles); 806 807 CallBase *NewCB = nullptr; 808 809 if (CallInst *CI = dyn_cast<CallInst>(CB)) { 810 Value *Dst = NF ? NF : CI->getCalledOperand(); 811 FunctionType *NFTy = inlinableVariadicFunctionType(M, VarargFunctionType); 812 813 NewCB = CallInst::Create(NFTy, Dst, Args, OpBundles, "", CI->getIterator()); 814 815 CallInst::TailCallKind TCK = CI->getTailCallKind(); 816 assert(TCK != CallInst::TCK_MustTail); 817 818 // Can't tail call a function that is being passed a pointer to an alloca 819 if (TCK == CallInst::TCK_Tail) 820 TCK = CallInst::TCK_None; 821 CI->setTailCallKind(TCK); 822 823 } else { 824 llvm_unreachable("Unreachable when !expansionApplicableToFunctionCall()"); 825 } 826 827 if (VaList) 828 Builder.CreateLifetimeEnd(VaList, sizeOfAlloca(Ctx, DL, VaList)); 829 830 Builder.CreateLifetimeEnd(Alloced, sizeOfAlloca(Ctx, DL, Alloced)); 831 832 NewCB->setAttributes(PAL); 833 NewCB->takeName(CB); 834 NewCB->setCallingConv(CB->getCallingConv()); 835 NewCB->setDebugLoc(DebugLoc()); 836 837 // DeadArgElim and ArgPromotion copy exactly this metadata 838 NewCB->copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg}); 839 840 CB->replaceAllUsesWith(NewCB); 841 CB->eraseFromParent(); 842 return Changed; 843 } 844 845 bool ExpandVariadics::expandVAIntrinsicCall(IRBuilder<> &Builder, 846 const DataLayout &DL, 847 VAStartInst *Inst) { 848 // Only removing va_start instructions that are not in variadic functions. 849 // Those would be rejected by the IR verifier before this pass. 850 // After splicing basic blocks from a variadic function into a fixed arity 851 // one the va_start that used to refer to the ... parameter still exist. 852 // There are also variadic functions that this pass did not change and 853 // va_start instances in the created single block wrapper functions. 854 // Replace exactly the instances in non-variadic functions as those are 855 // the ones to be fixed up to use the va_list passed as the final argument. 856 857 Function *ContainingFunction = Inst->getFunction(); 858 if (ContainingFunction->isVarArg()) { 859 return false; 860 } 861 862 // The last argument is a vaListParameterType, either a va_list 863 // or a pointer to one depending on the target. 864 bool PassedByValue = ABI->vaListPassedInSSARegister(); 865 Argument *PassedVaList = 866 ContainingFunction->getArg(ContainingFunction->arg_size() - 1); 867 868 // va_start takes a pointer to a va_list, e.g. one on the stack 869 Value *VaStartArg = Inst->getArgList(); 870 871 Builder.SetInsertPoint(Inst); 872 873 if (PassedByValue) { 874 // The general thing to do is create an alloca, store the va_list argument 875 // to it, then create a va_copy. When vaCopyIsMemcpy(), this optimises to a 876 // store to the VaStartArg. 877 assert(ABI->vaCopyIsMemcpy()); 878 Builder.CreateStore(PassedVaList, VaStartArg); 879 } else { 880 881 // Otherwise emit a vacopy to pick up target-specific handling if any 882 auto &Ctx = Builder.getContext(); 883 884 Builder.CreateIntrinsic(Intrinsic::vacopy, {DL.getAllocaPtrType(Ctx)}, 885 {VaStartArg, PassedVaList}); 886 } 887 888 Inst->eraseFromParent(); 889 return true; 890 } 891 892 bool ExpandVariadics::expandVAIntrinsicCall(IRBuilder<> &, const DataLayout &, 893 VAEndInst *Inst) { 894 assert(ABI->vaEndIsNop()); 895 Inst->eraseFromParent(); 896 return true; 897 } 898 899 bool ExpandVariadics::expandVAIntrinsicCall(IRBuilder<> &Builder, 900 const DataLayout &DL, 901 VACopyInst *Inst) { 902 assert(ABI->vaCopyIsMemcpy()); 903 Builder.SetInsertPoint(Inst); 904 905 auto &Ctx = Builder.getContext(); 906 Type *VaListTy = ABI->vaListType(Ctx); 907 uint64_t Size = DL.getTypeAllocSize(VaListTy).getFixedValue(); 908 909 Builder.CreateMemCpy(Inst->getDest(), {}, Inst->getSrc(), {}, 910 Builder.getInt32(Size)); 911 912 Inst->eraseFromParent(); 913 return true; 914 } 915 916 struct Amdgpu final : public VariadicABIInfo { 917 918 bool enableForTarget() override { return true; } 919 920 bool vaListPassedInSSARegister() override { return true; } 921 922 Type *vaListType(LLVMContext &Ctx) override { 923 return PointerType::getUnqual(Ctx); 924 } 925 926 Type *vaListParameterType(Module &M) override { 927 return PointerType::getUnqual(M.getContext()); 928 } 929 930 Value *initializeVaList(Module &M, LLVMContext &Ctx, IRBuilder<> &Builder, 931 AllocaInst * /*va_list*/, Value *Buffer) override { 932 // Given Buffer, which is an AllocInst of vararg_buffer 933 // need to return something usable as parameter type 934 return Builder.CreateAddrSpaceCast(Buffer, vaListParameterType(M)); 935 } 936 937 VAArgSlotInfo slotInfo(const DataLayout &DL, Type *Parameter) override { 938 return {Align(4), false}; 939 } 940 }; 941 942 struct NVPTX final : public VariadicABIInfo { 943 944 bool enableForTarget() override { return true; } 945 946 bool vaListPassedInSSARegister() override { return true; } 947 948 Type *vaListType(LLVMContext &Ctx) override { 949 return PointerType::getUnqual(Ctx); 950 } 951 952 Type *vaListParameterType(Module &M) override { 953 return PointerType::getUnqual(M.getContext()); 954 } 955 956 Value *initializeVaList(Module &M, LLVMContext &Ctx, IRBuilder<> &Builder, 957 AllocaInst *, Value *Buffer) override { 958 return Builder.CreateAddrSpaceCast(Buffer, vaListParameterType(M)); 959 } 960 961 VAArgSlotInfo slotInfo(const DataLayout &DL, Type *Parameter) override { 962 // NVPTX expects natural alignment in all cases. The variadic call ABI will 963 // handle promoting types to their appropriate size and alignment. 964 Align A = DL.getABITypeAlign(Parameter); 965 return {A, false}; 966 } 967 }; 968 969 struct Wasm final : public VariadicABIInfo { 970 971 bool enableForTarget() override { 972 // Currently wasm is only used for testing. 973 return commandLineOverride(); 974 } 975 976 bool vaListPassedInSSARegister() override { return true; } 977 978 Type *vaListType(LLVMContext &Ctx) override { 979 return PointerType::getUnqual(Ctx); 980 } 981 982 Type *vaListParameterType(Module &M) override { 983 return PointerType::getUnqual(M.getContext()); 984 } 985 986 Value *initializeVaList(Module &M, LLVMContext &Ctx, IRBuilder<> &Builder, 987 AllocaInst * /*va_list*/, Value *Buffer) override { 988 return Buffer; 989 } 990 991 VAArgSlotInfo slotInfo(const DataLayout &DL, Type *Parameter) override { 992 LLVMContext &Ctx = Parameter->getContext(); 993 const unsigned MinAlign = 4; 994 Align A = DL.getABITypeAlign(Parameter); 995 if (A < MinAlign) 996 A = Align(MinAlign); 997 998 if (auto *S = dyn_cast<StructType>(Parameter)) { 999 if (S->getNumElements() > 1) { 1000 return {DL.getABITypeAlign(PointerType::getUnqual(Ctx)), true}; 1001 } 1002 } 1003 1004 return {A, false}; 1005 } 1006 }; 1007 1008 std::unique_ptr<VariadicABIInfo> VariadicABIInfo::create(const Triple &T) { 1009 switch (T.getArch()) { 1010 case Triple::r600: 1011 case Triple::amdgcn: { 1012 return std::make_unique<Amdgpu>(); 1013 } 1014 1015 case Triple::wasm32: { 1016 return std::make_unique<Wasm>(); 1017 } 1018 1019 case Triple::nvptx: 1020 case Triple::nvptx64: { 1021 return std::make_unique<NVPTX>(); 1022 } 1023 1024 default: 1025 return {}; 1026 } 1027 } 1028 1029 } // namespace 1030 1031 char ExpandVariadics::ID = 0; 1032 1033 INITIALIZE_PASS(ExpandVariadics, DEBUG_TYPE, "Expand variadic functions", false, 1034 false) 1035 1036 ModulePass *llvm::createExpandVariadicsPass(ExpandVariadicsMode M) { 1037 return new ExpandVariadics(M); 1038 } 1039 1040 PreservedAnalyses ExpandVariadicsPass::run(Module &M, ModuleAnalysisManager &) { 1041 return ExpandVariadics(Mode).runOnModule(M) ? PreservedAnalyses::none() 1042 : PreservedAnalyses::all(); 1043 } 1044 1045 ExpandVariadicsPass::ExpandVariadicsPass(ExpandVariadicsMode M) : Mode(M) {} 1046