summaryrefslogtreecommitdiff
path: root/lib/Bytecode
diff options
context:
space:
mode:
authorVikram S. Adve <vadve@cs.uiuc.edu>2002-07-14 23:04:18 +0000
committerVikram S. Adve <vadve@cs.uiuc.edu>2002-07-14 23:04:18 +0000
commitc1e4a813a2209fc7e8d0bb9359945ea8edc16180 (patch)
tree47b75852786b15d2d616930eb9c26c6722883082 /lib/Bytecode
parentd3f7eb0aa4a3a198eb9c33d5ae086f6aff774956 (diff)
downloadllvm-c1e4a813a2209fc7e8d0bb9359945ea8edc16180.tar.gz
llvm-c1e4a813a2209fc7e8d0bb9359945ea8edc16180.tar.bz2
llvm-c1e4a813a2209fc7e8d0bb9359945ea8edc16180.tar.xz
Add support for reading ConstantExpr nodes.
Add class ConstantFwdRefs to resolve forward references to constants and to globals (unified old code for globals into this). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2895 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Bytecode')
-rw-r--r--lib/Bytecode/Reader/Reader.cpp143
1 files changed, 111 insertions, 32 deletions
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index f84ad565ca..c03191c9d9 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -218,42 +218,119 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf,
return false;
}
-// DeclareNewGlobalValue - Patch up forward references to global values in the
-// form of ConstantPointerRef.
-//
-void BytecodeParser::DeclareNewGlobalValue(GlobalValue *GV, unsigned Slot) {
- // Check to see if there is a forward reference to this global variable...
- // if there is, eliminate it and patch the reference to use the new def'n.
- GlobalRefsType::iterator I = GlobalRefs.find(make_pair(GV->getType(), Slot));
-
+Value*
+ConstantFwdRefs::find(const Type* Ty, unsigned Slot) {
+ GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot));
if (I != GlobalRefs.end()) {
- GlobalVariable *OldGV = I->second; // Get the placeholder...
- BCR_TRACE(3, "Mutating CPPR Forward Ref!\n");
-
- // Loop over all of the uses of the GlobalValue. The only thing they are
- // allowed to be at this point is ConstantPointerRef's.
- assert(OldGV->use_size() == 1 && "Only one reference should exist!");
- while (!OldGV->use_empty()) {
- User *U = OldGV->use_back(); // Must be a ConstantPointerRef...
- ConstantPointerRef *CPPR = cast<ConstantPointerRef>(U);
- assert(CPPR->getValue() == OldGV && "Something isn't happy");
-
- BCR_TRACE(4, "Mutating Forward Ref!\n");
+ return I->second;
+ } else {
+ return failure<Value*>(0);
+ }
+}
+
+void
+ConstantFwdRefs::insert(const Type* Ty, unsigned Slot, Value* V) {
+ // Keep track of the fact that we have a forward ref to recycle it
+ const pair<GlobalRefsType::iterator, bool>& result =
+ GlobalRefs.insert(make_pair(make_pair(Ty, Slot), V));
+ assert(result.second == true && "Entry already exists for this slot?");
+}
+
+void
+ConstantFwdRefs::erase(const Type* Ty, unsigned Slot) {
+ GlobalRefsType::iterator I = GlobalRefs.find(make_pair(Ty, Slot));
+ if (I != GlobalRefs.end())
+ GlobalRefs.erase(I);
+}
+
+// GetFwdRefToConstant - Get a forward reference to a constant value.
+// Create a unique one if it does not exist already.
+//
+Constant*
+ConstantFwdRefs::GetFwdRefToConstant(const Type* Ty, unsigned Slot) {
+
+ Constant* C = cast_or_null<Constant>(find(Ty, Slot));
+
+ if (C) {
+ BCR_TRACE(5, "Previous forward ref found!\n");
+ } else {
+ // Create a placeholder for the constant reference and
+ // keep track of the fact that we have a forward ref to recycle it
+ BCR_TRACE(5, "Creating new forward ref to a constant!\n");
+ C = new ConstPHolder(Ty, Slot);
+ insert(Ty, Slot, C);
+ }
+
+ return C;
+}
+
+
+// GetFwdRefToGlobal - Get a forward reference to a global value.
+// Create a unique one if it does not exist already.
+//
+GlobalValue*
+ConstantFwdRefs::GetFwdRefToGlobal(const PointerType* PT, unsigned Slot) {
+
+ GlobalValue* GV = cast_or_null<GlobalValue>(find(PT, Slot));
+
+ if (GV) {
+ BCR_TRACE(5, "Previous forward ref found!\n");
+ } else {
+ BCR_TRACE(5, "Creating new forward ref to a global variable!\n");
+
+ // Create a placeholder for the global variable reference...
+ GlobalVariable *GVar =
+ new GlobalVariable(PT->getElementType(), false, true);
+
+ // Keep track of the fact that we have a forward ref to recycle it
+ insert(PT, Slot, GVar);
+
+ // Must temporarily push this value into the module table...
+ TheModule->getGlobalList().push_back(GVar);
+ GV = GVar;
+ }
+
+ return GV;
+}
+
+void
+ConstantFwdRefs::ResolveRefsToValue(Value* NewV, unsigned Slot) {
+ if (Value* vph = find(NewV->getType(), Slot)) {
+ BCR_TRACE(3, "Mutating forward refs!\n");
+
+ // Loop over all of the uses of the Value. What they are depends
+ // on what NewV is. Replacing a use of the old reference takes the
+ // use off the use list, so loop with !use_empty(), not the use_iterator.
+ while (!vph->use_empty()) {
+ Constant *C = cast<Constant>(vph->use_back());
+ unsigned numReplaced = C->mutateReferences(vph, NewV);
+ assert(numReplaced > 0 && "Supposed user wasn't really a user?");
- // Change the const pool reference to point to the real global variable
- // now. This should drop a use from the OldGV.
- CPPR->mutateReference(GV);
+ if (GlobalValue* GVal = dyn_cast<GlobalValue>(NewV)) {
+ // Remove the placeholder GlobalValue from the module...
+ GVal->getParent()->getGlobalList().remove(cast<GlobalVariable>(vph));
+ }
}
-
- // Remove GV from the module...
- GV->getParent()->getGlobalList().remove(OldGV);
- delete OldGV; // Delete the old placeholder
-
- // Remove the map entry for the global now that it has been created...
- GlobalRefs.erase(I);
+
+ delete vph; // Delete the old placeholder
+ erase(NewV->getType(), Slot); // Remove the map entry for it
}
}
+// resolveRefsToGlobal - Patch up forward references to global values in the
+// form of ConstantPointerRef.
+//
+void BytecodeParser::resolveRefsToGlobal(GlobalValue *GV, unsigned Slot) {
+ fwdRefs.ResolveRefsToValue(GV, Slot);
+}
+
+// resolveRefsToConstant - Patch up forward references to constants
+//
+void BytecodeParser::resolveRefsToConstant(Constant *C, unsigned Slot) {
+ fwdRefs.ResolveRefsToValue(C, Slot);
+}
+
+
bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
Module *C) {
// Clear out the local values table...
@@ -369,7 +446,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf,
if (M->isExternal())
M->getArgumentList().clear();
- DeclareNewGlobalValue(M, MethSlot);
+ resolveRefsToGlobal(M, MethSlot);
return false;
}
@@ -417,7 +494,7 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
Mod->getGlobalList().push_back(GV);
- DeclareNewGlobalValue(GV, unsigned(DestSlot));
+ resolveRefsToGlobal(GV, unsigned(DestSlot));
BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription()
<< " into slot #" << DestSlot << "\n");
@@ -492,6 +569,8 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf,
BCR_TRACE(1, "FirstDerivedTyID = " << FirstDerivedTyID << "\n");
TheModule = C = new Module();
+ fwdRefs.VisitingModule(TheModule);
+
while (Buf < EndBuf) {
const uchar *OldBuf = Buf;
if (readBlock(Buf, EndBuf, Type, Size)) { delete C; return failure(true); }