//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
-#include "llvm/ParameterAttributes.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/LeakDetector.h"
-#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/StringPool.h"
#include "SymbolTableListTraitsImpl.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
LeakDetector::removeGarbageObject(this);
}
+/// getArgNo - 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 Argument::getArgNo() const {
+ const Function *F = getParent();
+ assert(F && "Argument is not in a function");
+
+ Function::const_arg_iterator AI = F->arg_begin();
+ unsigned ArgIdx = 0;
+ for (; &*AI != this; ++AI)
+ ++ArgIdx;
+
+ return ArgIdx;
+}
+
+/// hasByValAttr - Return true if this argument has the byval attribute on it
+/// in its containing function.
+bool Argument::hasByValAttr() const {
+ if (!isa<PointerType>(getType())) return false;
+ return getParent()->paramHasAttr(getArgNo()+1, ParamAttr::ByVal);
+}
+
+/// hasNoAliasAttr - Return true if this argument has the noalias attribute on
+/// it in its containing function.
+bool Argument::hasNoAliasAttr() const {
+ if (!isa<PointerType>(getType())) return false;
+ return getParent()->paramHasAttr(getArgNo()+1, ParamAttr::NoAlias);
+}
+
+/// hasSRetAttr - Return true if this argument has the sret attribute on
+/// it in its containing function.
+bool Argument::hasStructRetAttr() const {
+ if (!isa<PointerType>(getType())) return false;
+ if (this != getParent()->arg_begin()) return false; // StructRet param must be first param
+ return getParent()->paramHasAttr(1, ParamAttr::StructRet);
+}
+
+
+
+
//===----------------------------------------------------------------------===//
-// ParamAttrsList Implementation
+// Helper Methods in Function
//===----------------------------------------------------------------------===//
-uint16_t
-ParamAttrsList::getParamAttrs(uint16_t Index) const {
- unsigned limit = attrs.size();
- for (unsigned i = 0; i < limit; ++i)
- if (attrs[i].index == Index)
- return attrs[i].attrs;
- return ParamAttr::None;
-}
-
-
-std::string
-ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
- std::string Result;
- if (Attrs & ParamAttr::ZExt)
- Result += "zeroext ";
- if (Attrs & ParamAttr::SExt)
- Result += "signext ";
- if (Attrs & ParamAttr::NoReturn)
- Result += "noreturn ";
- if (Attrs & ParamAttr::NoUnwind)
- Result += "nounwind ";
- if (Attrs & ParamAttr::InReg)
- Result += "inreg ";
- if (Attrs & ParamAttr::NoAlias)
- Result += "noalias ";
- if (Attrs & ParamAttr::StructRet)
- Result += "sret ";
- if (Attrs & ParamAttr::ByVal)
- Result += "byval ";
- if (Attrs & ParamAttr::Nest)
- Result += "nest ";
- return Result;
+const FunctionType *Function::getFunctionType() const {
+ return cast<FunctionType>(getType()->getElementType());
}
-void
-ParamAttrsList::Profile(FoldingSetNodeID &ID) const {
- for (unsigned i = 0; i < attrs.size(); ++i) {
- unsigned val = attrs[i].attrs << 16 | attrs[i].index;
- ID.AddInteger(val);
- }
+bool Function::isVarArg() const {
+ return getFunctionType()->isVarArg();
}
-static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
+const Type *Function::getReturnType() const {
+ return getFunctionType()->getReturnType();
+}
-ParamAttrsList *
-ParamAttrsList::get(const ParamAttrsVector &attrVec) {
- assert(!attrVec.empty() && "Illegal to create empty ParamAttrsList");
- ParamAttrsList key(attrVec);
- FoldingSetNodeID ID;
- key.Profile(ID);
- void *InsertPos;
- ParamAttrsList* PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
- if (!PAL) {
- PAL = new ParamAttrsList(attrVec);
- ParamAttrsLists->InsertNode(PAL, InsertPos);
- }
- return PAL;
+void Function::removeFromParent() {
+ getParent()->getFunctionList().remove(this);
}
-ParamAttrsList::~ParamAttrsList() {
- ParamAttrsLists->RemoveNode(this);
+void Function::eraseFromParent() {
+ getParent()->getFunctionList().erase(this);
}
//===----------------------------------------------------------------------===//
Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
const std::string &name, Module *ParentModule)
- : GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) {
- ParamAttrs = 0;
+ : GlobalValue(PointerType::getUnqual(Ty),
+ Value::FunctionVal, 0, 0, Linkage, name) {
SymTab = new ValueSymbolTable();
- assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy)
+ assert((getReturnType()->isFirstClassType() ||getReturnType() == Type::VoidTy
+ || isa<StructType>(getReturnType()))
&& "LLVM functions cannot return aggregate values!");
// If the function has arguments, mark them as lazily built.
ArgumentList.clear();
delete SymTab;
- // Drop our reference to the parameter attributes, if any.
- if (ParamAttrs)
- ParamAttrs->dropRef();
+ // Remove the function from the on-the-side collector table.
+ clearCollector();
}
void Function::BuildLazyArguments() const {
LeakDetector::removeGarbageObject(this);
}
-void Function::setParamAttrs(ParamAttrsList *attrs) {
- if (ParamAttrs)
- ParamAttrs->dropRef();
-
- if (attrs)
- attrs->addRef();
-
- ParamAttrs = attrs;
-}
-
-const FunctionType *Function::getFunctionType() const {
- return cast<FunctionType>(getType()->getElementType());
-}
-
-bool Function::isVarArg() const {
- return getFunctionType()->isVarArg();
-}
-
-const Type *Function::getReturnType() const {
- return getFunctionType()->getReturnType();
-}
-
-void Function::removeFromParent() {
- getParent()->getFunctionList().remove(this);
-}
-
-void Function::eraseFromParent() {
- getParent()->getFunctionList().erase(this);
-}
-
// dropAllReferences() - This function causes all the subinstructions to "let
// go" of all references that they are maintaining. This allows one to
// 'delete' a whole class at a time, even though there may be circular
BasicBlocks.clear(); // Delete all basic blocks...
}
+// Maintain the collector name for each function in an on-the-side table. This
+// saves allocating an additional word in Function for programs which do not use
+// GC (i.e., most programs) at the cost of increased overhead for clients which
+// do use GC.
+static DenseMap<const Function*,PooledStringPtr> *CollectorNames;
+static StringPool *CollectorNamePool;
+
+bool Function::hasCollector() const {
+ return CollectorNames && CollectorNames->count(this);
+}
+
+const char *Function::getCollector() const {
+ assert(hasCollector() && "Function has no collector");
+ return *(*CollectorNames)[this];
+}
+
+void Function::setCollector(const char *Str) {
+ if (!CollectorNamePool)
+ CollectorNamePool = new StringPool();
+ if (!CollectorNames)
+ CollectorNames = new DenseMap<const Function*,PooledStringPtr>();
+ (*CollectorNames)[this] = CollectorNamePool->intern(Str);
+}
+
+void Function::clearCollector() {
+ if (CollectorNames) {
+ CollectorNames->erase(this);
+ if (CollectorNames->empty()) {
+ delete CollectorNames;
+ CollectorNames = 0;
+ if (CollectorNamePool->empty()) {
+ delete CollectorNamePool;
+ CollectorNamePool = 0;
+ }
+ }
+ }
+}
+
/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
/// intrinsic, or if the pointer is null. This value is always defined to be
return FunctionType::get(ResultTy, ArgTys, IsVarArg);
}
+PAListPtr Intrinsic::getParamAttrs(ID id) {
+ ParameterAttributes Attr = ParamAttr::None;
+
+#define GET_INTRINSIC_ATTRIBUTES
+#include "llvm/Intrinsics.gen"
+#undef GET_INTRINSIC_ATTRIBUTES
+
+ // Intrinsics cannot throw exceptions.
+ Attr |= ParamAttr::NoUnwind;
+
+ ParamAttrsWithIndex PAWI = ParamAttrsWithIndex::get(0, Attr);
+ return PAListPtr::get(&PAWI, 1);
+}
+
Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
unsigned numTys) {
-// There can never be multiple globals with the same name of different types,
-// because intrinsics must be a specific type.
- return cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
- getType(id, Tys, numTys)));
+ // There can never be multiple globals with the same name of different types,
+ // because intrinsics must be a specific type.
+ Function *F =
+ cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
+ getType(id, Tys, numTys)));
+ F->setParamAttrs(getParamAttrs(id));
+ return F;
}
Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {