================ @@ -0,0 +1,1056 @@ +//===-- ExpandVariadicsPass.cpp --------------------------------*- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a varidic function into a va_list +// and fix up the call sites. This is completely effective if the calling +// convention can declare that to be the right thing, e.g. on GPUs or where +// the application is wholly statically linked. In the usual case, it will +// replace known calls to known variadic functions with calls that are amenable +// to inlining and other optimisations. +// +// The target-dependent parts are in class VariadicABIInfo. Enabling a new +// target means adding a case to VariadicABIInfo::create() along with tests. +// This will be especially simple if the va_list representation is a char*. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. The target specific +// part is packing arguments into a contiguous buffer that the clang expansion +// of va_arg will do the right thing with. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" + +#include <cstdio> + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +cl::opt<ExpandVariadicsMode> ExpandVariadicsModeOption( + DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), + cl::init(ExpandVariadicsMode::unspecified), + cl::values(clEnumValN(ExpandVariadicsMode::unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::lowering, "lowering", + "Change variadic calling convention"))); + +namespace { + +// Module implements getFunction() which returns nullptr on missing declaration +// and getOrInsertFunction which creates one when absent. Intrinsics.h +// implements getDeclaration which creates one when missing. This should be +// changed to be consistent with Module()'s naming. Implementing as a local +// function here in the meantime to decouple from that process. +Function *getPreexistingDeclaration(Module *M, Intrinsic::ID id, + ArrayRef<Type *> Tys = std::nullopt) { ---------------- arsenm wrote:
```suggestion ArrayRef<Type *> Tys = {}) { ``` https://github.com/llvm/llvm-project/pull/89007 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits