From 05950c34a4297f26ec602ef5fe491b66addd745f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 13 Oct 2001 06:47:01 +0000 Subject: [PATCH] * Add real support for global variable addresses initializing constants * Add minor optimization to BytecodeParser::refineAbstractType * MethodType::get now take an explicit isVarArg parameter * Fix encoding/decoding of VarArgs calls * Support the Invoke instruction git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@760 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bytecode/Reader/ConstantReader.cpp | 68 +++++++++++++---- lib/Bytecode/Reader/InstructionReader.cpp | 91 +++++++++++++++++++---- lib/Bytecode/Reader/Reader.cpp | 85 +++++++++++++++------ lib/Bytecode/Reader/ReaderInternals.h | 18 ++++- 4 files changed, 210 insertions(+), 52 deletions(-) diff --git a/lib/Bytecode/Reader/ConstantReader.cpp b/lib/Bytecode/Reader/ConstantReader.cpp index 2775a8d24c9..3865a5e9825 100644 --- a/lib/Bytecode/Reader/ConstantReader.cpp +++ b/lib/Bytecode/Reader/ConstantReader.cpp @@ -12,6 +12,7 @@ #include "llvm/BasicBlock.h" #include "llvm/ConstPoolVals.h" #include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" #include "ReaderInternals.h" #include @@ -44,7 +45,10 @@ const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf, Params.push_back(Ty); } - Val = MethodType::get(RetType, Params); + bool isVarArg = Params.size() && Params.back() == Type::VoidTy; + if (isVarArg) Params.pop_back(); + + Val = MethodType::get(RetType, Params, isVarArg); break; } case Type::ArrayTyID: { @@ -97,6 +101,8 @@ const Type *BytecodeParser::parseTypeConstant(const uchar *&Buf, // void BytecodeParser::refineAbstractType(const DerivedType *OldType, const Type *NewType) { + if (OldType == NewType) return; // Type is modified, but same + TypeValuesListTy::iterator I = find(MethodTypeValues.begin(), MethodTypeValues.end(), OldType); if (I == MethodTypeValues.end()) { @@ -123,11 +129,7 @@ void BytecodeParser::refineAbstractType(const DerivedType *OldType, bool BytecodeParser::parseTypeConstants(const uchar *&Buf, const uchar *EndBuf, TypeValuesListTy &Tab, unsigned NumEntries) { - assert(Tab.size() == 0 && "I think table should always be empty here!" - "This should simplify later code"); - - // Record the base, starting level that we will begin with. - unsigned BaseLevel = Tab.size(); + assert(Tab.size() == 0 && "should not have read type constants in before!"); // Insert a bunch of opaque types to be resolved later... for (unsigned i = 0; i < NumEntries; i++) @@ -137,7 +139,7 @@ bool BytecodeParser::parseTypeConstants(const uchar *&Buf, const uchar *EndBuf, // opaque types just inserted. // for (unsigned i = 0; i < NumEntries; i++) { - const Type *NewTy = parseTypeConstant(Buf, EndBuf); + const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get(); if (NewTy == 0) return failure(true); BCR_TRACE(4, "Read Type Constant: '" << NewTy << "'\n"); @@ -149,16 +151,16 @@ bool BytecodeParser::parseTypeConstants(const uchar *&Buf, const uchar *EndBuf, // abstract type to use the newty. This also will cause the opaque type // to be deleted... // - cast(Tab[i+BaseLevel].get())->refineAbstractTypeTo(NewTy); + cast(Tab[i].get())->refineAbstractTypeTo(NewTy); // This should have replace the old opaque type with the new type in the - // value table... - assert(Tab[i+BaseLevel] == NewTy && "refineAbstractType didn't work!"); + // value table... or with a preexisting type that was already in the system + assert(Tab[i] != OldTy && "refineAbstractType didn't work!"); } BCR_TRACE(5, "Resulting types:\n"); for (unsigned i = 0; i < NumEntries; i++) { - BCR_TRACE(5, cast(Tab[i+BaseLevel]) << "\n"); + BCR_TRACE(5, cast(Tab[i]) << "\n"); } return false; } @@ -270,10 +272,48 @@ bool BytecodeParser::parseConstPoolValue(const uchar *&Buf, const PointerType *PT = cast(Ty); unsigned SubClass; if (read_vbr(Buf, EndBuf, SubClass)) return failure(true); - if (SubClass != 0) return failure(true); + switch (SubClass) { + case 0: // ConstPoolPointerNull value... + V = ConstPoolPointerNull::get(PT); + break; + case 1: { // ConstPoolPointerReference value... + unsigned Slot; + if (read_vbr(Buf, EndBuf, Slot)) return failure(true); + BCR_TRACE(4, "CPPR: Type: '" << Ty << "' slot: " << Slot << "\n"); - V = ConstPoolPointer::getNull(PT); + // Check to see if we have already read this global variable yet... + Value *Val = getValue(PT, Slot, false); + 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->getValueType(), false); + + // 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; + } + } + + V = ConstPoolPointerReference::get(GV); + break; + } + default: + return failure(true); + } break; } @@ -306,7 +346,7 @@ bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf, ConstPoolVal *I; if (parseConstPoolValue(Buf, EndBuf, Ty, I)) return failure(true); BCR_TRACE(4, "Read Constant: '" << I << "'\n"); - insertValue(I, Tab); + if (insertValue(I, Tab) == -1) return failure(true); } } } diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp index 5697b2620f9..58f2656559c 100644 --- a/lib/Bytecode/Reader/InstructionReader.cpp +++ b/lib/Bytecode/Reader/InstructionReader.cpp @@ -1,4 +1,4 @@ -//===- ReadInst.cpp - Code to read an instruction from bytecode -------------=== +//===- ReadInst.cpp - Code to read an instruction from bytecode -----------===// // // This file defines the mechanism to read an instruction from a bytecode // stream. @@ -9,7 +9,7 @@ // TODO: Change from getValue(Raw.Arg1) etc, to getArg(Raw, 1) // Make it check type, so that casts are checked. // -//===------------------------------------------------------------------------=== +//===----------------------------------------------------------------------===// #include "llvm/iOther.h" #include "llvm/iTerminators.h" @@ -193,13 +193,19 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf, } case Instruction::Call: { - Method *M = cast(getValue(Raw.Ty, Raw.Arg1)); + Value *M = getValue(Raw.Ty, Raw.Arg1); if (M == 0) return failure(true); - vector Params; - const MethodType::ParamTypes &PL = M->getMethodType()->getParamTypes(); + // Check to make sure we have a pointer to method type + PointerType *PTy = dyn_cast(M->getType()); + if (PTy == 0) return failure(true); + MethodType *MTy = dyn_cast(PTy->getValueType()); + if (MTy == 0) return failure(true); - if (!M->getMethodType()->isVarArg()) { + vector Params; + const MethodType::ParamTypes &PL = MTy->getParamTypes(); + + if (!MTy->isVarArg()) { MethodType::ParamTypes::const_iterator It = PL.begin(); switch (Raw.NumOperands) { @@ -224,23 +230,76 @@ bool BytecodeParser::ParseInstruction(const uchar *&Buf, const uchar *EndBuf, } if (It != PL.end()) return failure(true); } else { - // The first parameter does not have a type specifier... because there - // must be at least one concrete argument to a vararg type... - Params.push_back(getValue(PL.front(), Raw.Arg2)); + if (Raw.NumOperands > 2) { + vector &args = *Raw.VarArgs; + if (args.size() < 1) return failure(true); - vector &args = *Raw.VarArgs; - if ((args.size() & 1) != 0) - return failure(true); // Must be pairs of type/value - for (unsigned i = 0; i < args.size(); i+=2) { - // TODO: Check getValue for null! - Params.push_back(getValue(getType(args[i]), args[i+1])); + if ((args.size() & 1) != 0) + return failure(true); // Must be pairs of type/value + for (unsigned i = 0; i < args.size(); i+=2) { + const Type *Ty = getType(args[i]); + if (Ty == 0) + return failure(true); + + Value *V = getValue(Ty, args[i+1]); + if (V == 0) return failure(true); + Params.push_back(V); + } + delete Raw.VarArgs; } - delete Raw.VarArgs; } Res = new CallInst(M, Params); return false; } + case Instruction::Invoke: { + Value *M = getValue(Raw.Ty, Raw.Arg1); + if (M == 0) return failure(true); + + // Check to make sure we have a pointer to method type + PointerType *PTy = dyn_cast(M->getType()); + if (PTy == 0) return failure(true); + MethodType *MTy = dyn_cast(PTy->getValueType()); + if (MTy == 0) return failure(true); + + vector Params; + const MethodType::ParamTypes &PL = MTy->getParamTypes(); + vector &args = *Raw.VarArgs; + + BasicBlock *Normal, *Except; + + if (!MTy->isVarArg()) { + if (Raw.NumOperands < 3) return failure(true); + + Normal = cast(getValue(Type::LabelTy, Raw.Arg2)); + Except = cast(getValue(Type::LabelTy, args[0])); + + MethodType::ParamTypes::const_iterator It = PL.begin(); + for (unsigned i = 1; i < args.size(); i++) { + if (It == PL.end()) return failure(true); + // TODO: Check getValue for null! + Params.push_back(getValue(*It++, args[i])); + } + + if (It != PL.end()) return failure(true); + } else { + if (args.size() < 4) return failure(true); + + Normal = cast(getValue(Type::LabelTy, args[0])); + Except = cast(getValue(Type::LabelTy, args[2])); + + if ((args.size() & 1) != 0) + return failure(true); // Must be pairs of type/value + for (unsigned i = 4; i < args.size(); i+=2) { + // TODO: Check getValue for null! + Params.push_back(getValue(getType(args[i]), args[i+1])); + } + } + + delete Raw.VarArgs; + Res = new InvokeInst(M, Normal, Except, Params); + return false; + } case Instruction::Malloc: if (Raw.NumOperands > 2) return failure(true); V = Raw.NumOperands ? getValue(Type::UIntTy, Raw.Arg1) : 0; diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 97428ea4ee9..f93e73d42f7 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -58,9 +58,9 @@ const Type *BytecodeParser::getType(unsigned ID) { return cast(D); } -bool BytecodeParser::insertValue(Value *Val, vector &ValueTab) { +int BytecodeParser::insertValue(Value *Val, vector &ValueTab) { unsigned type; - if (getTypeSlot(Val->getType(), type)) return failure(true); + if (getTypeSlot(Val->getType(), type)) return failure(-1); assert(type != Type::TypeTyID && "Types should never be insertValue'd!"); if (ValueTab.size() <= type) @@ -70,7 +70,7 @@ bool BytecodeParser::insertValue(Value *Val, vector &ValueTab) { // << "] = " << Val << endl; ValueTab[type].push_back(Val); - return false; + return ValueTab[type].size()-1; } Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) { @@ -89,12 +89,12 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) { // Is it a module level type? if (Num < ModuleTypeValues.size()) - return (Value*)(const Type*)ModuleTypeValues[Num]; + return (Value*)ModuleTypeValues[Num].get(); // Nope, is it a method level type? Num -= ModuleTypeValues.size(); if (Num < MethodTypeValues.size()) - return (Value*)(const Type*)MethodTypeValues[Num]; + return (Value*)MethodTypeValues[Num].get(); return 0; } @@ -117,13 +117,13 @@ Value *BytecodeParser::getValue(const Type *Ty, unsigned oNum, bool Create) { cerr << "Creating method pholder! : " << type << ":" << oNum << " " << Ty->getName() << endl; d = new MethPHolder(Ty, oNum); - insertValue(d, LateResolveModuleValues); + if (insertValue(d, LateResolveModuleValues) ==-1) return failure(0); return d; default: d = new DefPHolder(Ty, oNum); break; } assert(d != 0 && "How did we not make something?"); - if (insertValue(d, LateResolveValues)) return failure(0); + if (insertValue(d, LateResolveValues) == -1) return failure(0); return d; } @@ -141,8 +141,8 @@ bool BytecodeParser::postResolveValues(ValueTable &ValTab) { Value *NewDef = getValue(D->getType(), IDNumber, false); if (NewDef == 0) { Error = true; // Unresolved thinger - cerr << "Unresolvable reference found: <" << D->getType()->getName() - << ">:" << IDNumber << "!\n"; + cerr << "Unresolvable reference found: <" + << D->getType()->getDescription() << ">:" << IDNumber << "!\n"; } else { // Fixup all of the uses of this placeholder def... D->replaceAllUsesWith(NewDef); @@ -169,7 +169,7 @@ bool BytecodeParser::ParseBasicBlock(const uchar *&Buf, const uchar *EndBuf, } if (Inst == 0) { delete BB; return failure(true); } - if (insertValue(Inst, Values)) { delete BB; return failure(true); } + if (insertValue(Inst, Values) == -1) { delete BB; return failure(true); } BB->getInstList().push_back(Inst); @@ -216,6 +216,41 @@ bool BytecodeParser::ParseSymbolTable(const uchar *&Buf, const uchar *EndBuf, return false; } +// DeclareNewGlobalValue - Patch up forward references to global values in the +// form of ConstPoolPointerReferences. +// +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)); + + 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 ConstPoolPointerReference's. + assert(OldGV->use_size() == 1 && "Only one reference should exist!"); + while (!OldGV->use_empty()) { + User *U = OldGV->use_back(); // Must be a ConstPoolPointerReference... + ConstPoolPointerReference *CPPR = cast(U); + assert(CPPR->getValue() == OldGV && "Something isn't happy"); + + BCR_TRACE(4, "Mutating Forward Ref!\n"); + + // Change the const pool reference to point to the real global variable + // now. This should drop a use from the OldGV. + CPPR->mutateReference(GV); + } + + // 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); + } +} bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, Module *C) { @@ -237,7 +272,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, for (MethodType::ParamTypes::const_iterator It = Params.begin(); It != Params.end(); ++It) { MethodArgument *MA = new MethodArgument(*It); - if (insertValue(MA, Values)) { delete M; return failure(true); } + if (insertValue(MA, Values) == -1) { delete M; return failure(true); } M->getArgumentList().push_back(MA); } @@ -258,7 +293,7 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, BCR_TRACE(2, "BLOCK BytecodeFormat::BasicBlock: {\n"); BasicBlock *BB; if (ParseBasicBlock(Buf, Buf+Size, BB) || - insertValue(BB, Values)) { + insertValue(BB, Values) == -1) { delete M; return failure(true); // Parse error... :( } @@ -314,11 +349,13 @@ bool BytecodeParser::ParseMethod(const uchar *&Buf, const uchar *EndBuf, // We don't need the placeholder anymore! delete MethPHolder; + DeclareNewGlobalValue(M, MethSlot); + return false; } bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End, - Module *C) { + Module *Mod) { if (!MethodSignatureList.empty()) return failure(true); // Two ModuleGlobal blocks? @@ -334,7 +371,7 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End, } const PointerType *PTy = cast(Ty); - Ty = PTy->getValueType(); + const Type *ElTy = PTy->getValueType(); ConstPoolVal *Initializer = 0; if (VarType & 2) { // Does it have an initalizer? @@ -344,18 +381,24 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End, unsigned InitSlot; if (read_vbr(Buf, End, InitSlot)) return failure(true); - Value *V = getValue(Ty, InitSlot, false); + Value *V = getValue(ElTy, InitSlot, false); if (V == 0) return failure(true); Initializer = cast(V); } // Create the global variable... - GlobalVariable *GV = new GlobalVariable(Ty, VarType & 1, Initializer); - insertValue(GV, ModuleValues); - C->getGlobalList().push_back(GV); + GlobalVariable *GV = new GlobalVariable(ElTy, VarType & 1, Initializer); + int DestSlot = insertValue(GV, ModuleValues); + if (DestSlot == -1) return failure(true); + + Mod->getGlobalList().push_back(GV); + + DeclareNewGlobalValue(GV, unsigned(DestSlot)); + + BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription() + << " into slot #" << DestSlot << endl); if (read_vbr(Buf, End, VarType)) return failure(true); - BCR_TRACE(2, "Global Variable of type: " << PTy->getDescription() << endl); } // Read the method signatures for all of the methods that are coming, and @@ -380,7 +423,7 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End, // Insert the placeholder... Value *Val = new MethPHolder(Ty, 0); - insertValue(Val, ModuleValues); + if (insertValue(Val, ModuleValues) == -1) return failure(true); // Figure out which entry of its typeslot it went into... unsigned TypeSlot; @@ -422,7 +465,7 @@ bool BytecodeParser::ParseModule(const uchar *Buf, const uchar *EndBuf, if (align32(Buf, EndBuf)) return failure(true); BCR_TRACE(1, "FirstDerivedTyID = " << FirstDerivedTyID << "\n"); - C = new Module(); + TheModule = C = new Module(); while (Buf < EndBuf) { const uchar *OldBuf = Buf; if (readBlock(Buf, EndBuf, Type, Size)) { delete C; return failure(true); } diff --git a/lib/Bytecode/Reader/ReaderInternals.h b/lib/Bytecode/Reader/ReaderInternals.h index ec486d851e4..a5b01c2438f 100644 --- a/lib/Bytecode/Reader/ReaderInternals.h +++ b/lib/Bytecode/Reader/ReaderInternals.h @@ -29,6 +29,7 @@ class BasicBlock; class Method; class Module; class Type; +class PointerType; typedef unsigned char uchar; @@ -52,11 +53,22 @@ public: Module *ParseBytecode(const uchar *Buf, const uchar *EndBuf); private: // All of this data is transient across calls to ParseBytecode + Module *TheModule; // Current Module being read into... + typedef vector ValueList; typedef vector ValueTable; 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 map, GlobalVariable*> + GlobalRefsType; + GlobalRefsType GlobalRefs; + // TypesLoaded - This vector mirrors the Values[TypeTyID] plane. It is used // to deal with forward references to types. // @@ -94,11 +106,15 @@ private: Value *getValue(const Type *Ty, unsigned num, bool Create = true); const Type *getType(unsigned ID); - bool insertValue(Value *D, vector &D); + int insertValue(Value *D, vector &D); // -1 = Failure bool postResolveValues(ValueTable &ValTab); bool getTypeSlot(const Type *Ty, unsigned &Slot); + // DeclareNewGlobalValue - Patch up forward references to global values in the + // form of ConstPoolPointerReferences. + // + void DeclareNewGlobalValue(GlobalValue *GV, unsigned Slot); // refineAbstractType - The callback method is invoked when one of the // elements of TypeValues becomes more concrete...