diff options
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 328 | ||||
-rw-r--r-- | lib/VMCore/BasicBlock.cpp | 113 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 197 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.h | 145 | ||||
-rw-r--r-- | lib/VMCore/ConstantFolding.h | 145 | ||||
-rw-r--r-- | lib/VMCore/ConstantPool.cpp | 434 | ||||
-rw-r--r-- | lib/VMCore/Function.cpp | 75 | ||||
-rw-r--r-- | lib/VMCore/InstrTypes.cpp | 66 | ||||
-rw-r--r-- | lib/VMCore/Instruction.cpp | 61 | ||||
-rw-r--r-- | lib/VMCore/Makefile | 7 | ||||
-rw-r--r-- | lib/VMCore/Module.cpp | 42 | ||||
-rw-r--r-- | lib/VMCore/SlotCalculator.cpp | 195 | ||||
-rw-r--r-- | lib/VMCore/SymbolTable.cpp | 106 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 308 | ||||
-rw-r--r-- | lib/VMCore/Value.cpp | 143 | ||||
-rw-r--r-- | lib/VMCore/ValueHolderImpl.h | 85 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 94 | ||||
-rw-r--r-- | lib/VMCore/iBranch.cpp | 69 | ||||
-rw-r--r-- | lib/VMCore/iCall.cpp | 48 | ||||
-rw-r--r-- | lib/VMCore/iOperators.cpp | 37 | ||||
-rw-r--r-- | lib/VMCore/iReturn.cpp | 25 | ||||
-rw-r--r-- | lib/VMCore/iSwitch.cpp | 81 |
22 files changed, 2804 insertions, 0 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp new file mode 100644 index 0000000..e23403b --- /dev/null +++ b/lib/VMCore/AsmWriter.cpp @@ -0,0 +1,328 @@ +//===-- Writer.cpp - Library for Printing VM assembly files ------*- C++ -*--=// +// +// This library implements the functionality defined in llvm/Assembly/Writer.h +// +// This library uses the Analysis library to figure out offsets for +// variables in the method tables... +// +// TODO: print out the type name instead of the full type if a particular type +// is in the symbol table... +// +//===----------------------------------------------------------------------===// + +#include "llvm/Assembly/Writer.h" +#include "llvm/Analysis/SlotCalculator.h" +#include "llvm/Module.h" +#include "llvm/Method.h" +#include "llvm/BasicBlock.h" +#include "llvm/ConstPoolVals.h" +#include "llvm/iOther.h" +#include "llvm/iMemory.h" + +class AssemblyWriter : public ModuleAnalyzer { + ostream &Out; + SlotCalculator &Table; +public: + inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) { + } + + inline void write(const Module *M) { processModule(M); } + inline void write(const Method *M) { processMethod(M); } + inline void write(const BasicBlock *BB) { processBasicBlock(BB); } + inline void write(const Instruction *I) { processInstruction(I); } + inline void write(const ConstPoolVal *CPV) { processConstant(CPV); } + +protected: + virtual bool visitMethod(const Method *M); + virtual bool processConstPool(const ConstantPool &CP, bool isMethod); + virtual bool processConstant(const ConstPoolVal *CPV); + virtual bool processMethod(const Method *M); + virtual bool processMethodArgument(const MethodArgument *MA); + virtual bool processBasicBlock(const BasicBlock *BB); + virtual bool processInstruction(const Instruction *I); + +private : + void writeOperand(const Value *Op, bool PrintType, bool PrintName = true); +}; + + + +// visitMethod - This member is called after the above two steps, visting each +// method, because they are effectively values that go into the constant pool. +// +bool AssemblyWriter::visitMethod(const Method *M) { + return false; +} + +bool AssemblyWriter::processConstPool(const ConstantPool &CP, bool isMethod) { + // Done printing arguments... + if (isMethod) Out << ")\n"; + + ModuleAnalyzer::processConstPool(CP, isMethod); + + if (isMethod) + Out << "begin"; + else + Out << "implementation\n"; + return false; +} + + +// processConstant - Print out a constant pool entry... +// +bool AssemblyWriter::processConstant(const ConstPoolVal *CPV) { + Out << "\t"; + + // Print out name if it exists... + if (CPV->hasName()) + Out << "%" << CPV->getName() << " = "; + + // Print out the opcode... + Out << CPV->getType(); + + // Write the value out now... + writeOperand(CPV, false, false); + + if (!CPV->hasName() && CPV->getType() != Type::VoidTy) { + int Slot = Table.getValSlot(CPV); // Print out the def slot taken... + Out << "\t\t; <" << CPV->getType() << ">:"; + if (Slot >= 0) Out << Slot; + else Out << "<badref>"; + } + + Out << endl; + return false; +} + +// processMethod - Process all aspects of a method. +// +bool AssemblyWriter::processMethod(const Method *M) { + // Print out the return type and name... + Out << "\n" << M->getReturnType() << " \"" << M->getName() << "\"("; + Table.incorporateMethod(M); + ModuleAnalyzer::processMethod(M); + Table.purgeMethod(); + Out << "end\n"; + return false; +} + +// processMethodArgument - This member is called for every argument that +// is passed into the method. Simply print it out +// +bool AssemblyWriter::processMethodArgument(const MethodArgument *Arg) { + // Insert commas as we go... the first arg doesn't get a comma + if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", "; + + // Output type... + Out << Arg->getType(); + + // Output name, if available... + if (Arg->hasName()) + Out << " %" << Arg->getName(); + else if (Table.getValSlot(Arg) < 0) + Out << "<badref>"; + + return false; +} + +// processBasicBlock - This member is called for each basic block in a methd. +// +bool AssemblyWriter::processBasicBlock(const BasicBlock *BB) { + if (BB->hasName()) { // Print out the label if it exists... + Out << "\n" << BB->getName() << ":\n"; + } else { + int Slot = Table.getValSlot(BB); + Out << "\t\t\t\t; <label>:"; + if (Slot >= 0) + Out << Slot << endl; // Extra newline seperates out label's + else + Out << "<badref>\n"; + } + + ModuleAnalyzer::processBasicBlock(BB); + return false; +} + +// processInstruction - This member is called for each Instruction in a methd. +// +bool AssemblyWriter::processInstruction(const Instruction *I) { + Out << "\t"; + + // Print out name if it exists... + if (I && I->hasName()) + Out << "%" << I->getName() << " = "; + + // Print out the opcode... + Out << I->getOpcode(); + + // Print out the type of the operands... + const Value *Operand = I->getOperand(0); + + // Special case conditional branches to swizzle the condition out to the front + if (I->getInstType() == Instruction::Br && I->getOperand(1)) { + writeOperand(I->getOperand(2), true); + Out << ","; + writeOperand(Operand, true); + Out << ","; + writeOperand(I->getOperand(1), true); + + } else if (I->getInstType() == Instruction::Switch) { + // Special case switch statement to get formatting nice and correct... + writeOperand(Operand , true); Out << ","; + writeOperand(I->getOperand(1), true); Out << " ["; + + for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) { + Out << "\n\t\t"; + writeOperand(Operand, true); Out << ","; + writeOperand(I->getOperand(op+1), true); + } + Out << "\n\t]"; + + } else if (I->getInstType() == Instruction::Ret && !Operand) { + Out << " void"; + } else if (I->getInstType() == Instruction::Call) { + writeOperand(Operand, true); + Out << "("; + Operand = I->getOperand(1); + if (Operand) writeOperand(Operand, true); + for (unsigned op = 2; (Operand = I->getOperand(op)); ++op) { + Out << ","; + writeOperand(Operand, true); + } + + Out << " )"; + } else if (I->getInstType() == Instruction::Malloc || + I->getInstType() == Instruction::Alloca) { + Out << " " << ((const PointerType*)((ConstPoolType*)Operand) + ->getValue())->getValueType(); + if ((Operand = I->getOperand(1))) { + Out << ","; writeOperand(Operand, true); + } + + } else if (Operand) { // Print the normal way... + + // PrintAllTypes - Instructions who have operands of all the same type + // omit the type from all but the first operand. If the instruction has + // different type operands (for example br), then they are all printed. + bool PrintAllTypes = false; + const Type *TheType = Operand->getType(); + unsigned i; + + for (i = 1; (Operand = I->getOperand(i)); i++) { + if (Operand->getType() != TheType) { + PrintAllTypes = true; // We have differing types! Print them all! + break; + } + } + + if (!PrintAllTypes) + Out << " " << I->getOperand(0)->getType(); + + for (unsigned i = 0; (Operand = I->getOperand(i)); i++) { + if (i) Out << ","; + writeOperand(Operand, PrintAllTypes); + } + } + + // Print a little comment after the instruction indicating which slot it + // occupies. + // + if (!I->hasName() && I->getType() != Type::VoidTy) { + int Slot = Table.getValSlot(I); // Print out the def slot taken... + Out << "\t\t; <" << I->getType() << ">:"; + if (Slot >= 0) Out << Slot; + else Out << "<badref>"; + + Out << "\t[#uses=" << I->use_size() << "]"; // Output # uses + } + + Out << endl; + + return false; +} + + +void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType, + bool PrintName) { + if (PrintType) + Out << " " << Operand->getType(); + + if (Operand->hasName() && PrintName) { + Out << " %" << Operand->getName(); + } else { + int Slot = Table.getValSlot(Operand); + + if (Operand->getValueType() == Value::ConstantVal) { + Out << " " << ((ConstPoolVal*)Operand)->getStrValue(); + } else { + if (Slot >= 0) Out << " %" << Slot; + else if (PrintName) + Out << "<badref>"; // Not embeded into a location? + } + } +} + + +//===----------------------------------------------------------------------===// +// External Interface declarations +//===----------------------------------------------------------------------===// + + + +void WriteToAssembly(const Module *M, ostream &o) { + if (M == 0) { o << "<null> module\n"; return; } + SlotCalculator SlotTable(M, true); + AssemblyWriter W(o, SlotTable); + + W.write(M); +} + +void WriteToAssembly(const Method *M, ostream &o) { + if (M == 0) { o << "<null> method\n"; return; } + SlotCalculator SlotTable(M->getParent(), true); + AssemblyWriter W(o, SlotTable); + + W.write(M); +} + + +void WriteToAssembly(const BasicBlock *BB, ostream &o) { + if (BB == 0) { o << "<null> basic block\n"; return; } + + SlotCalculator SlotTable(BB->getParent(), true); + AssemblyWriter W(o, SlotTable); + + W.write(BB); +} + +void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) { + if (CPV == 0) { o << "<null> constant pool value\n"; return; } + + SlotCalculator *SlotTable; + + // A Constant pool value may have a parent that is either a method or a + // module. Untangle this now... + // + if (CPV->getParent() == 0 || + CPV->getParent()->getValueType() == Value::MethodVal) { + SlotTable = new SlotCalculator((Method*)CPV->getParent(), true); + } else { + assert(CPV->getParent()->getValueType() == Value::ModuleVal); + SlotTable = new SlotCalculator((Module*)CPV->getParent(), true); + } + + AssemblyWriter W(o, *SlotTable); + W.write(CPV); + + delete SlotTable; +} + +void WriteToAssembly(const Instruction *I, ostream &o) { + if (I == 0) { o << "<null> instruction\n"; return; } + + SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0, + true); + AssemblyWriter W(o, SlotTable); + + W.write(I); +} diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp new file mode 100644 index 0000000..f60bd46 --- /dev/null +++ b/lib/VMCore/BasicBlock.cpp @@ -0,0 +1,113 @@ +//===-- BasicBlock.cpp - Implement BasicBlock related functions --*- C++ -*--=// +// +// This file implements the Method class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ValueHolderImpl.h" +#include "llvm/BasicBlock.h" +#include "llvm/iTerminators.h" +#include "llvm/Module.h" +#include "llvm/Method.h" +#include "llvm/SymbolTable.h" +#include "llvm/Type.h" + +// Instantiate Templates - This ugliness is the price we have to pay +// for having a ValueHolderImpl.h file seperate from ValueHolder.h! :( +// +template class ValueHolder<Instruction, BasicBlock>; + +BasicBlock::BasicBlock(const string &name, Method *parent) + : Value(Type::LabelTy, Value::BasicBlockVal, name), InstList(this, 0) { + + if (parent) + parent->getBasicBlocks().push_back(this); +} + +BasicBlock::~BasicBlock() { + dropAllReferences(); + InstList.delete_all(); +} + +// Specialize setName to take care of symbol table majik +void BasicBlock::setName(const string &name) { + Method *P; + if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this); + Value::setName(name); + if (P && hasName()) P->getSymbolTable()->insert(this); +} + +void BasicBlock::setParent(Method *parent) { + if (getParent() && hasName()) + getParent()->getSymbolTable()->remove(this); + + InstList.setParent(parent); + + if (getParent() && hasName()) + getParent()->getSymbolTableSure()->insert(this); +} + +TerminatorInst *BasicBlock::getTerminator() { + if (InstList.empty()) return 0; + Instruction *T = InstList.back(); + if (T->isTerminator()) return (TerminatorInst*)T; + return 0; +} + +const TerminatorInst *const BasicBlock::getTerminator() const { + if (InstList.empty()) return 0; + const Instruction *T = InstList.back(); + if (T->isTerminator()) return (TerminatorInst*)T; + return 0; +} + +void BasicBlock::dropAllReferences() { + for_each(InstList.begin(), InstList.end(), + std::mem_fun(&Instruction::dropAllReferences)); +} + +// hasConstantPoolReferences() - This predicate is true if there is a +// reference to this basic block in the constant pool for this method. For +// example, if a block is reached through a switch table, that table resides +// in the constant pool, and the basic block is reference from it. +// +bool BasicBlock::hasConstantPoolReferences() const { + for (use_const_iterator I = use_begin(), E = use_end(); I != E; ++I) + if ((*I)->getValueType() == ConstantVal) + return true; + + return false; +} + + +// splitBasicBlock - This splits a basic block into two at the specified +// instruction. Note that all instructions BEFORE the specified iterator stay +// as part of the original basic block, an unconditional branch is added to +// the new BB, and the rest of the instructions in the BB are moved to the new +// BB, including the old terminator. This invalidates the iterator. +// +// Note that this only works on well formed basic blocks (must have a +// terminator), and 'I' must not be the end of instruction list (which would +// cause a degenerate basic block to be formed, having a terminator inside of +// the basic block). +// +BasicBlock *BasicBlock::splitBasicBlock(InstListType::iterator I) { + assert(getTerminator() && "Can't use splitBasicBlock on degenerate BB!"); + assert(I != InstList.end() && + "Trying to get me to create degenerate basic block!"); + + BasicBlock *New = new BasicBlock("", getParent()); + + // Go from the end of the basic block through to the iterator pointer, moving + // to the new basic block... + Instruction *Inst = 0; + do { + InstListType::iterator EndIt = InstList.end(); + Inst = InstList.remove(--EndIt); // Remove from end + New->InstList.push_front(Inst); // Add to front + } while (Inst != *I); // Loop until we move the specified instruction. + + // Add a branch instruction to the newly formed basic block. + InstList.push_back(new BranchInst(New)); + return New; +} diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp new file mode 100644 index 0000000..438ea4b --- /dev/null +++ b/lib/VMCore/ConstantFold.cpp @@ -0,0 +1,197 @@ +//===- ConstantHandling.cpp - Implement ConstantHandling.h ----------------===// +// +// This file implements the various intrinsic operations, on constant values. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Opt/ConstantHandling.h" + +//===----------------------------------------------------------------------===// +// TemplateRules Class +//===----------------------------------------------------------------------===// +// +// TemplateRules - Implement a subclass of ConstRules that provides all +// operations as noops. All other rules classes inherit from this class so +// that if functionality is needed in the future, it can simply be added here +// and to ConstRules without changing anything else... +// +// This class also provides subclasses with typesafe implementations of methods +// so that don't have to do type casting. +// +template<class ArgType, class SubClassName> +class TemplateRules : public ConstRules { + + //===--------------------------------------------------------------------===// + // Redirecting functions that cast to the appropriate types + //===--------------------------------------------------------------------===// + + virtual ConstPoolVal *neg(const ConstPoolVal *V) const { + return SubClassName::Neg((const ArgType *)V); + } + + virtual ConstPoolVal *not(const ConstPoolVal *V) const { + return SubClassName::Not((const ArgType *)V); + } + + + virtual ConstPoolVal *add(const ConstPoolVal *V1, + const ConstPoolVal *V2) const { + return SubClassName::Add((const ArgType *)V1, (const ArgType *)V2); + } + + virtual ConstPoolVal *sub(const ConstPoolVal *V1, + const ConstPoolVal *V2) const { + return SubClassName::Sub((const ArgType *)V1, (const ArgType *)V2); + } + + virtual ConstPoolBool *lessthan(const ConstPoolVal *V1, + const ConstPoolVal *V2) const { + return SubClassName::LessThan((const ArgType *)V1, (const ArgType *)V2); + } + + //===--------------------------------------------------------------------===// + // Default "noop" implementations + //===--------------------------------------------------------------------===// + + inline static ConstPoolVal *Neg(const ArgType *V) { return 0; } + inline static ConstPoolVal *Not(const ArgType *V) { return 0; } + + inline static ConstPoolVal *Add(const ArgType *V1, const ArgType *V2) { + return 0; + } + + inline static ConstPoolVal *Sub(const ArgType *V1, const ArgType *V2) { + return 0; + } + + inline static ConstPoolBool *LessThan(const ArgType *V1, const ArgType *V2) { + return 0; + } +}; + + + +//===----------------------------------------------------------------------===// +// EmptyRules Class +//===----------------------------------------------------------------------===// +// +// EmptyRules provides a concrete base class of ConstRules that does nothing +// +static // EmptyInst is static +struct EmptyRules : public TemplateRules<ConstPoolVal, EmptyRules> { +} EmptyInst; + + + +//===----------------------------------------------------------------------===// +// BoolRules Class +//===----------------------------------------------------------------------===// +// +// BoolRules provides a concrete base class of ConstRules for the 'bool' type. +// +static // BoolTyInst is static... +struct BoolRules : public TemplateRules<ConstPoolBool, BoolRules> { + + inline static ConstPoolVal *Not(const ConstPoolBool *V) { + return new ConstPoolBool(!V->getValue()); + } + + inline static ConstPoolVal *Or(const ConstPoolBool *V1, + const ConstPoolBool *V2) { + bool Result = V1->getValue() | V2->getValue(); + return new ConstPoolBool(Result); + } + + inline static ConstPoolVal *And(const ConstPoolBool *V1, + const ConstPoolBool *V2) { + bool Result = V1->getValue() & V2->getValue(); + return new ConstPoolBool(Result); + } +} BoolTyInst; + + +//===----------------------------------------------------------------------===// +// DirectRules Class +//===----------------------------------------------------------------------===// +// +// DirectRules provides a concrete base classes of ConstRules for a variety of +// different types. This allows the C++ compiler to automatically generate our +// constant handling operations in a typesafe and accurate manner. +// +template<class ConstPoolClass, class BuiltinType, const Type **Ty> +struct DirectRules + : public TemplateRules<ConstPoolClass, + DirectRules<ConstPoolClass, BuiltinType, Ty> > { + + inline static ConstPoolVal *Neg(const ConstPoolClass *V) { + return new ConstPoolClass(*Ty, -(BuiltinType)V->getValue());; + } + inline static ConstPoolVal *Not(const ConstPoolClass *V) { + return new ConstPoolClass(*Ty, !(BuiltinType)V->getValue());; + } + + inline static ConstPoolVal *Add(const ConstPoolClass *V1, + const ConstPoolClass *V2) { + BuiltinType Result = (BuiltinType)V1->getValue() + + (BuiltinType)V2->getValue(); + return new ConstPoolClass(*Ty, Result); + } + + inline static ConstPoolVal *Sub(const ConstPoolClass *V1, + const ConstPoolClass *V2) { + BuiltinType Result = (BuiltinType)V1->getValue() - + (BuiltinType)V2->getValue(); + return new ConstPoolClass(*Ty, Result); + } + + inline static ConstPoolBool *LessThan(const ConstPoolClass *V1, + const ConstPoolClass *V2) { + bool Result = (BuiltinType)V1->getValue() < (BuiltinType)V2->getValue(); + return new ConstPoolBool(Result); + } +}; + +//===----------------------------------------------------------------------===// +// DirectRules Subclasses +//===----------------------------------------------------------------------===// +// +// Given the DirectRules class we can now implement lots of types with little +// code. Thank goodness C++ compilers are great at stomping out layers of +// templates... can you imagine having to do this all by hand? (/me is lazy :) +// +static DirectRules<ConstPoolSInt, signed char , &Type::SByteTy> SByteTyInst; +static DirectRules<ConstPoolUInt, unsigned char , &Type::UByteTy> UByteTyInst; +static DirectRules<ConstPoolSInt, signed short, &Type::ShortTy> ShortTyInst; +static DirectRules<ConstPoolUInt, unsigned short, &Type::UShortTy> UShortTyInst; +static DirectRules<ConstPoolSInt, signed int , &Type::IntTy> IntTyInst; +static DirectRules<ConstPoolUInt, unsigned int , &Type::UIntTy> UIntTyInst; +static DirectRules<ConstPoolSInt, int64_t , &Type::LongTy> LongTyInst; +static DirectRules<ConstPoolUInt, uint64_t , &Type::ULongTy> ULongTyInst; +static DirectRules<ConstPoolFP , float , &Type::FloatTy> FloatTyInst; +static DirectRules<ConstPoolFP , double , &Type::DoubleTy> DoubleTyInst; + + +// ConstRules::find - Return the constant rules that take care of the specified +// type. Note that this is cached in the Type value itself, so switch statement +// is only hit at most once per type. +// +const ConstRules *ConstRules::find(const Type *Ty) { + const ConstRules *Result; + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: Result = &BoolTyInst; break; + case Type::SByteTyID: Result = &SByteTyInst; break; + case Type::UByteTyID: Result = &UByteTyInst; break; + case Type::ShortTyID: Result = &ShortTyInst; break; + case Type::UShortTyID: Result = &UShortTyInst; break; + case Type::IntTyID: Result = &IntTyInst; break; + case Type::UIntTyID: Result = &UIntTyInst; break; + case Type::LongTyID: Result = &LongTyInst; break; + case Type::ULongTyID: Result = &ULongTyInst; break; + case Type::FloatTyID: Result = &FloatTyInst; break; + case Type::DoubleTyID: Result = &DoubleTyInst; break; + default: Result = &EmptyInst; break; + } + + Ty->setConstRules(Result); // Cache the value for future short circuiting! + return Result; +} diff --git a/lib/VMCore/ConstantFold.h b/lib/VMCore/ConstantFold.h new file mode 100644 index 0000000..3227e39 --- /dev/null +++ b/lib/VMCore/ConstantFold.h @@ -0,0 +1,145 @@ +//===-- ConstantHandling.h - Stuff for manipulating constants ----*- C++ -*--=// +// +// This file contains the declarations of some cool operators that allow you +// to do natural things with constant pool values. +// +// Unfortunately we can't overload operators on pointer types (like this:) +// +// inline bool operator==(const ConstPoolVal *V1, const ConstPoolVal *V2) +// +// so we must make due with references, even though it leads to some butt ugly +// looking code downstream. *sigh* (ex: ConstPoolVal *Result = *V1 + *v2; ) +// +//===----------------------------------------------------------------------===// +// +// WARNING: These operators return pointers to newly 'new'd objects. You MUST +// make sure to free them if you don't want them hanging around. Also, +// note that these may return a null object if I don't know how to +// perform those operations on the specified constant types. +// +//===----------------------------------------------------------------------===// +// +// Implementation notes: +// This library is implemented this way for a reason: In most cases, we do +// not want to have to link the constant mucking code into an executable. +// We do, however want to tie some of this into the main type system, as an +// optional component. By using a mutable cache member in the Type class, we +// get exactly the kind of behavior we want. +// +// In the end, we get performance almost exactly the same as having a virtual +// function dispatch, but we don't have to put our virtual functions into the +// "Type" class, and we can implement functionality with templates. Good deal. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OPT_CONSTANTHANDLING_H +#define LLVM_OPT_CONSTANTHANDLING_H + +#include "llvm/ConstPoolVals.h" +#include "llvm/Type.h" + +//===----------------------------------------------------------------------===// +// Implement == directly... +//===----------------------------------------------------------------------===// + +inline ConstPoolBool *operator==(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return new ConstPoolBool(V1.equals(&V2)); +} + +//===----------------------------------------------------------------------===// +// Implement all other operators indirectly through TypeRules system +//===----------------------------------------------------------------------===// + +class ConstRules { +protected: + inline ConstRules() {} // Can only be subclassed... +public: + // Unary Operators... + virtual ConstPoolVal *neg(const ConstPoolVal *V) const = 0; + virtual ConstPoolVal *not(const ConstPoolVal *V) const = 0; + + // Binary Operators... + virtual ConstPoolVal *add(const ConstPoolVal *V1, + const ConstPoolVal *V2) const = 0; + virtual ConstPoolVal *sub(const ConstPoolVal *V1, + const ConstPoolVal *V2) const = 0; + + virtual ConstPoolBool *lessthan(const ConstPoolVal *V1, + const ConstPoolVal *V2) const = 0; + + // ConstRules::get - A type will cache its own type rules if one is needed... + // we just want to make sure to hit the cache instead of doing it indirectly, + // if possible... + // + static inline const ConstRules *get(const ConstPoolVal &V) { + const ConstRules *Result = V.getType()->getConstRules(); + return Result ? Result : find(V.getType()); + } +private : + static const ConstRules *find(const Type *Ty); + + ConstRules(const ConstRules &); // Do not implement + ConstRules &operator=(const ConstRules &); // Do not implement +}; + + +inline ConstPoolVal *operator-(const ConstPoolVal &V) { + return ConstRules::get(V)->neg(&V); +} + +inline ConstPoolVal *operator!(const ConstPoolVal &V) { + return ConstRules::get(V)->not(&V); +} + + + +inline ConstPoolVal *operator+(const ConstPoolVal &V1, const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return ConstRules::get(V1)->add(&V1, &V2); +} + +inline ConstPoolVal *operator-(const ConstPoolVal &V1, const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return ConstRules::get(V1)->sub(&V1, &V2); +} + +inline ConstPoolBool *operator<(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return ConstRules::get(V1)->lessthan(&V1, &V2); +} + + +//===----------------------------------------------------------------------===// +// Implement 'derived' operators based on what we already have... +//===----------------------------------------------------------------------===// + +inline ConstPoolBool *operator>(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + return V2 < V1; +} + +inline ConstPoolBool *operator!=(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + ConstPoolBool *Result = V1 == V2; + Result->setValue(!Result->getValue()); // Invert value + return Result; // !(V1 == V2) +} + +inline ConstPoolBool *operator>=(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + ConstPoolBool *Result = V1 < V2; + Result->setValue(!Result->getValue()); // Invert value + return Result; // !(V1 < V2) +} + +inline ConstPoolBool *operator<=(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + ConstPoolBool *Result = V1 > V2; + Result->setValue(!Result->getValue()); // Invert value + return Result; // !(V1 > V2) +} + +#endif diff --git a/lib/VMCore/ConstantFolding.h b/lib/VMCore/ConstantFolding.h new file mode 100644 index 0000000..3227e39 --- /dev/null +++ b/lib/VMCore/ConstantFolding.h @@ -0,0 +1,145 @@ +//===-- ConstantHandling.h - Stuff for manipulating constants ----*- C++ -*--=// +// +// This file contains the declarations of some cool operators that allow you +// to do natural things with constant pool values. +// +// Unfortunately we can't overload operators on pointer types (like this:) +// +// inline bool operator==(const ConstPoolVal *V1, const ConstPoolVal *V2) +// +// so we must make due with references, even though it leads to some butt ugly +// looking code downstream. *sigh* (ex: ConstPoolVal *Result = *V1 + *v2; ) +// +//===----------------------------------------------------------------------===// +// +// WARNING: These operators return pointers to newly 'new'd objects. You MUST +// make sure to free them if you don't want them hanging around. Also, +// note that these may return a null object if I don't know how to +// perform those operations on the specified constant types. +// +//===----------------------------------------------------------------------===// +// +// Implementation notes: +// This library is implemented this way for a reason: In most cases, we do +// not want to have to link the constant mucking code into an executable. +// We do, however want to tie some of this into the main type system, as an +// optional component. By using a mutable cache member in the Type class, we +// get exactly the kind of behavior we want. +// +// In the end, we get performance almost exactly the same as having a virtual +// function dispatch, but we don't have to put our virtual functions into the +// "Type" class, and we can implement functionality with templates. Good deal. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OPT_CONSTANTHANDLING_H +#define LLVM_OPT_CONSTANTHANDLING_H + +#include "llvm/ConstPoolVals.h" +#include "llvm/Type.h" + +//===----------------------------------------------------------------------===// +// Implement == directly... +//===----------------------------------------------------------------------===// + +inline ConstPoolBool *operator==(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return new ConstPoolBool(V1.equals(&V2)); +} + +//===----------------------------------------------------------------------===// +// Implement all other operators indirectly through TypeRules system +//===----------------------------------------------------------------------===// + +class ConstRules { +protected: + inline ConstRules() {} // Can only be subclassed... +public: + // Unary Operators... + virtual ConstPoolVal *neg(const ConstPoolVal *V) const = 0; + virtual ConstPoolVal *not(const ConstPoolVal *V) const = 0; + + // Binary Operators... + virtual ConstPoolVal *add(const ConstPoolVal *V1, + const ConstPoolVal *V2) const = 0; + virtual ConstPoolVal *sub(const ConstPoolVal *V1, + const ConstPoolVal *V2) const = 0; + + virtual ConstPoolBool *lessthan(const ConstPoolVal *V1, + const ConstPoolVal *V2) const = 0; + + // ConstRules::get - A type will cache its own type rules if one is needed... + // we just want to make sure to hit the cache instead of doing it indirectly, + // if possible... + // + static inline const ConstRules *get(const ConstPoolVal &V) { + const ConstRules *Result = V.getType()->getConstRules(); + return Result ? Result : find(V.getType()); + } +private : + static const ConstRules *find(const Type *Ty); + + ConstRules(const ConstRules &); // Do not implement + ConstRules &operator=(const ConstRules &); // Do not implement +}; + + +inline ConstPoolVal *operator-(const ConstPoolVal &V) { + return ConstRules::get(V)->neg(&V); +} + +inline ConstPoolVal *operator!(const ConstPoolVal &V) { + return ConstRules::get(V)->not(&V); +} + + + +inline ConstPoolVal *operator+(const ConstPoolVal &V1, const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return ConstRules::get(V1)->add(&V1, &V2); +} + +inline ConstPoolVal *operator-(const ConstPoolVal &V1, const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return ConstRules::get(V1)->sub(&V1, &V2); +} + +inline ConstPoolBool *operator<(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + assert(V1.getType() == V2.getType() && "Constant types must be identical!"); + return ConstRules::get(V1)->lessthan(&V1, &V2); +} + + +//===----------------------------------------------------------------------===// +// Implement 'derived' operators based on what we already have... +//===----------------------------------------------------------------------===// + +inline ConstPoolBool *operator>(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + return V2 < V1; +} + +inline ConstPoolBool *operator!=(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + ConstPoolBool *Result = V1 == V2; + Result->setValue(!Result->getValue()); // Invert value + return Result; // !(V1 == V2) +} + +inline ConstPoolBool *operator>=(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + ConstPoolBool *Result = V1 < V2; + Result->setValue(!Result->getValue()); // Invert value + return Result; // !(V1 < V2) +} + +inline ConstPoolBool *operator<=(const ConstPoolVal &V1, + const ConstPoolVal &V2) { + ConstPoolBool *Result = V1 > V2; + Result->setValue(!Result->getValue()); // Invert value + return Result; // !(V1 > V2) +} + +#endif diff --git a/lib/VMCore/ConstantPool.cpp b/lib/VMCore/ConstantPool.cpp new file mode 100644 index 0000000..d624c8d --- /dev/null +++ b/lib/VMCore/ConstantPool.cpp @@ -0,0 +1,434 @@ +//===-- iConstPool.cpp - Implement ConstPool instructions --------*- C++ -*--=// +// +// This file implements the ConstPool* classes... +// +//===----------------------------------------------------------------------===// + +#define __STDC_LIMIT_MACROS // Get defs for INT64_MAX and friends... +#include "llvm/ConstPoolVals.h" +#include "llvm/ConstantPool.h" +#include "llvm/Tools/StringExtras.h" // itostr +#include "llvm/DerivedTypes.h" +#include "llvm/SymbolTable.h" +#include <algorithm> +#include <assert.h> + +//===----------------------------------------------------------------------===// +// ConstantPool Class +//===----------------------------------------------------------------------===// + +void ConstantPool::setParent(SymTabValue *STV) { + Parent = STV; + for (unsigned i = 0; i < Planes.size(); i++) + Planes[i]->setParent(Parent); +} + +// Constant getPlane - Returns true if the type plane does not exist, otherwise +// updates the pointer to point to the correct plane. +// +bool ConstantPool::getPlane(const Type *T, const PlaneType *&Plane) const { + unsigned Ty = T->getUniqueID(); + if (Ty >= Planes.size()) return true; + Plane = Planes[Ty]; + return false; +} + +// Constant getPlane - Returns true if the type plane does not exist, otherwise +// updates the pointer to point to the correct plane. +// +bool ConstantPool::getPlane(const Type *T, PlaneType *&Plane) { + unsigned Ty = T->getUniqueID(); + if (Ty >= Planes.size()) return true; + Plane = Planes[Ty]; + return false; +} + +void ConstantPool::resize(unsigned size) { + unsigned oldSize = Planes.size(); + Planes.resize(size, 0); + while (oldSize < size) + Planes[oldSize++] = new PlaneType(Parent, Parent); +} + +ConstantPool::PlaneType &ConstantPool::getPlane(const Type *T) { + unsigned Ty = T->getUniqueID(); + if (Ty >= Planes.size()) resize(Ty+1); + return *Planes[Ty]; +} + +// insert - Add constant into the symbol table... +void ConstantPool::insert(ConstPoolVal *N) { + unsigned Ty = N->getType()->getUniqueID(); + if (Ty >= Planes.size()) resize(Ty+1); + Planes[Ty]->push_back(N); +} + +bool ConstantPool::remove(ConstPoolVal *N) { + unsigned Ty = N->getType()->getUniqueID(); + if (Ty >= Planes.size()) return true; // Doesn't contain any of that type + + PlaneType::iterator I = ::find(Planes[Ty]->begin(), Planes[Ty]->end(), N); + if (I == Planes[Ty]->end()) return true; + Planes[Ty]->remove(I); + return false; +} + +void ConstantPool::delete_all() { + dropAllReferences(); + for (unsigned i = 0; i < Planes.size(); i++) { + Planes[i]->delete_all(); + Planes[i]->setParent(0); + delete Planes[i]; + } + Planes.clear(); +} + +void ConstantPool::dropAllReferences() { + for (unsigned i = 0; i < Planes.size(); i++) + for (PlaneType::iterator I = Planes[i]->begin(); + I != Planes[i]->end(); I++) + (*I)->dropAllReferences(); +} + +struct EqualsConstant { + const ConstPoolVal *v; + inline EqualsConstant(const ConstPoolVal *V) { v = V; } + inline bool operator()(const ConstPoolVal *V) const { + return v->equals(V); + } +}; + + +ConstPoolVal *ConstantPool::find(const ConstPoolVal *V) { + const PlaneType *P; + if (getPlane(V->getType(), P)) return 0; + PlaneType::const_iterator PI = find_if(P->begin(), P->end(), + EqualsConstant(V)); + if (PI == P->end()) return 0; + return *PI; +} + +const ConstPoolVal *ConstantPool::find(const ConstPoolVal *V) const { + const PlaneType *P; + if (getPlane(V->getType(), P)) return 0; + PlaneType::const_iterator PI = find_if(P->begin(), P->end(), + EqualsConstant(V)); + if (PI == P->end()) return 0; + return *PI; +} + +ConstPoolVal *ConstantPool::find(const Type *Ty) { + const PlaneType *P; + if (getPlane(Type::TypeTy, P)) return 0; + + // TODO: This is kinda silly + ConstPoolType V(Ty); + + PlaneType::const_iterator PI = + find_if(P->begin(), P->end(), EqualsConstant(&V)); + if (PI == P->end()) return 0; + return *PI; +} + +const ConstPoolVal *ConstantPool::find(const Type *Ty) const { + const PlaneType *P; + if (getPlane(Type::TypeTy, P)) return 0; + + // TODO: This is kinda silly + ConstPoolType V(Ty); + + PlaneType::const_iterator PI = + find_if(P->begin(), P->end(), EqualsConstant(&V)); + if (PI == P->end()) return 0; + return *PI; +} + +//===----------------------------------------------------------------------===// +// ConstPoolVal Class +//===----------------------------------------------------------------------===// + +// Specialize setName to take care of symbol table majik +void ConstPoolVal::setName(const string &name) { + SymTabValue *P; + if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this); + Value::setName(name); + if (P && hasName()) P->getSymbolTable()->insert(this); +} + +// Static constructor to create a '0' constant of arbitrary type... +ConstPoolVal *ConstPoolVal::getNullConstant(const Type *Ty) { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: return new ConstPoolBool(false); + case Type::SByteTyID: + case Type::ShortTyID: + case Type::IntTyID: + case Type::LongTyID: return new ConstPoolSInt(Ty, 0); + + case Type::UByteTyID: + case Type::UShortTyID: + case Type::UIntTyID: + case Type::ULongTyID: return new ConstPoolUInt(Ty, 0); + + case Type::FloatTyID: + case Type::DoubleTyID: return new ConstPoolFP(Ty, 0); + default: + return 0; + } +} + + + +//===----------------------------------------------------------------------===// +// ConstPoolXXX Classes +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Normal Constructors + +ConstPoolBool::ConstPoolBool(bool V, const string &Name = "") + : ConstPoolVal(Type::BoolTy, Name) { + Val = V; +} + +ConstPoolSInt::ConstPoolSInt(const Type *Ty, int64_t V, const string &Name) + : ConstPoolVal(Ty, Name) { + //cerr << "value = " << (int)V << ": " << Ty->getName() << endl; + assert(isValueValidForType(Ty, V) && "Value to large for type!"); + Val = V; +} + +ConstPoolUInt::ConstPoolUInt(const Type *Ty, uint64_t V, const string &Name) + : ConstPoolVal(Ty, Name) { + //cerr << "Uvalue = " << (int)V << ": " << Ty->getName() << endl; + assert(isValueValidForType(Ty, V) && "Value to large for type!"); + Val = V; +} + +ConstPoolFP::ConstPoolFP(const Type *Ty, double V, const string &Name) + : ConstPoolVal(Ty, Name) { + assert(isValueValidForType(Ty, V) && "Value to large for type!"); + Val = V; +} + +ConstPoolType::ConstPoolType(const Type *V, const string &Name) + : ConstPoolVal(Type::TypeTy, Name), Val(V) { +} + +ConstPoolArray::ConstPoolArray(const ArrayType *T, + vector<ConstPoolVal*> &V, + const string &Name) + : ConstPoolVal(T, Name) { + for (unsigned i = 0; i < V.size(); i++) { + assert(V[i]->getType() == T->getElementType()); + Val.push_back(ConstPoolUse(V[i], this)); + } +} + +ConstPoolStruct::ConstPoolStruct(const StructType *T, + vector<ConstPoolVal*> &V, + const string &Name) + : ConstPoolVal(T, Name) { + const StructType::ElementTypes &ETypes = T->getElementTypes(); + + for (unsigned i = 0; i < V.size(); i++) { + assert(V[i]->getType() == ETypes[i]); + Val.push_back(ConstPoolUse(V[i], this)); + } +} + + +//===----------------------------------------------------------------------===// +// Copy Constructors + +ConstPoolBool::ConstPoolBool(const ConstPoolBool &CPB) + : ConstPoolVal(Type::BoolTy) { + Val = CPB.Val; +} + +ConstPoolSInt::ConstPoolSInt(const ConstPoolSInt &CPSI) + : ConstPoolVal(CPSI.getType()) { + Val = CPSI.Val; +} + +ConstPoolUInt::ConstPoolUInt(const ConstPoolUInt &CPUI) + : ConstPoolVal(CPUI.getType()) { + Val = CPUI.Val; +} + +ConstPoolFP::ConstPoolFP(const ConstPoolFP &CPFP) + : ConstPoolVal(CPFP.getType()) { + Val = CPFP.Val; +} + +ConstPoolType::ConstPoolType(const ConstPoolType &CPT) + : ConstPoolVal(Type::TypeTy), Val(CPT.Val) { +} + +ConstPoolArray::ConstPoolArray(const ConstPoolArray &CPA) + : ConstPoolVal(CPA.getType()) { + for (unsigned i = 0; i < CPA.Val.size(); i++) + Val.push_back(ConstPoolUse((ConstPoolVal*)CPA.Val[i], this)); +} + +ConstPoolStruct::ConstPoolStruct(const ConstPoolStruct &CPS) + : ConstPoolVal(CPS.getType()) { + for (unsigned i = 0; i < CPS.Val.size(); i++) + Val.push_back(ConstPoolUse((ConstPoolVal*)CPS.Val[i], this)); +} + +//===----------------------------------------------------------------------===// +// getStrValue implementations + +string ConstPoolBool::getStrValue() const { + if (Val) + return "true"; + else + return "false"; +} + +string ConstPoolSInt::getStrValue() const { + return itostr(Val); +} + +string ConstPoolUInt::getStrValue() const { + return utostr(Val); +} + +string ConstPoolFP::getStrValue() const { + assert(0 && "FP Constants Not implemented yet!!!!!!!!!!!"); + return "% FP Constants NI!" /* + dtostr(Val)*/; +} + +string ConstPoolType::getStrValue() const { + return Val->getName(); +} + +string ConstPoolArray::getStrValue() const { + string Result = "["; + if (Val.size()) { + Result += " " + Val[0]->getType()->getName() + + " " + Val[0]->getStrValue(); + for (unsigned i = 1; i < Val.size(); i++) + Result += ", " + Val[i]->getType()->getName() + + " " + Val[i]->getStrValue(); + } + + return Result + " ]"; +} + +string ConstPoolStruct::getStrValue() const { + string Result = "{"; + if (Val.size()) { + Result += " " + Val[0]->getType()->getName() + + " " + Val[0]->getStrValue(); + for (unsigned i = 1; i < Val.size(); i++) + Result += ", " + Val[i]->getType()->getName() + + " " + Val[i]->getStrValue(); + } + + return Result + " }"; +} + +//===----------------------------------------------------------------------===// +// equals implementations + +bool ConstPoolBool::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + return ((ConstPoolBool*)V)->getValue() == Val; +} + +bool ConstPoolSInt::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + return ((ConstPoolSInt*)V)->getValue() == Val; +} + +bool ConstPoolUInt::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + return ((ConstPoolUInt*)V)->getValue() == Val; +} + +bool ConstPoolFP::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + return ((ConstPoolFP*)V)->getValue() == Val; +} + +bool ConstPoolType::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + return ((ConstPoolType*)V)->getValue() == Val; +} + +bool ConstPoolArray::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + ConstPoolArray *AV = (ConstPoolArray*)V; + if (Val.size() != AV->Val.size()) return false; + for (unsigned i = 0; i < Val.size(); i++) + if (!Val[i]->equals(AV->Val[i])) return false; + + return true; +} + +bool ConstPoolStruct::equals(const ConstPoolVal *V) const { + assert(getType() == V->getType()); + ConstPoolStruct *SV = (ConstPoolStruct*)V; + if (Val.size() != SV->Val.size()) return false; + for (unsigned i = 0; i < Val.size(); i++) + if (!Val[i]->equals(SV->Val[i])) return false; + + return true; +} + +//===----------------------------------------------------------------------===// +// isValueValidForType implementations + +bool ConstPoolSInt::isValueValidForType(const Type *Ty, int64_t Val) { + switch (Ty->getPrimitiveID()) { + default: + return false; // These can't be represented as integers!!! + + // Signed types... + case Type::SByteTyID: + return (Val <= INT8_MAX && Val >= INT8_MIN); + case Type::ShortTyID: + return (Val <= INT16_MAX && Val >= INT16_MIN); + case Type::IntTyID: + return (Val <= INT32_MAX && Val >= INT32_MIN); + case Type::LongTyID: + return true; // This is the largest type... + } + assert(0 && "WTF?"); + return false; +} + +bool ConstPoolUInt::isValueValidForType(const Type *Ty, uint64_t Val) { + switch (Ty->getPrimitiveID()) { + default: + return false; // These can't be represented as integers!!! + + // Unsigned types... + case Type::UByteTyID: + return (Val <= UINT8_MAX); + case Type::UShortTyID: + return (Val <= UINT16_MAX); + case Type::UIntTyID: + return (Val <= UINT32_MAX); + case Type::ULongTyID: + return true; // This is the largest type... + } + assert(0 && "WTF?"); + return false; +} + +bool ConstPoolFP::isValueValidForType(const Type *Ty, double Val) { + switch (Ty->getPrimitiveID()) { + default: + return false; // These can't be represented as floating point! + + // TODO: Figure out how to test if a double can be cast to a float! + /* + case Type::FloatTyID: + return (Val <= UINT8_MAX); + */ + case Type::DoubleTyID: + return true; // This is the largest type... + } +}; diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp new file mode 100644 index 0000000..550c4f0 --- /dev/null +++ b/lib/VMCore/Function.cpp @@ -0,0 +1,75 @@ +//===-- Method.cpp - Implement the Method class ------------------*- C++ -*--=// +// +// This file implements the Method class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ValueHolderImpl.h" +#include "llvm/DerivedTypes.h" +#include "llvm/SymbolTable.h" +#include "llvm/Module.h" +#include "llvm/Method.h" +#include "llvm/BasicBlock.h" +#include "llvm/iOther.h" + +// Instantiate Templates - This ugliness is the price we have to pay +// for having a ValueHolderImpl.h file seperate from ValueHolder.h! :( +// +template class ValueHolder<MethodArgument, Method>; +template class ValueHolder<BasicBlock , Method>; + +Method::Method(const MethodType *Ty, const string &name) + : SymTabValue(Ty, Value::MethodVal, name), BasicBlocks(this), + ArgumentList(this, this) { + assert(Ty->isMethodType() && "Method signature must be of method type!"); + Parent = 0; +} + +Method::~Method() { + dropAllReferences(); // After this it is safe to delete instructions. + + // TODO: Should remove from the end, not the beginning of vector! + BasicBlocksType::iterator BI = BasicBlocks.begin(); + while ((BI = BasicBlocks.begin()) != BasicBlocks.end()) + delete BasicBlocks.remove(BI); + + // Delete all of the method arguments and unlink from symbol table... + ArgumentList.delete_all(); + ArgumentList.setParent(0); +} + +// Specialize setName to take care of symbol table majik +void Method::setName(const string &name) { + Module *P; + if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this); + Value::setName(name); + if (P && getName() != "") P->getSymbolTableSure()->insert(this); +} + +void Method::setParent(Module *parent) { + Parent = parent; + + // Relink symbol tables together... + setParentSymTab(Parent ? Parent->getSymbolTableSure() : 0); +} + +const Type *Method::getReturnType() const { + return ((const MethodType *)getType())->getReturnType(); +} + +const MethodType *Method::getMethodType() const { + return (const MethodType *)getType(); +} + +// 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 +// references... first all references are dropped, and all use counts go to +// zero. Then everything is delete'd for real. Note that no operations are +// valid on an object that has "dropped all references", except operator +// delete. +// +void Method::dropAllReferences() { + for_each(BasicBlocks.begin(), BasicBlocks.end(), + std::mem_fun(&BasicBlock::dropAllReferences)); +} diff --git a/lib/VMCore/InstrTypes.cpp b/lib/VMCore/InstrTypes.cpp new file mode 100644 index 0000000..29b293f --- /dev/null +++ b/lib/VMCore/InstrTypes.cpp @@ -0,0 +1,66 @@ +//===-- InstrTypes.cpp - Implement Instruction subclasses --------*- C++ -*--=// +// +// This file implements +// +//===----------------------------------------------------------------------===// + +#include "llvm/iOther.h" +#include "llvm/BasicBlock.h" +#include "llvm/Method.h" +#include "llvm/SymbolTable.h" +#include "llvm/Type.h" +#include <algorithm> + +//===----------------------------------------------------------------------===// +// TerminatorInst Class +//===----------------------------------------------------------------------===// + +TerminatorInst::TerminatorInst(unsigned iType) + : Instruction(Type::VoidTy, iType, "") { +} + + +//===----------------------------------------------------------------------===// +// MethodArgument Class +//===----------------------------------------------------------------------===// + +// Specialize setName to take care of symbol table majik +void MethodArgument::setName(const string &name) { + Method *P; + if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this); + Value::setName(name); + if (P && hasName()) P->getSymbolTable()->insert(this); +} + + +//===----------------------------------------------------------------------===// +// PHINode Class +//===----------------------------------------------------------------------===// + +PHINode::PHINode(const Type *Ty, const string &name) + : Instruction(Ty, Instruction::PHINode, name) { +} + +PHINode::PHINode(const PHINode &PN) + : Instruction(PN.getType(), Instruction::PHINode) { + + for (unsigned i = 0; i < PN.IncomingValues.size(); i++) + IncomingValues.push_back(Use(PN.IncomingValues[i], this)); +} + +void PHINode::dropAllReferences() { + IncomingValues.clear(); +} + +bool PHINode::setOperand(unsigned i, Value *Val) { + assert(Val && "PHI node must only reference nonnull definitions!"); + if (i >= IncomingValues.size()) return false; + + IncomingValues[i] = Val; + return true; +} + +void PHINode::addIncoming(Value *D) { + IncomingValues.push_back(Use(D, this)); +} + diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp new file mode 100644 index 0000000..4b528f0 --- /dev/null +++ b/lib/VMCore/Instruction.cpp @@ -0,0 +1,61 @@ +//===-- Instruction.cpp - Implement the Instruction class --------*- C++ -*--=// +// +// This file implements the Instruction class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Instruction.h" +#include "llvm/BasicBlock.h" +#include "llvm/Method.h" +#include "llvm/SymbolTable.h" +#include "llvm/iBinary.h" +#include "llvm/iUnary.h" + +Instruction::Instruction(const Type *ty, unsigned it, const string &Name) + : User(ty, Value::InstructionVal, Name) { + Parent = 0; + iType = it; +} + +Instruction::~Instruction() { + assert(getParent() == 0 && "Instruction still embeded in basic block!"); +} + +// Specialize setName to take care of symbol table majik +void Instruction::setName(const string &name) { + BasicBlock *P = 0; Method *PP = 0; + if ((P = getParent()) && (PP = P->getParent()) && hasName()) + PP->getSymbolTable()->remove(this); + Value::setName(name); + if (PP && hasName()) PP->getSymbolTableSure()->insert(this); +} + +Instruction *Instruction::getBinaryOperator(unsigned Op, Value *S1, Value *S2) { + switch (Op) { + case Add: + return new AddInst(S1, S2); + case Sub: + return new SubInst(S1, S2); + + case SetLT: + case SetGT: + case SetLE: + case SetGE: + case SetEQ: + case SetNE: + return new SetCondInst((BinaryOps)Op, S1, S2); + + default: + cerr << "Don't know how to GetBinaryOperator " << Op << endl; + return 0; + } +} + + +Instruction *Instruction::getUnaryOperator(unsigned Op, Value *Source) { + switch (Op) { + default: + cerr << "Don't know how to GetUnaryOperator " << Op << endl; + return 0; + } +} diff --git a/lib/VMCore/Makefile b/lib/VMCore/Makefile new file mode 100644 index 0000000..7d1289c --- /dev/null +++ b/lib/VMCore/Makefile @@ -0,0 +1,7 @@ + +LEVEL = ../.. + +LIBRARYNAME = vmcore + +include $(LEVEL)/Makefile.common + diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp new file mode 100644 index 0000000..4f2eee4 --- /dev/null +++ b/lib/VMCore/Module.cpp @@ -0,0 +1,42 @@ +//===-- Module.cpp - Implement the Module class ------------------*- C++ -*--=// +// +// This file implements the Module class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ValueHolderImpl.h" +#include "llvm/InstrTypes.h" +#include "llvm/BasicBlock.h" +#include "llvm/Method.h" +#include "llvm/Module.h" + +// Instantiate Templates - This ugliness is the price we have to pay +// for having a DefHolderImpl.h file seperate from DefHolder.h! :( +// +template class ValueHolder<Method, Module>; + +Module::Module() + : SymTabValue(0/*TODO: REAL TYPE*/, Value::ModuleVal, ""), + MethodList(this, this) { +} + +Module::~Module() { + dropAllReferences(); + MethodList.delete_all(); + MethodList.setParent(0); +} + + +// 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 +// references... first all references are dropped, and all use counts go to +// zero. Then everything is delete'd for real. Note that no operations are +// valid on an object that has "dropped all references", except operator +// delete. +// +void Module::dropAllReferences() { + MethodListType::iterator MI = MethodList.begin(); + for (; MI != MethodList.end(); MI++) + (*MI)->dropAllReferences(); +} diff --git a/lib/VMCore/SlotCalculator.cpp b/lib/VMCore/SlotCalculator.cpp new file mode 100644 index 0000000..01fae37 --- /dev/null +++ b/lib/VMCore/SlotCalculator.cpp @@ -0,0 +1,195 @@ +//===-- SlotCalculator.cpp - Calculate what slots values land in ------------=// +// +// This file implements a useful analysis step to figure out what numbered +// slots values in a program will land in (keeping track of per plane +// information as required. +// +// This is used primarily for when writing a file to disk, either in bytecode +// or source format. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/SlotCalculator.h" +#include "llvm/ConstantPool.h" +#include "llvm/Method.h" +#include "llvm/Module.h" +#include "llvm/BasicBlock.h" +#include "llvm/ConstPoolVals.h" +#include "llvm/iOther.h" +#include "llvm/DerivedTypes.h" + +SlotCalculator::SlotCalculator(const Module *M, bool IgnoreNamed) { + IgnoreNamedNodes = IgnoreNamed; + TheModule = M; + + // Preload table... Make sure that all of the primitive types are in the table + // and that their Primitive ID is equal to their slot # + // + for (unsigned i = 0; i < Type::FirstDerivedTyID; ++i) { + assert(Type::getPrimitiveType((Type::PrimitiveID)i)); + insertVal(Type::getPrimitiveType((Type::PrimitiveID)i)); + } + + if (M == 0) return; // Empty table... + + bool Result = processModule(M); + assert(Result == false && "Error in processModule!"); +} + +SlotCalculator::SlotCalculator(const Method *M, bool IgnoreNamed) { + IgnoreNamedNodes = IgnoreNamed; + TheModule = M ? M->getParent() : 0; + + // Preload table... Make sure that all of the primitive types are in the table + // and that their Primitive ID is equal to their slot # + // + for (unsigned i = 0; i < Type::FirstDerivedTyID; ++i) { + assert(Type::getPrimitiveType((Type::PrimitiveID)i)); + insertVal(Type::getPrimitiveType((Type::PrimitiveID)i)); + } + + if (TheModule == 0) return; // Empty table... + + bool Result = processModule(TheModule); + assert(Result == false && "Error in processModule!"); + + incorporateMethod(M); +} + +void SlotCalculator::incorporateMethod(const Method *M) { + assert(ModuleLevel.size() == 0 && "Module already incorporated!"); + + // Save the Table state before we process the method... + for (unsigned i = 0; i < Table.size(); ++i) { + ModuleLevel.push_back(Table[i].size()); + } + + // Process the method to incorporate its values into our table + processMethod(M); +} + +void SlotCalculator::purgeMethod() { + assert(ModuleLevel.size() != 0 && "Module not incorporated!"); + unsigned NumModuleTypes = ModuleLevel.size(); + + // First, remove values from existing type planes + for (unsigned i = 0; i < NumModuleTypes; ++i) { + unsigned ModuleSize = ModuleLevel[i]; // Size of plane before method came + while (Table[i].size() != ModuleSize) { + NodeMap.erase(NodeMap.find(Table[i].back())); // Erase from nodemap + Table[i].pop_back(); // Shrink plane + } + } + + // We don't need this state anymore, free it up. + ModuleLevel.clear(); + + // Next, remove any type planes defined by the method... + while (NumModuleTypes != Table.size()) { + TypePlane &Plane = Table.back(); + while (Plane.size()) { + NodeMap.erase(NodeMap.find(Plane.back())); // Erase from nodemap + Plane.pop_back(); // Shrink plane + } + + Table.pop_back(); // Nuke the plane, we don't like it. + } +} + +bool SlotCalculator::processConstant(const ConstPoolVal *CPV) { + //cerr << "Inserting constant: '" << CPV->getStrValue() << endl; + insertVal(CPV); + return false; +} + +// processType - This callback occurs when an derived type is discovered +// at the class level. This activity occurs when processing a constant pool. +// +bool SlotCalculator::processType(const Type *Ty) { + //cerr << "processType: " << Ty->getName() << endl; + // TODO: Don't leak memory!!! Free this in the dtor! + insertVal(new ConstPoolType(Ty)); + return false; +} + +bool SlotCalculator::visitMethod(const Method *M) { + //cerr << "visitMethod: '" << M->getType()->getName() << "'\n"; + insertVal(M); + return false; +} + +bool SlotCalculator::processMethodArgument(const MethodArgument *MA) { + insertVal(MA); + return false; +} + +bool SlotCalculator::processBasicBlock(const BasicBlock *BB) { + insertVal(BB); + ModuleAnalyzer::processBasicBlock(BB); // Lets visit the instructions too! + return false; +} + +bool SlotCalculator::processInstruction(const Instruction *I) { + insertVal(I); + return false; +} + +int SlotCalculator::getValSlot(const Value *D) const { + map<const Value*, unsigned>::const_iterator I = NodeMap.find(D); + if (I == NodeMap.end()) return -1; + + return (int)I->second; +} + +void SlotCalculator::insertVal(const Value *D) { + if (D == 0) return; + + // If this node does not contribute to a plane, or if the node has a + // name and we don't want names, then ignore the silly node... + // + if (D->getType() == Type::VoidTy || (IgnoreNamedNodes && D->hasName())) + return; + + const Type *Typ = D->getType(); + unsigned Ty = Typ->getPrimitiveID(); + if (Typ->isDerivedType()) { + int DefSlot = getValSlot(Typ); + if (DefSlot == -1) { // Have we already entered this type? + // This can happen if a type is first seen in an instruction. For + // example, if you say 'malloc uint', this defines a type 'uint*' that + // may be undefined at this point. + // + cerr << "SHOULDNT HAPPEN Adding Type ba: " << Typ->getName() << endl; + assert(0 && "SHouldn't this be taken care of by processType!?!?!"); + // Nope... add this to the Type plane now! + insertVal(Typ); + + DefSlot = getValSlot(Typ); + assert(DefSlot >= 0 && "Type didn't get inserted correctly!"); + } + Ty = (unsigned)DefSlot; + } + + if (Table.size() <= Ty) // Make sure we have the type plane allocated... + Table.resize(Ty+1, TypePlane()); + + // Insert node into table and NodeMap... + NodeMap[D] = Table[Ty].size(); + + if (Typ == Type::TypeTy && // If it's a type constant, add the Type also + D->getValueType() != Value::TypeVal) { + assert(D->getValueType() == Value::ConstantVal && + "All Type instances should be constant types!"); + + const ConstPoolType *CPT = (const ConstPoolType*)D; + int Slot = getValSlot(CPT->getValue()); + if (Slot == -1) { + // Only add if it's not already here! + NodeMap[CPT->getValue()] = Table[Ty].size(); + } else if (!CPT->hasName()) { // If the type has no name... + NodeMap[D] = (unsigned)Slot; // Don't readd type, merge. + return; + } + } + Table[Ty].push_back(D); +} diff --git a/lib/VMCore/SymbolTable.cpp b/lib/VMCore/SymbolTable.cpp new file mode 100644 index 0000000..395c23f --- /dev/null +++ b/lib/VMCore/SymbolTable.cpp @@ -0,0 +1,106 @@ +//===-- SymbolTable.cpp - Implement the SymbolTable class -------------------=// +// +// This file implements the SymbolTable class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/SymbolTable.h" +#include "llvm/InstrTypes.h" +#ifndef NDEBUG +#include "llvm/BasicBlock.h" // Required for assertions to work. +#include "llvm/Type.h" +#endif + +SymbolTable::~SymbolTable() { +#ifndef NDEBUG // Only do this in -g mode... + bool Good = true; + for (iterator i = begin(); i != end(); i++) { + if (i->second.begin() != i->second.end()) { + for (type_iterator I = i->second.begin(); I != i->second.end(); I++) + cerr << "Value still in symbol table! Type = " << i->first->getName() + << " Name = " << I->first << endl; + Good = false; + } + } + assert(Good && "Values remain in symbol table!"); +#endif +} + +SymbolTable::type_iterator SymbolTable::type_find(const Value *D) { + assert(D->hasName() && "type_find(Value*) only works on named nodes!"); + return type_find(D->getType(), D->getName()); +} + + +// find - returns end(Ty->getIDNumber()) on failure... +SymbolTable::type_iterator SymbolTable::type_find(const Type *Ty, + const string &Name) { + iterator I = find(Ty); + if (I == end()) { // Not in collection yet... insert dummy entry + (*this)[Ty] = VarMap(); + I = find(Ty); + assert(I != end() && "How did insert fail?"); + } + + return I->second.find(Name); +} + + +// lookup - Returns null on failure... +Value *SymbolTable::lookup(const Type *Ty, const string &Name) { + iterator I = find(Ty); + if (I != end()) { // We have symbols in that plane... + type_iterator J = I->second.find(Name); + if (J != I->second.end()) // and the name is in our hash table... + return J->second; + } + + return ParentSymTab ? ParentSymTab->lookup(Ty, Name) : 0; +} + +void SymbolTable::remove(Value *N) { + assert(N->hasName() && "Value doesn't have name!"); + assert(type_find(N) != type_end(N->getType()) && + "Value not in symbol table!"); + type_remove(type_find(N)); +} + + +#define DEBUG_SYMBOL_TABLE 0 + +Value *SymbolTable::type_remove(const type_iterator &It) { + Value *Result = It->second; +#if DEBUG_SYMBOL_TABLE + cerr << this << " Removing Value: " << Result->getName() << endl; +#endif + + find(Result->getType())->second.erase(It); + + return Result; +} + +void SymbolTable::insert(Value *N) { + assert(N->hasName() && "Value must be named to go into symbol table!"); + + // TODO: The typeverifier should catch this when its implemented + if (lookup(N->getType(), N->getName())) { + cerr << "SymbolTable WARNING: Name already in symbol table: '" + << N->getName() << "'\n"; + abort(); // TODO: REMOVE THIS + } + +#if DEBUG_SYMBOL_TABLE + cerr << this << " Inserting definition: " << N->getName() << ": " + << N->getType()->getName() << endl; +#endif + + iterator I = find(N->getType()); + if (I == end()) { // Not in collection yet... insert dummy entry + (*this)[N->getType()] = VarMap(); + I = find(N->getType()); + assert(I != end() && "How did insert fail?"); + } + + I->second.insert(make_pair(N->getName(), N)); +} + diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp new file mode 100644 index 0000000..cf16309 --- /dev/null +++ b/lib/VMCore/Type.cpp @@ -0,0 +1,308 @@ +//===-- Type.cpp - Implement the Type class ----------------------*- C++ -*--=// +// +// This file implements the Type class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DerivedTypes.h" +#include "llvm/Tools/StringExtras.h" + +//===----------------------------------------------------------------------===// +// Type Class Implementation +//===----------------------------------------------------------------------===// + +static unsigned CurUID = 0; +static vector<const Type *> UIDMappings; + +Type::Type(const string &name, PrimitiveID id) + : Value(Type::TypeTy, Value::TypeVal, name) { + ID = id; + ConstRulesImpl = 0; + + UID = CurUID++; // Assign types UID's as they are created + UIDMappings.push_back(this); +} + +const Type *Type::getUniqueIDType(unsigned UID) { + assert(UID < UIDMappings.size() && + "Type::getPrimitiveType: UID out of range!"); + return UIDMappings[UID]; +} + +const Type *Type::getPrimitiveType(PrimitiveID IDNumber) { + switch (IDNumber) { + case VoidTyID : return VoidTy; + case BoolTyID : return BoolTy; + case UByteTyID : return UByteTy; + case SByteTyID : return SByteTy; + case UShortTyID: return UShortTy; + case ShortTyID : return ShortTy; + case UIntTyID : return UIntTy; + case IntTyID : return IntTy; + case ULongTyID : return ULongTy; + case LongTyID : return LongTy; + case FloatTyID : return FloatTy; + case DoubleTyID: return DoubleTy; + case TypeTyID : return TypeTy; + case LabelTyID : return LabelTy; + case LockTyID : return LockTy; + case FillerTyID: return new Type("XXX FILLER XXX", FillerTyID); // TODO:KILLME + default: + return 0; + } +} + + + +//===----------------------------------------------------------------------===// +// Auxilliary classes +//===----------------------------------------------------------------------===// +// +// These classes are used to implement specialized behavior for each different +// type. +// +class SignedIntType : public Type { + int Size; +public: + SignedIntType(const string &Name, PrimitiveID id, int size) : Type(Name, id) { + Size = size; + } + + // isSigned - Return whether a numeric type is signed. + virtual bool isSigned() const { return 1; } +}; + +class UnsignedIntType : public Type { + uint64_t Size; +public: + UnsignedIntType(const string &N, PrimitiveID id, int size) : Type(N, id) { + Size = size; + } + + // isUnsigned - Return whether a numeric type is signed. + virtual bool isUnsigned() const { return 1; } +}; + +static struct TypeType : public Type { + TypeType() : Type("type", TypeTyID) {} +} TheTypeType; // Implement the type that is global. + + +//===----------------------------------------------------------------------===// +// Static 'Type' data +//===----------------------------------------------------------------------===// + +const Type *Type::VoidTy = new Type("void" , VoidTyID), + *Type::BoolTy = new Type("bool" , BoolTyID), + *Type::SByteTy = new SignedIntType("sbyte" , SByteTyID, 1), + *Type::UByteTy = new UnsignedIntType("ubyte" , UByteTyID, 1), + *Type::ShortTy = new SignedIntType("short" , ShortTyID, 2), + *Type::UShortTy = new UnsignedIntType("ushort", UShortTyID, 2), + *Type::IntTy = new SignedIntType("int" , IntTyID, 4), + *Type::UIntTy = new UnsignedIntType("uint" , UIntTyID, 4), + *Type::LongTy = new SignedIntType("long" , LongTyID, 8), + *Type::ULongTy = new UnsignedIntType("ulong" , ULongTyID, 8), + *Type::FloatTy = new Type("float" , FloatTyID), + *Type::DoubleTy = new Type("double", DoubleTyID), + *Type::TypeTy = &TheTypeType, + *Type::LabelTy = new Type("label" , LabelTyID), + *Type::LockTy = new Type("lock" , LockTyID); + + +//===----------------------------------------------------------------------===// +// Derived Type Implementations +//===----------------------------------------------------------------------===// + +// Make sure that only one instance of a particular type may be created on any +// given run of the compiler... +// +// TODO: This list should be kept in sorted order so that we can do a binary +// TODO: search instead of linear search! +// +// TODO: This should be templatized so that every derived type can use the same +// TODO: code! +// +#define TEST_MERGE_TYPES 0 + +#if TEST_MERGE_TYPES +#include "llvm/Assembly/Writer.h" +#endif + +//===----------------------------------------------------------------------===// +// Derived Type Constructors +//===----------------------------------------------------------------------===// + +MethodType::MethodType(const Type *Result, const vector<const Type*> &Params, + const string &Name) + : Type(Name, MethodTyID), ResultType(Result), ParamTys(Params) { +} + +ArrayType::ArrayType(const Type *ElType, int NumEl, const string &Name) + : Type(Name, ArrayTyID), ElementType(ElType) { + NumElements = NumEl; +} + +StructType::StructType(const vector<const Type*> &Types, const string &Name) + : Type(Name, StructTyID), ETypes(Types) { +} + +PointerType::PointerType(const Type *E) + : Type(E->getName() + " *", PointerTyID), ValueType(E) { +} + +//===----------------------------------------------------------------------===// +// Derived Type Creator Functions +//===----------------------------------------------------------------------===// + +const MethodType *MethodType::getMethodType(const Type *ReturnType, + const vector<const Type*> &Params) { + static vector<const MethodType*> ExistingMethodTypesCache; + for (unsigned i = 0; i < ExistingMethodTypesCache.size(); i++) { + const MethodType *T = ExistingMethodTypesCache[i]; + if (T->getReturnType() == ReturnType) { + const ParamTypes &EParams = T->getParamTypes(); + ParamTypes::const_iterator I = Params.begin(); + ParamTypes::const_iterator J = EParams.begin(); + for (; I != Params.end() && J != EParams.end(); I++, J++) + if (*I != *J) break; // These types aren't equal! + + if (I == Params.end() && J == EParams.end()) { +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Type: \""; + copy(Params.begin(), Params.end(), out); + cerr << "\"\nEquals: \""; + copy(EParams.begin(), EParams.end(), out); + cerr << "\"" << endl; +#endif + return T; + } + } + } +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Input Types: "; + copy(Params.begin(), Params.end(), out); + cerr << endl; +#endif + + // Calculate the string name for the new type... + string Name = ReturnType->getName() + " ("; + for (ParamTypes::const_iterator I = Params.begin(); + I != Params.end(); I++) { + if (I != Params.begin()) + Name += ", "; + Name += (*I)->getName(); + } + Name += ")"; + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Name << endl; +#endif + + MethodType *Result = new MethodType(ReturnType, Params, Name); + ExistingMethodTypesCache.push_back(Result); + return Result; +} + + +const ArrayType *ArrayType::getArrayType(const Type *ElementType, + int NumElements = -1) { + static vector<const ArrayType*> ExistingTypesCache; + + // Search cache for value... + for (unsigned i = 0; i < ExistingTypesCache.size(); i++) { + const ArrayType *T = ExistingTypesCache[i]; + + if (T->getElementType() == ElementType && + T->getNumElements() == NumElements) + return T; + } + + // Value not found. Derive a new type! + string Name = "["; + if (NumElements != -1) Name += itostr(NumElements) + " x "; + + Name += ElementType->getName(); + + ArrayType *Result = new ArrayType(ElementType, NumElements, Name + "]"); + ExistingTypesCache.push_back(Result); + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Result->getName() << endl; +#endif + return Result; +} + +const StructType *StructType::getStructType(const ElementTypes &ETypes) { + static vector<const StructType*> ExistingStructTypesCache; + + for (unsigned i = 0; i < ExistingStructTypesCache.size(); i++) { + const StructType *T = ExistingStructTypesCache[i]; + + const ElementTypes &Elements = T->getElementTypes(); + ElementTypes::const_iterator I = ETypes.begin(); + ElementTypes::const_iterator J = Elements.begin(); + for (; I != ETypes.end() && J != Elements.end(); I++, J++) + if (*I != *J) break; // These types aren't equal! + + if (I == ETypes.end() && J == Elements.end()) { +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Type: \""; + copy(ETypes.begin(), ETypes.end(), out); + cerr << "\"\nEquals: \""; + copy(Elements.begin(), Elements.end(), out); + cerr << "\"" << endl; +#endif + return T; + } + } + +#if TEST_MERGE_TYPES == 2 + ostream_iterator<const Type*> out(cerr, ", "); + cerr << "Input Types: "; + copy(ETypes.begin(), ETypes.end(), out); + cerr << endl; +#endif + + // Calculate the string name for the new type... + string Name = "{ "; + for (ElementTypes::const_iterator I = ETypes.begin(); + I != ETypes.end(); I++) { + if (I != ETypes.begin()) + Name += ", "; + Name += (*I)->getName(); + } + Name += " }"; + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Name << endl; +#endif + + StructType *Result = new StructType(ETypes, Name); + ExistingStructTypesCache.push_back(Result); + return Result; +} + + +const PointerType *PointerType::getPointerType(const Type *ValueType) { + static vector<const PointerType*> ExistingTypesCache; + + // Search cache for value... + for (unsigned i = 0; i < ExistingTypesCache.size(); i++) { + const PointerType *T = ExistingTypesCache[i]; + + if (T->getValueType() == ValueType) + return T; + } + + PointerType *Result = new PointerType(ValueType); + ExistingTypesCache.push_back(Result); + +#if TEST_MERGE_TYPES + cerr << "Derived new type: " << Result->getName() << endl; +#endif + return Result; +} + diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp new file mode 100644 index 0000000..1c3f76b --- /dev/null +++ b/lib/VMCore/Value.cpp @@ -0,0 +1,143 @@ +//===-- Value.cpp - Implement the Value class -----------------------------===// +// +// This file implements the Value class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ValueHolderImpl.h" +#include "llvm/InstrTypes.h" +#include "llvm/SymbolTable.h" +#include "llvm/SymTabValue.h" +#include "llvm/ConstantPool.h" +#include "llvm/ConstPoolVals.h" +#include "llvm/Type.h" +#ifndef NDEBUG // Only in -g mode... +#include "llvm/Assembly/Writer.h" +#endif +#include <algorithm> + +//===----------------------------------------------------------------------===// +// Value Class +//===----------------------------------------------------------------------===// + +Value::Value(const Type *ty, ValueTy vty, const string &name = "") : Name(name){ + Ty = ty; + VTy = vty; +} + +Value::~Value() { +#ifndef NDEBUG // Only in -g mode... + if (Uses.begin() != Uses.end()) { + for (use_const_iterator I = Uses.begin(); I != Uses.end(); I++) + cerr << "Use still stuck around after Def is destroyed:" << *I << endl; + } +#endif + assert(Uses.begin() == Uses.end()); +} + +void Value::replaceAllUsesWith(Value *D) { + assert(D && "Value::replaceAllUsesWith(<null>) is invalid!"); + while (!Uses.empty()) { + User *Use = Uses.front(); +#ifndef NDEBUG + unsigned NumUses = Uses.size(); +#endif + Use->replaceUsesOfWith(this, D); + +#ifndef NDEBUG // only in -g mode... + if (Uses.size() == NumUses) + cerr << "Use: " << Use << "replace with: " << D; +#endif + assert(Uses.size() != NumUses && "Didn't remove definition!"); + } +} + +void Value::killUse(User *i) { + if (i == 0) return; + use_iterator I = find(Uses.begin(), Uses.end(), i); + + assert(I != Uses.end() && "Use not in uses list!!"); + Uses.erase(I); +} + +User *Value::use_remove(use_iterator &I) { + assert(I != Uses.end() && "Trying to remove the end of the use list!!!"); + User *i = *I; + I = Uses.erase(I); + return i; +} + + +//===----------------------------------------------------------------------===// +// User Class +//===----------------------------------------------------------------------===// + +User::User(const Type *Ty, ValueTy vty, const string &name) + : Value(Ty, vty, name) { +} + +// replaceUsesOfWith - Replaces all references to the "From" definition with +// references to the "To" definition. +// +void User::replaceUsesOfWith(Value *From, Value *To) { + if (From == To) return; // Duh what? + + for (unsigned OpNum = 0; Value *D = getOperand(OpNum); OpNum++) { + if (D == From) { // Okay, this operand is pointing to our fake def. + // The side effects of this setOperand call include linking to + // "To", adding "this" to the uses list of To, and + // most importantly, removing "this" from the use list of "From". + setOperand(OpNum, To); // Fix it now... + } + } +} + + +//===----------------------------------------------------------------------===// +// SymTabValue Class +//===----------------------------------------------------------------------===// + +// Instantiate Templates - This ugliness is the price we have to pay +// for having a ValueHolderImpl.h file seperate from ValueHolder.h! :( +// +template class ValueHolder<ConstPoolVal, SymTabValue>; + +SymTabValue::SymTabValue(const Type *Ty, ValueTy dty, const string &name = "") + : Value(Ty, dty, name), ConstPool(this) { + ParentSymTab = SymTab = 0; +} + + +SymTabValue::~SymTabValue() { + ConstPool.dropAllReferences(); + ConstPool.delete_all(); + ConstPool.setParent(0); + + delete SymTab; +} + +void SymTabValue::setParentSymTab(SymbolTable *ST) { + ParentSymTab = ST; + if (SymTab) + SymTab->setParentSymTab(ST); +} + +SymbolTable *SymTabValue::getSymbolTableSure() { + if (!SymTab) SymTab = new SymbolTable(ParentSymTab); + return SymTab; +} + +// hasSymbolTable() - Returns true if there is a symbol table allocated to +// this object AND if there is at least one name in it! +// +bool SymTabValue::hasSymbolTable() const { + if (!SymTab) return false; + + for (SymbolTable::const_iterator I = SymTab->begin(); + I != SymTab->end(); I++) { + if (I->second.begin() != I->second.end()) + return true; // Found nonempty type plane! + } + + return false; +} diff --git a/lib/VMCore/ValueHolderImpl.h b/lib/VMCore/ValueHolderImpl.h new file mode 100644 index 0000000..ecafd47 --- /dev/null +++ b/lib/VMCore/ValueHolderImpl.h @@ -0,0 +1,85 @@ +//===-- llvm/ValueHolderImpl.h - Implement ValueHolder template --*- C++ -*--=// +// +// This file implements the ValueHolder class. This is kept out of line because +// it tends to pull in a lot of dependencies on other headers and most files +// don't need all that crud. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUEHOLDER_IMPL_H +#define LLVM_VALUEHOLDER_IMPL_H + +#include "llvm/ValueHolder.h" +#include "llvm/SymbolTable.h" +#include <algorithm> + +template<class ValueSubclass, class ItemParentType> +void ValueHolder<ValueSubclass,ItemParentType>::setParent(SymTabValue *P) { + if (Parent) { // Remove all of the items from the old symbol table.. + SymbolTable *SymTab = Parent->getSymbolTable(); + for (iterator I = begin(); I != end(); I++) + if ((*I)->hasName()) SymTab->remove(*I); + } + + Parent = P; + + if (Parent) { // Remove all of the items from the old symbol table.. + SymbolTable *SymTab = Parent->getSymbolTableSure(); + for (iterator I = begin(); I != end(); I++) + if ((*I)->hasName()) SymTab->insert(*I); + } +} + + +template<class ValueSubclass, class ItemParentType> +void ValueHolder<ValueSubclass,ItemParentType>::remove(ValueSubclass *D) { + iterator I(find(begin(), end(), D)); + assert(I != end() && "Value not in ValueHolder!!"); + remove(I); +} + +// ValueHolder::remove(iterator &) this removes the element at the location specified +// by the iterator, and leaves the iterator pointing to the element that used to follow +// the element deleted. +// +template<class ValueSubclass, class ItemParentType> +ValueSubclass *ValueHolder<ValueSubclass,ItemParentType>::remove(iterator &DI) { + assert(DI != ValueList.end() && + "Trying to remove the end of the def list!!!"); + + ValueSubclass *i = *DI; + DI = ValueList.erase(DI); + + i->setParent(0); // I don't own you anymore... byebye... + + // You don't get to be in the symbol table anymore... byebye + if (i->hasName() && Parent) + Parent->getSymbolTable()->remove(i); + + return i; +} + +template<class ValueSubclass, class ItemParentType> +void ValueHolder<ValueSubclass,ItemParentType>::push_front(ValueSubclass *Inst) { + assert(Inst->getParent() == 0 && "Value already has parent!"); + Inst->setParent(ItemParent); + + //ValueList.push_front(Inst); + ValueList.insert(ValueList.begin(), Inst); + + if (Inst->hasName() && Parent) + Parent->getSymbolTableSure()->insert(Inst); +} + +template<class ValueSubclass, class ItemParentType> +void ValueHolder<ValueSubclass,ItemParentType>::push_back(ValueSubclass *Inst) { + assert(Inst->getParent() == 0 && "Value already has parent!"); + Inst->setParent(ItemParent); + + ValueList.push_back(Inst); + + if (Inst->hasName() && Parent) + Parent->getSymbolTableSure()->insert(Inst); +} + +#endif diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp new file mode 100644 index 0000000..820fa5c --- /dev/null +++ b/lib/VMCore/Verifier.cpp @@ -0,0 +1,94 @@ +//===-- Verifier.cpp - Implement the Module Verifier -------------*- C++ -*-==// +// +// This file defines the method verifier interface, that can be used for some +// sanity checking of input to the system. +// +// Note that this does not provide full 'java style' security and verifications, +// instead it just tries to ensure that code is well formed. +// +// . There are no duplicated names in a symbol table... ie there !exist a val +// with the same name as something in the symbol table, but with a different +// address as what is in the symbol table... +// . Both of a binary operator's parameters are the same type +// . Only PHI nodes can refer to themselves +// . All of the constants in a switch statement are of the correct type +// . The code is in valid SSA form +// . It should be illegal to put a label into any other type (like a structure) +// or to return one. [except constant arrays!] +// . Right now 'add bool 0, 0' is valid. This isn't particularly good. +// . Only phi nodes can be self referential: 'add int 0, 0 ; <int>:0' is bad +// . All other things that are tested by asserts spread about the code... +// . All basic blocks should only end with terminator insts, not contain them +// . All methods must have >= 1 basic block +// . Verify that none of the Def getType()'s are null. +// . Method's cannot take a void typed parameter +// . Verify that a method's argument list agrees with it's declared type. +// . Verify that arrays and structures have fixed elements: No unsized arrays. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Verifier.h" +#include "llvm/ConstantPool.h" +#include "llvm/Method.h" +#include "llvm/Module.h" +#include "llvm/BasicBlock.h" +#include "llvm/Type.h" + +// Error - Define a macro to do the common task of pushing a message onto the +// end of the error list and setting Bad to true. +// +#define Error(msg) do { ErrorMsgs.push_back(msg); Bad = true; } while (0) + +#define t(x) (1 << (unsigned)Type::x) + +#define SignedIntegralTypes (t(SByteTyID) | t(ShortTyID) | \ + t(IntTyID) | t(LongTyID)) +static long UnsignedIntegralTypes = t(UByteTyID) | t(UShortTyID) | + t(UIntTyID) | t(ULongTyID); +static const long FloatingPointTypes = t(FloatTyID) | t(DoubleTyID); + +static const long IntegralTypes = SignedIntegralTypes | UnsignedIntegralTypes; + +#if 0 +static long ValidTypes[Type::FirstDerivedTyID] = { + [(unsigned)Instruction::UnaryOps::Not] t(BoolTyID), + //[Instruction::UnaryOps::Add] = IntegralTypes, + // [Instruction::Sub] = IntegralTypes, +}; +#endif + +#undef t + +static bool verify(const BasicBlock *BB, vector<string> &ErrorMsgs) { + bool Bad = false; + if (BB->getTerminator() == 0) Error("Basic Block does not have terminator!"); + + + return Bad; +} + + +bool verify(const Method *M, vector<string> &ErrorMsgs) { + bool Bad = false; + + for (Method::BasicBlocksType::const_iterator BBIt = M->getBasicBlocks().begin(); + BBIt != M->getBasicBlocks().end(); BBIt++) { + Bad |= verify(*BBIt, ErrorMsgs); + } + + return Bad; +} + +bool verify(const Module *C, vector<string> &ErrorMsgs) { + bool Bad = false; + assert(Type::FirstDerivedTyID-1 < sizeof(long)*8 && + "Resize ValidTypes table to handle more than 32 primitive types!"); + + for (Module::MethodListType::const_iterator MI = C->getMethodList().begin(); + MI != C->getMethodList().end(); MI++) { + const Method *M = *MI; + Bad |= verify(M, ErrorMsgs); + } + + return Bad; +} diff --git a/lib/VMCore/iBranch.cpp b/lib/VMCore/iBranch.cpp new file mode 100644 index 0000000..05f3505 --- /dev/null +++ b/lib/VMCore/iBranch.cpp @@ -0,0 +1,69 @@ +//===-- iBranch.cpp - Implement the Branch instruction -----------*- C++ -*--=// +// +// This file implements the 'br' instruction, which can represent either a +// conditional or unconditional branch. +// +//===----------------------------------------------------------------------===// + +#include "llvm/iTerminators.h" +#include "llvm/BasicBlock.h" +#ifndef NDEBUG +#include "llvm/Type.h" // Only used for assertions... +#include "llvm/Assembly/Writer.h" +#endif + +BranchInst::BranchInst(BasicBlock *True, BasicBlock *False, Value *Cond) + : TerminatorInst(Instruction::Br), TrueDest(True, this), + FalseDest(False, this), Condition(Cond, this) { + assert(True != 0 && "True branch destination may not be null!!!"); + +#ifndef NDEBUG + if (Cond != 0 && Cond->getType() != Type::BoolTy) + cerr << "Bad Condition: " << Cond << endl; +#endif + assert((Cond == 0 || Cond->getType() == Type::BoolTy) && + "May only branch on boolean predicates!!!!"); +} + +BranchInst::BranchInst(const BranchInst &BI) + : TerminatorInst(Instruction::Br), TrueDest(BI.TrueDest, this), + FalseDest(BI.FalseDest, this), Condition(BI.Condition, this) { +} + + +void BranchInst::dropAllReferences() { + Condition = 0; + TrueDest = FalseDest = 0; +} + +const Value *BranchInst::getOperand(unsigned i) const { + return (i == 0) ? (Value*)TrueDest : + ((i == 1) ? (Value*)FalseDest : + ((i == 2) ? (Value*)Condition : 0)); +} + +const BasicBlock *BranchInst::getSuccessor(unsigned i) const { + return (i == 0) ? (const BasicBlock*)TrueDest : + ((i == 1) ? (const BasicBlock*)FalseDest : 0); +} + +bool BranchInst::setOperand(unsigned i, Value *Val) { + switch (i) { + case 0: + assert(Val && "Can't change primary direction to 0!"); + assert(Val->getType() == Type::LabelTy); + TrueDest = (BasicBlock*)Val; + return true; + case 1: + assert(Val == 0 || Val->getType() == Type::LabelTy); + FalseDest = (BasicBlock*)Val; + return true; + case 2: + Condition = Val; + assert(!Condition || Condition->getType() == Type::BoolTy && + "Condition expr must be a boolean expression!"); + return true; + } + + return false; +} diff --git a/lib/VMCore/iCall.cpp b/lib/VMCore/iCall.cpp new file mode 100644 index 0000000..9ff6bb6 --- /dev/null +++ b/lib/VMCore/iCall.cpp @@ -0,0 +1,48 @@ +//===-- iCall.cpp - Implement the Call & Invoke instructions -----*- C++ -*--=// +// +// This file implements the call and invoke instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/iOther.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Method.h" + +CallInst::CallInst(Method *m, vector<Value*> ¶ms, + const string &Name) + : Instruction(m->getReturnType(), Instruction::Call, Name), M(m, this) { + + const MethodType* MT = M->getMethodType(); + const MethodType::ParamTypes &PL = MT->getParamTypes(); + assert(params.size() == PL.size()); +#ifndef NDEBUG + MethodType::ParamTypes::const_iterator It = PL.begin(); +#endif + for (unsigned i = 0; i < params.size(); i++) { + assert(*It++ == params[i]->getType()); + Params.push_back(Use(params[i], this)); + } +} + +CallInst::CallInst(const CallInst &CI) + : Instruction(CI.getType(), Instruction::Call), M(CI.M, this) { + for (unsigned i = 0; i < CI.Params.size(); i++) + Params.push_back(Use(CI.Params[i], this)); +} + +void CallInst::dropAllReferences() { + M = 0; + Params.clear(); +} + +bool CallInst::setOperand(unsigned i, Value *Val) { + if (i > Params.size()) return false; + if (i == 0) { + assert(Val->getValueType() == Value::MethodVal); + M = (Method*)Val; + } else { + // TODO: assert = method arg type + Params[i-1] = Val; + } + return true; +} diff --git a/lib/VMCore/iOperators.cpp b/lib/VMCore/iOperators.cpp new file mode 100644 index 0000000..c754f42 --- /dev/null +++ b/lib/VMCore/iOperators.cpp @@ -0,0 +1,37 @@ +//===-- iBinaryOperators.cpp - Implement the BinaryOperators -----*- C++ -*--=// +// +// This file implements the nontrivial binary operator instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/iBinary.h" +#include "llvm/Type.h" + +//===----------------------------------------------------------------------===// +// SetCondInst Class +//===----------------------------------------------------------------------===// + +SetCondInst::SetCondInst(BinaryOps opType, Value *S1, Value *S2, + const string &Name) + : BinaryOperator(opType, S1, S2, Name) { + + OpType = opType; + setType(Type::BoolTy); // setcc instructions always return bool type. + + // Make sure it's a valid type... + assert(getOpcode() != "Invalid opcode type to SetCondInst class!"); +} + +string SetCondInst::getOpcode() const { + switch (OpType) { + case SetLE: return "setle"; + case SetGE: return "setge"; + case SetLT: return "setlt"; + case SetGT: return "setgt"; + case SetEQ: return "seteq"; + case SetNE: return "setne"; + default: + assert(0 && "Invalid opcode type to SetCondInst class!"); + return "invalid opcode type to SetCondInst"; + } +} diff --git a/lib/VMCore/iReturn.cpp b/lib/VMCore/iReturn.cpp new file mode 100644 index 0000000..7fa04fb --- /dev/null +++ b/lib/VMCore/iReturn.cpp @@ -0,0 +1,25 @@ +//===-- iReturn.cpp - Implement the Return instruction -----------*- C++ -*--=// +// +// This file implements the Return instruction... +// +//===----------------------------------------------------------------------===// + +#include "llvm/iTerminators.h" + +ReturnInst::ReturnInst(Value *V) + : TerminatorInst(Instruction::Ret), Val(V, this) { +} + +ReturnInst::ReturnInst(const ReturnInst &RI) + : TerminatorInst(Instruction::Ret), Val(RI.Val, this) { +} + +void ReturnInst::dropAllReferences() { + Val = 0; +} + +bool ReturnInst::setOperand(unsigned i, Value *V) { + if (i) return false; + Val = V; + return true; +} diff --git a/lib/VMCore/iSwitch.cpp b/lib/VMCore/iSwitch.cpp new file mode 100644 index 0000000..2a1eec2 --- /dev/null +++ b/lib/VMCore/iSwitch.cpp @@ -0,0 +1,81 @@ +//===-- iSwitch.cpp - Implement the Switch instruction -----------*- C++ -*--=// +// +// This file implements the Switch instruction... +// +//===----------------------------------------------------------------------===// + +#include "llvm/iTerminators.h" +#include "llvm/BasicBlock.h" +#ifndef NDEBUG +#include "llvm/Type.h" +#endif + +SwitchInst::SwitchInst(Value *V, BasicBlock *DefV) + : TerminatorInst(Instruction::Switch), + DefaultDest(DefV, this), Val(V, this) { + assert(Val && DefV); +} + +SwitchInst::SwitchInst(const SwitchInst &SI) + : TerminatorInst(Instruction::Switch), DefaultDest(SI.DefaultDest), + Val(SI.Val) { + + for (dest_const_iterator I = SI.Destinations.begin(), + end = SI.Destinations.end(); I != end; ++I) + Destinations.push_back(dest_value(ConstPoolUse(I->first, this), + BasicBlockUse(I->second, this))); +} + + +void SwitchInst::dest_push_back(ConstPoolVal *OnVal, BasicBlock *Dest) { + Destinations.push_back(dest_value(ConstPoolUse(OnVal, this), + BasicBlockUse(Dest, this))); +} + +void SwitchInst::dropAllReferences() { + Val = 0; + DefaultDest = 0; + Destinations.clear(); +} + +const BasicBlock *SwitchInst::getSuccessor(unsigned idx) const { + if (idx == 0) return DefaultDest; + if (idx > Destinations.size()) return 0; + return Destinations[idx-1].second; +} + +unsigned SwitchInst::getNumOperands() const { + return 2+Destinations.size(); +} + +const Value *SwitchInst::getOperand(unsigned i) const { + if (i == 0) return Val; + else if (i == 1) return DefaultDest; + + unsigned slot = (i-2) >> 1; + if (slot >= Destinations.size()) return 0; + + if (i & 1) return Destinations[slot].second; + return Destinations[slot].first; +} + +bool SwitchInst::setOperand(unsigned i, Value *V) { + if (i == 0) { Val = V; return true; } + else if (i == 1) { + assert(V->getType() == Type::LabelTy); + DefaultDest = (BasicBlock*)V; + return true; + } + + unsigned slot = (i-2) >> 1; + if (slot >= Destinations.size()) return 0; + + if (i & 1) { + assert(V->getType() == Type::LabelTy); + Destinations[slot].second = (BasicBlock*)V; + } else { + // TODO: assert constant + Destinations[slot].first = (ConstPoolVal*)V; + } + return true; +} |