#define BITCODE_READER_H
#include "llvm/ModuleProvider.h"
-#include "llvm/ParameterAttributes.h"
+#include "llvm/Attributes.h"
#include "llvm/Type.h"
-#include "llvm/User.h"
+#include "llvm/OperandTraits.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/ADT/DenseMap.h"
namespace llvm {
class MemoryBuffer;
+//===----------------------------------------------------------------------===//
+// BitcodeReaderValueList Class
+//===----------------------------------------------------------------------===//
+
class BitcodeReaderValueList : public User {
- std::vector<Use> Uses;
+ unsigned Capacity;
+
+ /// ResolveConstants - As we resolve forward-referenced constants, we add
+ /// information about them to this vector. This allows us to resolve them in
+ /// bulk instead of resolving each reference at a time. See the code in
+ /// ResolveConstantForwardRefs for more information about this.
+ ///
+ /// The key of this vector is the placeholder constant, the value is the slot
+ /// number that holds the resolved value.
+ typedef std::vector<std::pair<Constant*, unsigned> > ResolveConstantsTy;
+ ResolveConstantsTy ResolveConstants;
public:
- BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0) {}
-
+ BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0)
+ , Capacity(0) {}
+ ~BitcodeReaderValueList() {
+ assert(ResolveConstants.empty() && "Constants not resolved?");
+ }
+
+ /// Provide fast operand accessors
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
// vector compatibility methods
unsigned size() const { return getNumOperands(); }
+ void resize(unsigned);
void push_back(Value *V) {
- Uses.push_back(Use(V, this));
- OperandList = &Uses[0];
- ++NumOperands;
+ unsigned OldOps(NumOperands), NewOps(NumOperands + 1);
+ resize(NewOps);
+ NumOperands = NewOps;
+ OperandList[OldOps] = V;
}
void clear() {
- std::vector<Use>().swap(Uses);
+ assert(ResolveConstants.empty() && "Constants not resolved?");
+ if (OperandList) dropHungoffUses(OperandList);
+ Capacity = 0;
}
Value *operator[](unsigned i) const { return getOperand(i); }
- Value *back() const { return Uses.back(); }
- void pop_back() { Uses.pop_back(); --NumOperands; }
+ Value *back() const { return getOperand(size() - 1); }
+ void pop_back() { setOperand(size() - 1, 0); --NumOperands; }
bool empty() const { return NumOperands == 0; }
void shrinkTo(unsigned N) {
assert(N <= NumOperands && "Invalid shrinkTo request!");
- Uses.resize(N);
- NumOperands = N;
+ while (NumOperands > N)
+ pop_back();
}
virtual void print(std::ostream&) const {}
if (Idx == size()) {
push_back(V);
} else if (Value *OldV = getOperand(Idx)) {
- // If there was a forward reference to this value, replace it.
- setOperand(Idx, V);
- OldV->replaceAllUsesWith(V);
- delete OldV;
+ // Handle constants and non-constants (e.g. instrs) differently for
+ // efficiency.
+ if (Constant *PHC = dyn_cast<Constant>(OldV)) {
+ ResolveConstants.push_back(std::make_pair(PHC, Idx));
+ setOperand(Idx, V);
+ } else {
+ // If there was a forward reference to this value, replace it.
+ setOperand(Idx, V);
+ OldV->replaceAllUsesWith(V);
+ delete OldV;
+ }
} else {
initVal(Idx, V);
}
}
+ /// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+ /// resolves any forward references.
+ void ResolveConstantForwardRefs();
+
private:
void initVal(unsigned Idx, Value *V) {
- assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
- Uses[Idx].init(V, this);
+ if (Idx >= size()) {
+ // Insert a bunch of null values.
+ resize(Idx * 2 + 1);
+ }
+ assert(getOperand(Idx) == 0 && "Cannot init an already init'd Use!");
+ OperandList[Idx] = V;
}
};
-
+
+template <>
+struct OperandTraits<BitcodeReaderValueList>
+ : HungoffOperandTraits</*16 FIXME*/> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitcodeReaderValueList, Value)
class BitcodeReader : public ModuleProvider {
MemoryBuffer *Buffer;
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
- /// ParamAttrs - The set of parameter attributes by index. Index zero in the
+ /// Attributes - The set of parameter attributes by index. Index zero in the
/// file is for null, and is thus not represented here. As such all indices
/// are off by one.
- std::vector<PAListPtr> ParamAttrs;
+ std::vector<AttrListPtr> Attributes;
/// FunctionBBs - While parsing a function body, this is a list of the basic
/// blocks for the function.
/// stream) and what linkage the original function had.
DenseMap<Function*, std::pair<uint64_t, unsigned> > DeferredFunctionInfo;
public:
- BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) {
+ explicit BitcodeReader(MemoryBuffer *buffer)
+ : Buffer(buffer), ErrorString(0) {
HasReversedFunctionsWithBodies = false;
}
~BitcodeReader() {
if (ID >= FunctionBBs.size()) return 0; // Invalid ID
return FunctionBBs[ID];
}
- PAListPtr getParamAttrs(unsigned i) const {
- if (i-1 < ParamAttrs.size())
- return ParamAttrs[i-1];
- return PAListPtr();
+ AttrListPtr getAttributes(unsigned i) const {
+ if (i-1 < Attributes.size())
+ return Attributes[i-1];
+ return AttrListPtr();
}
/// getValueTypePair - Read a value/type pair out of the specified record from
bool ParseModule(const std::string &ModuleID);
- bool ParseParamAttrBlock();
+ bool ParseAttributeBlock();
bool ParseTypeTable();
bool ParseTypeSymbolTable();
bool ParseValueSymbolTable();