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