namespace llvm {
-template <typename NodeTy> 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<Argument> {
+class Argument : public Value {
virtual void anchor();
Function *Parent;
unsigned ArgNo;
- friend class SymbolTableListTraits<Argument>;
+ 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; }
/// 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
class Function : public GlobalObject, public ilist_node<Function> {
public:
- typedef SymbolTableList<Argument> ArgumentListType;
typedef SymbolTableList<BasicBlock> 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<ValueSymbolTable>
SymTab; ///< Symbol table of args/instructions
AttributeSet AttributeSets; ///< Parameter attributes
void BuildLazyArguments() const;
+ 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.
/// 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.
///
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<arg_iterator> args() {
/// @}
- 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.
}
LLVMValueRef LLVMGetParam(LLVMValueRef FnRef, unsigned index) {
- Function::arg_iterator AI = unwrap<Function>(FnRef)->arg_begin();
- while (index --> 0)
- AI++;
- return wrap(&*AI);
+ Function *Fn = unwrap<Function>(FnRef);
+ return wrap(&Fn->arg_begin()[index]);
}
LLVMValueRef LLVMGetParamParent(LLVMValueRef V) {
LLVMValueRef LLVMGetNextParam(LLVMValueRef Arg) {
Argument *A = unwrap<Argument>(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<Argument>(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) {
// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file...
-template class llvm::SymbolTableListTraits<Argument>;
template class llvm::SymbolTableListTraits<BasicBlock>;
//===----------------------------------------------------------------------===//
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);
}
Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name,
Module *ParentModule)
: GlobalObject(Ty, Value::FunctionVal,
- OperandTraits<Function>::op_begin(this), 0, Linkage, name) {
+ OperandTraits<Function>::op_begin(this), 0, Linkage, name),
+ Arguments(nullptr), NumArgs(Ty->getNumParams()) {
assert(FunctionType::isValidReturnType(getReturnType()) &&
"invalid return type");
setGlobalObjectSubClassData(0);
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();
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 = std::allocator<Argument>().allocate(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<Function *>(this), i);
+ }
}
// Clear the lazy arguments bit.
unsigned SDC = getSubclassDataFromValue();
const_cast<Function*>(this)->setValueSubclassData(SDC &= ~(1<<0));
+ assert(!hasLazyArguments());
+}
+
+static MutableArrayRef<Argument> makeArgArray(Argument *Args, size_t Count) {
+ return MutableArrayRef<Argument>(Args, Count);
+}
+
+void Function::clearArguments() {
+ for (Argument &A : makeArgArray(Arguments, NumArgs)) {
+ A.setName("");
+ A.~Argument();
+ }
+ std::allocator<Argument>().deallocate(Arguments, NumArgs);
+ Arguments = nullptr;
}
void Function::stealArgumentListFrom(Function &Src) {
// Drop the current arguments, if any, and set the lazy argument bit.
if (!hasLazyArguments()) {
- assert(llvm::all_of(ArgumentList,
+ assert(llvm::all_of(makeArgArray(Arguments, NumArgs),
[](const Argument &A) { return A.use_empty(); }) &&
"Expected arguments to be unused in declaration");
- ArgumentList.clear();
+ clearArguments();
setValueSubclassData(getSubclassDataFromValue() | (1 << 0));
}
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 : makeArgArray(Arguments, NumArgs)) {
+ // 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));
}