66#define DEBUG_TYPE "expand-variadics" 
   76                          "Use the implementation defaults"),
 
   78                          "Disable the pass entirely"),
 
   80                          "Optimise without changing ABI"),
 
   82                          "Change variadic calling convention")));
 
   84bool commandLineOverride() {
 
   93class VariadicABIInfo {
 
   95  VariadicABIInfo() = 
default;
 
   98  static std::unique_ptr<VariadicABIInfo> create(
const Triple &
T);
 
  101  virtual bool enableForTarget() = 0;
 
  106  virtual bool vaListPassedInSSARegister() = 0;
 
  112  virtual Type *vaListParameterType(
Module &M) = 0;
 
  121  struct VAArgSlotInfo {
 
  128  bool vaEndIsNop() { 
return true; }
 
  129  bool vaCopyIsMemcpy() { 
return true; }
 
  131  virtual ~VariadicABIInfo() = 
default;
 
  146  std::unique_ptr<VariadicABIInfo> ABI;
 
  150        Mode(commandLineOverride() ? ExpandVariadicsModeOption : 
Mode) {}
 
  152  StringRef getPassName()
 const override { 
return "Expand variadic functions"; }
 
  156  bool runOnModule(
Module &M) 
override;
 
  178  template <Intrinsic::ID ID, 
typename InstructionType>
 
  187          Changed |= expandVAIntrinsicCall(Builder, 
DL, 
I);
 
  196                                           unsigned Addrspace) {
 
  197    auto &Ctx = M.getContext();
 
  202    Changed |= expandIntrinsicUsers<Intrinsic::vastart, VAStartInst>(
 
  203        M, Builder, IntrinsicArgType);
 
  204    Changed |= expandIntrinsicUsers<Intrinsic::vaend, VAEndInst>(
 
  205        M, Builder, IntrinsicArgType);
 
  206    Changed |= expandIntrinsicUsers<Intrinsic::vacopy, VACopyInst>(
 
  207        M, Builder, IntrinsicArgType);
 
  223    ArgTypes.
push_back(ABI->vaListParameterType(M));
 
  229    if (
F->isIntrinsic() || !
F->isVarArg() ||
 
  230        F->hasFnAttribute(Attribute::Naked))
 
  239    if (!
F->hasExactDefinition())
 
  245  bool expansionApplicableToFunctionCall(
CallBase *CB) {
 
  247      if (CI->isMustTailCall()) {
 
  267  class ExpandedCallFrame {
 
  273    enum Tag { Store, Memcpy, Padding };
 
  278      Source.push_back({V, Bytes, tag});
 
  285      append<Memcpy>(
T, V, Bytes);
 
  292    size_t size()
 const { 
return FieldTypes.
size(); }
 
  293    bool empty()
 const { 
return FieldTypes.
empty(); }
 
  296      const bool IsPacked = 
true;
 
  298                                (
Twine(Name) + 
".vararg").str(), IsPacked);
 
  306      for (
size_t I = 0; 
I < 
size(); 
I++) {
 
  308        auto [V, bytes, tag] = Source[
I];
 
  310        if (tag == Padding) {
 
  315        auto Dst = Builder.CreateStructGEP(VarargsTy, Alloced, 
I);
 
  320          Builder.CreateStore(V, Dst);
 
  323          Builder.CreateMemCpy(Dst, {}, V, {}, bytes);
 
  329bool ExpandVariadics::runOnModule(
Module &M) {
 
  334  Triple TT(M.getTargetTriple());
 
  335  ABI = VariadicABIInfo::create(TT);
 
  339  if (!ABI->enableForTarget())
 
  342  auto &Ctx = M.getContext();
 
  359    unsigned Addrspace = 0;
 
  360    Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, Addrspace);
 
  362    Addrspace = 
DL.getAllocaAddrSpace();
 
  364      Changed |= expandVAIntrinsicUsersWithAddrspace(M, Builder, Addrspace);
 
  371    if (
F.isDeclaration())
 
  380          if (CB->isIndirectCall()) {
 
  383              Changed |= expandCall(M, Builder, CB, FTy, 
nullptr);
 
  397  if (!expansionApplicableToFunction(M, OriginalFunction))
 
  400  [[maybe_unused]] 
const bool OriginalFunctionIsDeclaration =
 
  402  assert(rewriteABI() || !OriginalFunctionIsDeclaration);
 
  406      replaceAllUsesWithNewDeclaration(M, OriginalFunction);
 
  413      deriveFixedArityReplacement(M, Builder, OriginalFunction);
 
  416         OriginalFunctionIsDeclaration);
 
  420  [[maybe_unused]] 
Function *VariadicWrapperDefine =
 
  421      defineVariadicWrapper(M, Builder, VariadicWrapper, FixedArityReplacement);
 
  422  assert(VariadicWrapperDefine == VariadicWrapper);
 
  433      Value *CalledOperand = CB->getCalledOperand();
 
  434      if (VariadicWrapper == CalledOperand)
 
  437                       FixedArityReplacement);
 
  445  Function *
const ExternallyAccessible =
 
  446      rewriteABI() ? FixedArityReplacement : VariadicWrapper;
 
  448      rewriteABI() ? VariadicWrapper : FixedArityReplacement;
 
  454  ExternallyAccessible->
takeName(OriginalFunction);
 
  476ExpandVariadics::replaceAllUsesWithNewDeclaration(
Module &M,
 
  483  NF->
setName(
F.getName() + 
".varargs");
 
  485  F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
 
  487  AttrBuilder ParamAttrs(Ctx);
 
  489  Attrs = Attrs.addParamAttributes(Ctx, FTy->getNumParams(), ParamAttrs);
 
  505  assert(expansionApplicableToFunction(M, &
F));
 
  507  auto &Ctx = M.getContext();
 
  511  const bool FunctionIsDefinition = !
F.isDeclaration();
 
  515  ArgTypes.
push_back(ABI->vaListParameterType(M));
 
  517  FunctionType *NFTy = inlinableVariadicFunctionType(M, FTy);
 
  523  F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
 
  524  NF->
setName(
F.getName() + 
".valist");
 
  526  AttrBuilder ParamAttrs(Ctx);
 
  529  Attrs = Attrs.addParamAttributes(Ctx, NFTy->getNumParams() - 1, ParamAttrs);
 
  533  if (FunctionIsDefinition) {
 
  538      Arg.replaceAllUsesWith(NewArg);
 
  539      NewArg->setName(Arg.getName()); 
 
  546  F.getAllMetadata(MDs);
 
  547  for (
auto [KindID, 
Node] : MDs)
 
  564  Type *VaListTy = ABI->vaListType(Ctx);
 
  567  Builder.SetInsertPoint(BB);
 
  570      Builder.CreateAlloca(VaListTy, 
nullptr, 
"va_start");
 
  572  Builder.CreateLifetimeStart(VaListInstance);
 
  574  Builder.CreateIntrinsic(Intrinsic::vastart, {
DL.getAllocaPtrType(Ctx)},
 
  579  Type *ParameterType = ABI->vaListParameterType(M);
 
  580  if (ABI->vaListPassedInSSARegister())
 
  581    Args.push_back(Builder.CreateLoad(ParameterType, VaListInstance));
 
  583    Args.push_back(Builder.CreateAddrSpaceCast(VaListInstance, ParameterType));
 
  585  CallInst *Result = Builder.CreateCall(FixedArityReplacement, Args);
 
  587  Builder.CreateIntrinsic(Intrinsic::vaend, {
DL.getAllocaPtrType(Ctx)},
 
  589  Builder.CreateLifetimeEnd(VaListInstance);
 
  591  if (Result->getType()->isVoidTy())
 
  592    Builder.CreateRetVoid();
 
  594    Builder.CreateRet(Result);
 
  596  return VariadicWrapper;
 
  605  if (!expansionApplicableToFunctionCall(CB)) {
 
  615  if (FuncType != VarargFunctionType) {
 
  618    FuncType = VarargFunctionType;
 
  623  Align MaxFieldAlign(1);
 
  633  ExpandedCallFrame Frame;
 
  637  for (
unsigned I = FuncType->getNumParams(), 
E = CB->
arg_size(); 
I < 
E; ++
I) {
 
  648        DL.getTypeAllocSize(UnderlyingType).getFixedValue();
 
  651    Type *FrameFieldType = UnderlyingType;
 
  654    Value *SourceValue = ArgVal;
 
  656    VariadicABIInfo::VAArgSlotInfo SlotInfo = ABI->slotInfo(
DL, UnderlyingType);
 
  658    if (SlotInfo.Indirect) {
 
  661      Builder.SetInsertPointPastAllocas(CBF);
 
  664          Builder.CreateAlloca(UnderlyingType, 
nullptr, 
"IndirectAlloca");
 
  666      Builder.SetInsertPoint(CB);
 
  668        Builder.CreateMemCpy(CallerCopy, {}, ArgVal, {}, UnderlyingSize);
 
  670        Builder.CreateStore(ArgVal, CallerCopy);
 
  673      FrameFieldType = 
DL.getAllocaPtrType(Ctx);
 
  674      SourceValue = CallerCopy;
 
  679    Align DataAlign = SlotInfo.DataAlign;
 
  681    MaxFieldAlign = std::max(MaxFieldAlign, DataAlign);
 
  684    if (
uint64_t Rem = CurrentOffset % DataAlignV) {
 
  686      uint64_t Padding = DataAlignV - Rem;
 
  687      Frame.padding(Ctx, Padding);
 
  688      CurrentOffset += Padding;
 
  691    if (SlotInfo.Indirect) {
 
  692      Frame.store(Ctx, FrameFieldType, SourceValue);
 
  695        Frame.memcpy(Ctx, FrameFieldType, SourceValue, UnderlyingSize);
 
  697        Frame.store(Ctx, FrameFieldType, SourceValue);
 
  700    CurrentOffset += 
DL.getTypeAllocSize(FrameFieldType).getFixedValue();
 
  708    Frame.padding(Ctx, 1);
 
  719  Align AllocaAlign = MaxFieldAlign;
 
  721      StackAlign && *StackAlign > AllocaAlign)
 
  722    AllocaAlign = *StackAlign;
 
  725  Builder.SetInsertPointPastAllocas(CBF);
 
  732      new AllocaInst(VarargsTy, 
DL.getAllocaAddrSpace(), 
nullptr, AllocaAlign),
 
  738  Builder.SetInsertPoint(CB);
 
  739  Builder.CreateLifetimeStart(Alloced);
 
  740  Frame.initializeStructAlloca(
DL, Builder, Alloced);
 
  742  const unsigned NumArgs = FuncType->getNumParams();
 
  749    if (!ABI->vaListPassedInSSARegister()) {
 
  750      Type *VaListTy = ABI->vaListType(Ctx);
 
  751      Builder.SetInsertPointPastAllocas(CBF);
 
  753      VaList = Builder.CreateAlloca(VaListTy, 
nullptr, 
"va_argument");
 
  754      Builder.SetInsertPoint(CB);
 
  755      Builder.CreateLifetimeStart(VaList);
 
  757    Builder.SetInsertPoint(CB);
 
  758    Args.push_back(ABI->initializeVaList(M, Ctx, Builder, VaList, Alloced));
 
  763  if (!PAL.isEmpty()) {
 
  765    for (
unsigned ArgNo = 0; ArgNo < NumArgs; ArgNo++)
 
  766      ArgAttrs.
push_back(PAL.getParamAttrs(ArgNo));
 
  768        AttributeList::get(Ctx, PAL.getFnAttrs(), PAL.getRetAttrs(), ArgAttrs);
 
  777    Value *Dst = NF ? NF : CI->getCalledOperand();
 
  778    FunctionType *NFTy = inlinableVariadicFunctionType(M, VarargFunctionType);
 
  780    NewCB = 
CallInst::Create(NFTy, Dst, Args, OpBundles, 
"", CI->getIterator());
 
  788    CI->setTailCallKind(TCK);
 
  795    Builder.CreateLifetimeEnd(VaList);
 
  797  Builder.CreateLifetimeEnd(Alloced);
 
  805  NewCB->
copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
 
  812bool ExpandVariadics::expandVAIntrinsicCall(
IRBuilder<> &Builder,
 
  825  if (ContainingFunction->
isVarArg()) {
 
  831  bool PassedByValue = ABI->vaListPassedInSSARegister();
 
  838  Builder.SetInsertPoint(Inst);
 
  844    assert(ABI->vaCopyIsMemcpy());
 
  845    Builder.CreateStore(PassedVaList, VaStartArg);
 
  849    auto &Ctx = Builder.getContext();
 
  851    Builder.CreateIntrinsic(Intrinsic::vacopy, {
DL.getAllocaPtrType(Ctx)},
 
  852                            {VaStartArg, PassedVaList});
 
  861  assert(ABI->vaEndIsNop());
 
  866bool ExpandVariadics::expandVAIntrinsicCall(
IRBuilder<> &Builder,
 
  869  assert(ABI->vaCopyIsMemcpy());
 
  870  Builder.SetInsertPoint(Inst);
 
  872  auto &Ctx = Builder.getContext();
 
  873  Type *VaListTy = ABI->vaListType(Ctx);
 
  876  Builder.CreateMemCpy(Inst->
getDest(), {}, Inst->
getSrc(), {},
 
  877                       Builder.getInt32(
Size));
 
  883struct Amdgpu final : 
public VariadicABIInfo {
 
  885  bool enableForTarget()
 override { 
return true; }
 
  887  bool vaListPassedInSSARegister()
 override { 
return true; }
 
  893  Type *vaListParameterType(
Module &M)
 override {
 
  901    return Builder.CreateAddrSpaceCast(Buffer, vaListParameterType(M));
 
  905    return {
Align(4), 
false};
 
  909struct NVPTX final : 
public VariadicABIInfo {
 
  911  bool enableForTarget()
 override { 
return true; }
 
  913  bool vaListPassedInSSARegister()
 override { 
return true; }
 
  919  Type *vaListParameterType(
Module &M)
 override {
 
  925    return Builder.CreateAddrSpaceCast(Buffer, vaListParameterType(M));
 
  931    Align A = 
DL.getABITypeAlign(Parameter);
 
  936struct Wasm final : 
public VariadicABIInfo {
 
  938  bool enableForTarget()
 override {
 
  940    return commandLineOverride();
 
  943  bool vaListPassedInSSARegister()
 override { 
return true; }
 
  949  Type *vaListParameterType(
Module &M)
 override {
 
  961    Align A = 
DL.getABITypeAlign(Parameter);
 
  966      if (S->getNumElements() > 1) {
 
  975std::unique_ptr<VariadicABIInfo> VariadicABIInfo::create(
const Triple &
T) {
 
  976  switch (
T.getArch()) {
 
  979    return std::make_unique<Amdgpu>();
 
  983    return std::make_unique<Wasm>();
 
  988    return std::make_unique<NVPTX>();
 
  998char ExpandVariadics::ID = 0;
 
 1004  return new ExpandVariadics(M);
 
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file defines the SmallVector class.
an instruction to allocate memory on the stack
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
This class represents an incoming formal argument to a Function.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
Type * getParamByRefType(unsigned ArgNo) const
Extract the byref type for a call or parameter.
CallingConv::ID getCallingConv() const
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
LLVM_ABI void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
A parsed version of the target data layout string in and methods for querying it.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
ExpandVariadicsPass(ExpandVariadicsMode Mode)
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void splice(Function::iterator ToIt, Function *FromF)
Transfer all blocks from FromF to this function at ToIt.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
AttributeList getAttributes() const
Return the attribute list for this Function.
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
LLVM_ABI void setComdat(Comdat *C)
const Comdat * getComdat() const
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
VisibilityTypes getVisibility() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
void setLinkage(LinkageTypes LT)
@ DefaultVisibility
The GV is visible.
void setVisibility(VisibilityTypes V)
@ InternalLinkage
Rename collisions when linking (static functions).
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const DebugLoc & getStableDebugLoc() const
Fetch the debug location for this node, unless this is a debug intrinsic, in which case fetch the deb...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
This is an important class for using LLVM in a threaded context.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Class to represent struct types.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
This represents the llvm.va_copy intrinsic.
This represents the llvm.va_end intrinsic.
This represents the llvm.va_start intrinsic.
Value * getArgList() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
ModulePass * createExpandVariadicsPass(ExpandVariadicsMode)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.