xref: /llvm-project/llvm/lib/Transforms/IPO/ExpandVariadics.cpp (revision 6924fc03260370876f7091ba06cdc350989ac3c5)
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