Index: include/llvm/IR/Argument.h =================================================================== --- include/llvm/IR/Argument.h +++ include/llvm/IR/Argument.h @@ -21,25 +21,24 @@ namespace llvm { -template class SymbolTableListTraits; - /// This class represents an incoming formal argument to a Function. A formal /// argument, since it is ``formal'', does not contain an actual value but /// instead represents the type, argument number, and attributes of an argument /// for a specific function. When used in the body of said function, the /// argument of course represents the value of the actual argument that the /// function was called with. -class Argument : public Value, public ilist_node { +class Argument : public Value { virtual void anchor(); Function *Parent; unsigned ArgNo; - friend class SymbolTableListTraits; + friend class Function; void setParent(Function *parent); public: /// Argument constructor. - explicit Argument(Type *Ty, const Twine &Name = "", unsigned ArgNo = 0); + explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr, + unsigned ArgNo = 0); inline const Function *getParent() const { return Parent; } inline Function *getParent() { return Parent; } @@ -47,7 +46,10 @@ /// Return the index of this formal argument in its containing function. /// /// For example in "void foo(int a, float b)" a is 0 and b is 1. - unsigned getArgNo() const { return ArgNo; } + unsigned getArgNo() const { + assert(Parent && "can't get number of unparented arg"); + return ArgNo; + } /// Return true if this argument has the nonnull attribute. Also returns true /// if at least one byte is known to be dereferenceable and the pointer is in Index: include/llvm/IR/Function.h =================================================================== --- include/llvm/IR/Function.h +++ include/llvm/IR/Function.h @@ -48,20 +48,21 @@ class Function : public GlobalObject, public ilist_node { public: - typedef SymbolTableList ArgumentListType; + typedef OwningArrayRef ArgumentListType; typedef SymbolTableList BasicBlockListType; // BasicBlock iterators... typedef BasicBlockListType::iterator iterator; typedef BasicBlockListType::const_iterator const_iterator; - typedef ArgumentListType::iterator arg_iterator; - typedef ArgumentListType::const_iterator const_arg_iterator; + typedef Argument *arg_iterator; + typedef const Argument *const_arg_iterator; private: // Important things that make up a function! BasicBlockListType BasicBlocks; ///< The basic blocks - mutable ArgumentListType ArgumentList; ///< The formal arguments + mutable Argument *Arguments; ///< The formal arguments + size_t NumArgs; std::unique_ptr SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes @@ -103,6 +104,13 @@ void BuildLazyArguments() const; + /// Internal wrapper for conveniently iterating the argument list. + MutableArrayRef getArgList() { + return MutableArrayRef(Arguments, NumArgs); + } + + void clearArguments(); + /// Function ctor - If the (optional) Module argument is specified, the /// function is automatically inserted into the end of the function list for /// the module. @@ -509,10 +517,6 @@ /// Requires that this has no function body. void stealArgumentListFrom(Function &Src); - static ArgumentListType Function::*getSublistAccess(Argument*) { - return &Function::ArgumentList; - } - /// Get the underlying elements of the Function... the basic block list is /// empty for external functions. /// @@ -556,20 +560,20 @@ arg_iterator arg_begin() { CheckLazyArguments(); - return ArgumentList.begin(); + return Arguments; } const_arg_iterator arg_begin() const { CheckLazyArguments(); - return ArgumentList.begin(); + return Arguments; } arg_iterator arg_end() { CheckLazyArguments(); - return ArgumentList.end(); + return Arguments + NumArgs; } const_arg_iterator arg_end() const { CheckLazyArguments(); - return ArgumentList.end(); + return Arguments + NumArgs; } iterator_range args() { @@ -581,7 +585,7 @@ /// @} - size_t arg_size() const { return getFunctionType()->getNumParams(); } + size_t arg_size() const { return NumArgs; } bool arg_empty() const { return arg_size() == 0; } /// \brief Check whether this function has a personality function. Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -1913,10 +1913,8 @@ } LLVMValueRef LLVMGetParam(LLVMValueRef FnRef, unsigned index) { - Function::arg_iterator AI = unwrap(FnRef)->arg_begin(); - while (index --> 0) - AI++; - return wrap(&*AI); + Function *Fn = unwrap(FnRef); + return wrap(&Fn->arg_begin()[index]); } LLVMValueRef LLVMGetParamParent(LLVMValueRef V) { @@ -1941,18 +1939,17 @@ LLVMValueRef LLVMGetNextParam(LLVMValueRef Arg) { Argument *A = unwrap(Arg); - Function::arg_iterator I(A); - if (++I == A->getParent()->arg_end()) + Function *Fn = A->getParent(); + if (A->getArgNo() + 1 >= Fn->arg_size()) return nullptr; - return wrap(&*I); + return wrap(&Fn->arg_begin()[A->getArgNo() + 1]); } LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg) { Argument *A = unwrap(Arg); - Function::arg_iterator I(A); - if (I == A->getParent()->arg_begin()) + if (A->getArgNo() == 0) return nullptr; - return wrap(&*--I); + return wrap(&A->getParent()->arg_begin()[A->getArgNo() - 1]); } void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align) { Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -30,7 +30,6 @@ // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... -template class llvm::SymbolTableListTraits; template class llvm::SymbolTableListTraits; //===----------------------------------------------------------------------===// @@ -39,8 +38,8 @@ void Argument::anchor() { } -Argument::Argument(Type *Ty, const Twine &Name, unsigned ArgNo) - : Value(Ty, Value::ArgumentVal), Parent(nullptr), ArgNo(ArgNo) { +Argument::Argument(Type *Ty, const Twine &Name, Function *Par, unsigned ArgNo) + : Value(Ty, Value::ArgumentVal), Parent(Par), ArgNo(ArgNo) { setName(Name); } @@ -188,7 +187,8 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name, Module *ParentModule) : GlobalObject(Ty, Value::FunctionVal, - OperandTraits::op_begin(this), 0, Linkage, name) { + OperandTraits::op_begin(this), 0, Linkage, name), + Arguments(nullptr), NumArgs(Ty->getNumParams()) { assert(FunctionType::isValidReturnType(getReturnType()) && "invalid return type"); setGlobalObjectSubClassData(0); @@ -216,7 +216,8 @@ dropAllReferences(); // After this it is safe to delete instructions. // Delete all of the method arguments and unlink from symbol table... - ArgumentList.clear(); + if (Arguments) + clearArguments(); // Remove the function from the on-the-side GC table. clearGC(); @@ -224,17 +225,30 @@ void Function::BuildLazyArguments() const { // Create the arguments vector, all arguments start out unnamed. - FunctionType *FT = getFunctionType(); - for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { - assert(!FT->getParamType(i)->isVoidTy() && - "Cannot have void typed arguments!"); - ArgumentList.push_back( - new Argument(FT->getParamType(i), "", i)); + auto *FT = getFunctionType(); + if (NumArgs > 0) { + Arguments = + reinterpret_cast(malloc(sizeof(Argument) * NumArgs)); + for (unsigned i = 0, e = NumArgs; i != e; ++i) { + Type *ArgTy = FT->getParamType(i); + assert(!ArgTy->isVoidTy() && "Cannot have void typed arguments!"); + new (Arguments + i) Argument(ArgTy, "", const_cast(this), i); + } } // Clear the lazy arguments bit. unsigned SDC = getSubclassDataFromValue(); const_cast(this)->setValueSubclassData(SDC &= ~(1<<0)); + assert(!hasLazyArguments()); +} + +void Function::clearArguments() { + for (Argument &A : getArgList()) { + A.setName(""); + A.~Argument(); + } + free(Arguments); + Arguments = nullptr; } void Function::stealArgumentListFrom(Function &Src) { @@ -242,10 +256,10 @@ // Drop the current arguments, if any, and set the lazy argument bit. if (!hasLazyArguments()) { - assert(llvm::all_of(ArgumentList, + assert(llvm::all_of(getArgList(), [](const Argument &A) { return A.use_empty(); }) && "Expected arguments to be unused in declaration"); - ArgumentList.clear(); + clearArguments(); setValueSubclassData(getSubclassDataFromValue() | (1 << 0)); } @@ -254,8 +268,23 @@ return; // Steal arguments from Src, and fix the lazy argument bits. - ArgumentList.splice(ArgumentList.end(), Src.ArgumentList); + assert(arg_size() == Src.arg_size()); + Arguments = Src.Arguments; + Src.Arguments = nullptr; + for (Argument &A : getArgList()) { + // FIXME: This does the work of transferNodesFromList inefficiently. + SmallString<128> Name; + if (A.hasName()) + Name = A.getName(); + if (!Name.empty()) + A.setName(""); + A.setParent(this); + if (!Name.empty()) + A.setName(Name); + } + setValueSubclassData(getSubclassDataFromValue() & ~(1 << 0)); + assert(!hasLazyArguments()); Src.setValueSubclassData(Src.getSubclassDataFromValue() | (1 << 0)); }