From c668b7c3ae26bec3cd829495508370bdd8849330 Mon Sep 17 00:00:00 2001 From: "Vikram S. Adve" Date: Sun, 14 Jul 2002 23:05:09 +0000 Subject: [PATCH] Add support for reading ConstantExpr nodes. Add class ConstantFwdRefs to resolve forward references to constants and to globals. (Hmm... this class could be renamed I guess.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2896 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bytecode/Reader/ConstantReader.cpp | 84 ++++++++++++++++++-------- lib/Bytecode/Reader/ReaderInternals.h | 66 ++++++++++++++++---- 2 files changed, 112 insertions(+), 38 deletions(-) diff --git a/lib/Bytecode/Reader/ConstantReader.cpp b/lib/Bytecode/Reader/ConstantReader.cpp index 7e00cd23431..2fa392e5db5 100644 --- a/lib/Bytecode/Reader/ConstantReader.cpp +++ b/lib/Bytecode/Reader/ConstantReader.cpp @@ -179,6 +179,54 @@ bool BytecodeParser::parseTypeConstants(const uchar *&Buf, const uchar *EndBuf, bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf, const Type *Ty, Constant *&V) { + + // We must check for a ConstantExpr before switching by type because + // a ConstantExpr can be of any type, and has no explicit value. + // + unsigned isExprNumArgs; // 0 if not expr; numArgs if is expr + if (read_vbr(Buf, EndBuf, isExprNumArgs)) return failure(true); + if (isExprNumArgs) { + unsigned opCode; + vector argVec; + argVec.reserve(isExprNumArgs); + + if (read_vbr(Buf, EndBuf, opCode)) return failure(true); + + // Read the slot number and types of each of the arguments + for (unsigned i=0; i < isExprNumArgs; ++i) { + unsigned argValSlot, argTypeSlot; + if (read_vbr(Buf, EndBuf, argValSlot)) return failure(true); + if (read_vbr(Buf, EndBuf, argTypeSlot)) return failure(true); + const Type *argTy = getType(argTypeSlot); + if (argTy == 0) return failure(true); + + BCR_TRACE(4, "CE Arg " << i << ": Type: '" << argTy << "' slot: " << argValSlot << "\n"); + + // Get the arg value from its slot if it exists, otherwise a placeholder + Value *Val = getValue(argTy, argValSlot, false); + Constant* C; + if (Val) { + if (!(C = dyn_cast(Val))) return failure(true); + BCR_TRACE(5, "Constant Found in ValueTable!\n"); + } else { // Nope... find or create a forward ref. for it + C = fwdRefs.GetFwdRefToConstant(argTy, argValSlot); + } + argVec.push_back(C); + } + + // Construct a ConstantExpr of the appropriate kind + if (isExprNumArgs == 1) { // All one-operand expressions + V = ConstantExpr::get(opCode, argVec[0], Ty); + } else if (opCode == Instruction::GetElementPtr) { // GetElementPtr + vector IdxList(argVec.begin()+1, argVec.end()); + V = ConstantExpr::get(opCode, argVec[0], IdxList, Ty); + } else { // All other 2-operand expressions + V = ConstantExpr::get(opCode, argVec[0], argVec[1], Ty); + } + return false; + } + + // Ok, not an ConstantExpr. We now know how to read the given type... switch (Ty->getPrimitiveID()) { case Type::BoolTyID: { unsigned Val; @@ -286,38 +334,21 @@ bool BytecodeParser::parseConstantValue(const uchar *&Buf, const uchar *EndBuf, case 1: { // ConstantPointerRef value... unsigned Slot; if (read_vbr(Buf, EndBuf, Slot)) return failure(true); - BCR_TRACE(4, "CPPR: Type: '" << Ty << "' slot: " << Slot << "\n"); + BCR_TRACE(4, "CPR: Type: '" << Ty << "' slot: " << Slot << "\n"); // Check to see if we have already read this global variable yet... Value *Val = getValue(PT, Slot, false); - GlobalValue *GV; + GlobalValue* GV; if (Val) { - if (!(GV = dyn_cast(Val))) return failure(true); - BCR_TRACE(5, "Value Found in ValueTable!\n"); - } else { // Nope... see if we have previously forward ref'd it - GlobalRefsType::iterator I = GlobalRefs.find(make_pair(PT, Slot)); - if (I != GlobalRefs.end()) { - BCR_TRACE(5, "Previous forward ref found!\n"); - GV = I->second; - } else { - BCR_TRACE(5, "Creating new forward ref 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 - GlobalRefs.insert(make_pair(make_pair(PT, Slot), GVar)); - - // Must temporarily push this value into the module table... - TheModule->getGlobalList().push_back(GVar); - GV = GVar; - } + if (!(GV = dyn_cast(Val))) return failure(true); + BCR_TRACE(5, "Value Found in ValueTable!\n"); + } else { // Nope... find or create a forward ref. for it + GV = fwdRefs.GetFwdRefToGlobal(PT, Slot); } - V = ConstantPointerRef::get(GV); break; } + default: BCR_TRACE(5, "UNKNOWN Pointer Constant Type!\n"); return failure(true); @@ -352,9 +383,12 @@ bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf, } else { for (unsigned i = 0; i < NumEntries; ++i) { Constant *I; + int Slot; if (parseConstantValue(Buf, EndBuf, Ty, I)) return failure(true); + assert(I && "parseConstantValue returned `!failure' and NULL result"); BCR_TRACE(4, "Read Constant: '" << I << "'\n"); - if (insertValue(I, Tab) == -1) return failure(true); + if ((Slot = insertValue(I, Tab)) < 0) return failure(true); + resolveRefsToConstant(I, (unsigned) Slot); } } } diff --git a/lib/Bytecode/Reader/ReaderInternals.h b/lib/Bytecode/Reader/ReaderInternals.h index f98db725bc7..4b1974e0196 100644 --- a/lib/Bytecode/Reader/ReaderInternals.h +++ b/lib/Bytecode/Reader/ReaderInternals.h @@ -12,6 +12,8 @@ #include "llvm/BasicBlock.h" #include "llvm/Instruction.h" #include "llvm/DerivedTypes.h" +#include "llvm/Constant.h" +#include "Support/NonCopyable.h" #include #include #include @@ -39,6 +41,36 @@ struct RawInst { // The raw fields out of the bytecode stream... }; }; + +class ConstantFwdRefs: public NonCopyable { + Module* TheModule; + + // GlobalRefs - This maintains a mapping between 's and forward + // references to global values or constants. Such values may be referenced + // before they are defined, and if so, the temporary object that they + // represent is held here. + // + typedef std::map, + Value*> GlobalRefsType; + GlobalRefsType GlobalRefs; + + Value* find (const Type* Ty, unsigned Slot); + void insert (const Type* Ty, unsigned Slot, Value* V); + void erase (const Type* Ty, unsigned Slot); + +public: + // sets the current module pointer: needed to insert placeholder globals + void VisitingModule (Module* M) { TheModule = M; } + + // get a forward reference to a global or a constant + GlobalValue* GetFwdRefToGlobal (const PointerType* PT, unsigned Slot); + Constant* GetFwdRefToConstant (const Type* Ty, unsigned Slot); + + // resolve all references to the placeholder (if any) for the given value + void ResolveRefsToValue (Value* val, unsigned Slot); +}; + + class BytecodeParser : public AbstractTypeUser { std::string Error; // Error message string goes here... public: @@ -63,14 +95,8 @@ private: // All of this data is transient across calls to ParseBytecode ValueTable Values, LateResolveValues; ValueTable ModuleValues, LateResolveModuleValues; - // GlobalRefs - This maintains a mapping between 's and forward - // references to global values. Global values may be referenced before they - // are defined, and if so, the temporary object that they represent is held - // here. - // - typedef std::map, - GlobalVariable*> GlobalRefsType; - GlobalRefsType GlobalRefs; + // fwdRefs - This manages forward references to global values. + ConstantFwdRefs fwdRefs; // TypesLoaded - This vector mirrors the Values[TypeTyID] plane. It is used // to deal with forward references to types. @@ -114,11 +140,12 @@ private: bool getTypeSlot(const Type *Ty, unsigned &Slot); - // DeclareNewGlobalValue - Patch up forward references to global values in the - // form of ConstantPointerRefs. - // - void DeclareNewGlobalValue(GlobalValue *GV, unsigned Slot); - + // resolveRefsToGlobal -- resolve forward references to a global + // resolveRefsToConstant -- resolve forward references to a constant + // + void resolveRefsToGlobal(GlobalValue* GV, unsigned Slot); + void resolveRefsToConstant(Constant* C, unsigned Slot); + // refineAbstractType - The callback method is invoked when one of the // elements of TypeValues becomes more concrete... // @@ -128,6 +155,7 @@ private: template class PlaceholderDef : public SuperType { unsigned ID; + PlaceholderDef(); // do not implement public: PlaceholderDef(const Type *Ty, unsigned id) : SuperType(Ty), ID(id) {} unsigned getID() { return ID; } @@ -152,11 +180,23 @@ struct MethPlaceHolderHelper : public Function { } }; +struct ConstantPlaceHolderHelper : public Constant { + ConstantPlaceHolderHelper(const Type *Ty) + : Constant(Ty) {} + virtual bool isNullValue() const { return false; } +}; + typedef PlaceholderDef DefPHolder; typedef PlaceholderDef BBPHolder; typedef PlaceholderDef MethPHolder; +typedef PlaceholderDef ConstPHolder; + static inline unsigned getValueIDNumberFromPlaceHolder(Value *Def) { + if (isa(Def)) + return ((ConstPHolder*)Def)->getID(); + + // else discriminate by type switch (Def->getType()->getPrimitiveID()) { case Type::LabelTyID: return ((BBPHolder*)Def)->getID(); case Type::FunctionTyID: return ((MethPHolder*)Def)->getID(); -- 2.34.1