diff --git a/include/llvm/CodeGen/MachineCodeForInstruction.h b/include/llvm/CodeGen/MachineCodeForInstruction.h new file mode 100644 index 00000000000..5d0cdd91330 --- /dev/null +++ b/include/llvm/CodeGen/MachineCodeForInstruction.h @@ -0,0 +1,48 @@ +//===-- llvm/CodeGen/MachineCodeForInstruction.h -----------------*- C++ -*--=// +// +// Representation of the sequence of machine instructions created +// for a single VM instruction. Additionally records information +// about hidden and implicit values used by the machine instructions: +// about hidden values used by the machine instructions: +// +// "Temporary values" are intermediate values used in the machine +// instruction sequence, but not in the VM instruction +// Note that such values should be treated as pure SSA values with +// no interpretation of their operands (i.e., as a TmpInstruction +// object which actually represents such a value). +// +// (2) "Implicit uses" are values used in the VM instruction but not in +// the machine instruction sequence +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODE_FOR_INSTRUCTION_H +#define LLVM_CODEGEN_MACHINECODE_FOR_INSTRUCTION_H + +#include "llvm/Annotation.h" +#include +class MachineInstr; +class Instruction; +class Value; + +class MachineCodeForInstruction + : public Annotation, public std::vector { + std::vector tempVec; // used by m/c instr but not VM instr + +public: + MachineCodeForInstruction(); + ~MachineCodeForInstruction(); + + static MachineCodeForInstruction &get(const Instruction *I); + static void destroy(const Instruction *I); + + const std::vector &getTempValues() const { return tempVec; } + std::vector &getTempValues() { return tempVec; } + + inline MachineCodeForInstruction &addTemp(Value *tmp) { + tempVec.push_back(tmp); + return *this; + } +}; + +#endif diff --git a/include/llvm/CodeGen/MachineCodeForMethod.h b/include/llvm/CodeGen/MachineCodeForMethod.h new file mode 100644 index 00000000000..3ef4b10d3ff --- /dev/null +++ b/include/llvm/CodeGen/MachineCodeForMethod.h @@ -0,0 +1,112 @@ +//===-- llvm/CodeGen/MachineCodeForMethod.h ----------------------*- C++ -*--=// +// +// Purpose: +// Collect native machine code information for a method. +// This allows target-specific information about the generated code +// to be stored with each method. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODEFORMETHOD_H +#define LLVM_CODEGEN_MACHINECODEFORMETHOD_H + +#include "llvm/Annotation.h" +#include "Support/NonCopyable.h" +#include "Support/HashExtras.h" +#include +class Value; +class Method; +class Constant; +class Type; +class TargetMachine; + + +class MachineCodeForMethod : private Annotation { + const Method* method; + bool compiledAsLeaf; + unsigned staticStackSize; + unsigned automaticVarsSize; + unsigned regSpillsSize; + unsigned currentOptionalArgsSize; + unsigned maxOptionalArgsSize; + unsigned currentTmpValuesSize; + std::hash_set constantsForConstPool; + std::hash_map offsets; + // hash_map offsetsFromSP; + +public: + /*ctor*/ MachineCodeForMethod(const Method* method, + const TargetMachine& target); + + // The next two methods are used to construct and to retrieve + // the MachineCodeForMethod object for the given method. + // construct() -- Allocates and initializes for a given method and target + // get() -- Returns a handle to the object. + // This should not be called before "construct()" + // for a given Method. + // + static MachineCodeForMethod& construct(const Method *method, + const TargetMachine &target); + static void destruct(const Method *M); + static MachineCodeForMethod& get(const Method* method); + + // + // Accessors for global information about generated code for a method. + // + inline bool isCompiledAsLeafMethod() const { return compiledAsLeaf; } + inline unsigned getStaticStackSize() const { return staticStackSize; } + inline unsigned getAutomaticVarsSize() const { return automaticVarsSize; } + inline unsigned getRegSpillsSize() const { return regSpillsSize; } + inline unsigned getMaxOptionalArgsSize() const { return maxOptionalArgsSize;} + inline unsigned getCurrentOptionalArgsSize() const + { return currentOptionalArgsSize;} + inline const std::hash_set& + getConstantPoolValues() const {return constantsForConstPool;} + + // + // Modifiers used during code generation + // + void initializeFrameLayout (const TargetMachine& target); + + void addToConstantPool (const Constant* constVal) + { constantsForConstPool.insert(constVal); } + + inline void markAsLeafMethod() { compiledAsLeaf = true; } + + int allocateLocalVar (const TargetMachine& target, + const Value* local, + unsigned int size = 0); + + int allocateSpilledValue (const TargetMachine& target, + const Type* type); + + int allocateOptionalArg (const TargetMachine& target, + const Type* type); + + void resetOptionalArgs (const TargetMachine& target); + + int pushTempValue (const TargetMachine& target, + unsigned int size); + + void popAllTempValues (const TargetMachine& target); + + int getOffset (const Value* val) const; + + // int getOffsetFromFP (const Value* val) const; + + void dump () const; + +private: + inline void incrementAutomaticVarsSize(int incr) { + automaticVarsSize+= incr; + staticStackSize += incr; + } + inline void incrementRegSpillsSize(int incr) { + regSpillsSize+= incr; + staticStackSize += incr; + } + inline void incrementCurrentOptionalArgsSize(int incr) { + currentOptionalArgsSize+= incr; // stack size already includes this! + } +}; + +#endif diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h new file mode 100644 index 00000000000..3ef4b10d3ff --- /dev/null +++ b/include/llvm/CodeGen/MachineFunction.h @@ -0,0 +1,112 @@ +//===-- llvm/CodeGen/MachineCodeForMethod.h ----------------------*- C++ -*--=// +// +// Purpose: +// Collect native machine code information for a method. +// This allows target-specific information about the generated code +// to be stored with each method. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODEFORMETHOD_H +#define LLVM_CODEGEN_MACHINECODEFORMETHOD_H + +#include "llvm/Annotation.h" +#include "Support/NonCopyable.h" +#include "Support/HashExtras.h" +#include +class Value; +class Method; +class Constant; +class Type; +class TargetMachine; + + +class MachineCodeForMethod : private Annotation { + const Method* method; + bool compiledAsLeaf; + unsigned staticStackSize; + unsigned automaticVarsSize; + unsigned regSpillsSize; + unsigned currentOptionalArgsSize; + unsigned maxOptionalArgsSize; + unsigned currentTmpValuesSize; + std::hash_set constantsForConstPool; + std::hash_map offsets; + // hash_map offsetsFromSP; + +public: + /*ctor*/ MachineCodeForMethod(const Method* method, + const TargetMachine& target); + + // The next two methods are used to construct and to retrieve + // the MachineCodeForMethod object for the given method. + // construct() -- Allocates and initializes for a given method and target + // get() -- Returns a handle to the object. + // This should not be called before "construct()" + // for a given Method. + // + static MachineCodeForMethod& construct(const Method *method, + const TargetMachine &target); + static void destruct(const Method *M); + static MachineCodeForMethod& get(const Method* method); + + // + // Accessors for global information about generated code for a method. + // + inline bool isCompiledAsLeafMethod() const { return compiledAsLeaf; } + inline unsigned getStaticStackSize() const { return staticStackSize; } + inline unsigned getAutomaticVarsSize() const { return automaticVarsSize; } + inline unsigned getRegSpillsSize() const { return regSpillsSize; } + inline unsigned getMaxOptionalArgsSize() const { return maxOptionalArgsSize;} + inline unsigned getCurrentOptionalArgsSize() const + { return currentOptionalArgsSize;} + inline const std::hash_set& + getConstantPoolValues() const {return constantsForConstPool;} + + // + // Modifiers used during code generation + // + void initializeFrameLayout (const TargetMachine& target); + + void addToConstantPool (const Constant* constVal) + { constantsForConstPool.insert(constVal); } + + inline void markAsLeafMethod() { compiledAsLeaf = true; } + + int allocateLocalVar (const TargetMachine& target, + const Value* local, + unsigned int size = 0); + + int allocateSpilledValue (const TargetMachine& target, + const Type* type); + + int allocateOptionalArg (const TargetMachine& target, + const Type* type); + + void resetOptionalArgs (const TargetMachine& target); + + int pushTempValue (const TargetMachine& target, + unsigned int size); + + void popAllTempValues (const TargetMachine& target); + + int getOffset (const Value* val) const; + + // int getOffsetFromFP (const Value* val) const; + + void dump () const; + +private: + inline void incrementAutomaticVarsSize(int incr) { + automaticVarsSize+= incr; + staticStackSize += incr; + } + inline void incrementRegSpillsSize(int incr) { + regSpillsSize+= incr; + staticStackSize += incr; + } + inline void incrementCurrentOptionalArgsSize(int incr) { + currentOptionalArgsSize+= incr; // stack size already includes this! + } +}; + +#endif diff --git a/lib/CodeGen/MachineCodeForInstruction.cpp b/lib/CodeGen/MachineCodeForInstruction.cpp new file mode 100644 index 00000000000..97a53752e13 --- /dev/null +++ b/lib/CodeGen/MachineCodeForInstruction.cpp @@ -0,0 +1,57 @@ +//===-- MachineCodeForInstruction.cpp -------------------------------------===// +// +// Representation of the sequence of machine instructions created +// for a single VM instruction. Additionally records information +// about hidden and implicit values used by the machine instructions: +// about hidden values used by the machine instructions: +// +// "Temporary values" are intermediate values used in the machine +// instruction sequence, but not in the VM instruction +// Note that such values should be treated as pure SSA values with +// no interpretation of their operands (i.e., as a TmpInstruction +// object which actually represents such a value). +// +// (2) "Implicit uses" are values used in the VM instruction but not in +// the machine instruction sequence +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineCodeForInstruction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Instruction.h" + +static AnnotationID MCFI_AID( + AnnotationManager::getID("CodeGen::MachineCodeForInstruction")); + +static Annotation *CreateMCFI(AnnotationID AID, const Annotable *, void *) { + assert(AID == MCFI_AID); + return new MachineCodeForInstruction(); // Invoke constructor! +} + +// Register the annotation with the annotation factory +static struct Initializer { + Initializer() { + AnnotationManager::registerAnnotationFactory(MCFI_AID, &CreateMCFI); + } +} RegisterAID; + +MachineCodeForInstruction &MachineCodeForInstruction::get(const Instruction *I){ + return *(MachineCodeForInstruction*)I->getOrCreateAnnotation(MCFI_AID); +} + +void MachineCodeForInstruction::destroy(const Instruction *I) { + I->deleteAnnotation(MCFI_AID); +} + + +MachineCodeForInstruction::MachineCodeForInstruction() : Annotation(MCFI_AID) {} + +MachineCodeForInstruction::~MachineCodeForInstruction() { + // Free the Value objects created to hold intermediate values + for (unsigned i=0, N=tempVec.size(); i < N; i++) + delete tempVec[i]; + + // Free the MachineInstr objects allocated, if any. + for (unsigned i=0, N = size(); i < N; i++) + delete (*this)[i]; +} diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp new file mode 100644 index 00000000000..3ff3e8ceea2 --- /dev/null +++ b/lib/CodeGen/MachineFunction.cpp @@ -0,0 +1,300 @@ +//===-- MachineCodeForMethod.cpp --------------------------------------------=// +// +// Purpose: +// Collect native machine code information for a method. +// This allows target-specific information about the generated code +// to be stored with each method. +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineCodeForMethod.h" +#include "llvm/CodeGen/MachineInstr.h" // For debug output +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/MachineFrameInfo.h" +#include "llvm/Target/MachineCacheInfo.h" +#include "llvm/Method.h" +#include "llvm/iOther.h" +#include + +const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits::max(); + +static AnnotationID MCFM_AID( + AnnotationManager::getID("CodeGen::MachineCodeForMethod")); + +// The next two methods are used to construct and to retrieve +// the MachineCodeForMethod object for the given method. +// construct() -- Allocates and initializes for a given method and target +// get() -- Returns a handle to the object. +// This should not be called before "construct()" +// for a given Method. +// +MachineCodeForMethod &MachineCodeForMethod::construct(const Method *M, + const TargetMachine &Tar){ + assert(M->getAnnotation(MCFM_AID) == 0 && + "Object already exists for this method!"); + MachineCodeForMethod* mcInfo = new MachineCodeForMethod(M, Tar); + M->addAnnotation(mcInfo); + return *mcInfo; +} + +void MachineCodeForMethod::destruct(const Method *M) { + bool Deleted = M->deleteAnnotation(MCFM_AID); + assert(Deleted && "Machine code did not exist for method!"); +} + + +MachineCodeForMethod &MachineCodeForMethod::get(const Method* method) { + MachineCodeForMethod* mc = (MachineCodeForMethod*) + method->getAnnotation(MCFM_AID); + assert(mc && "Call construct() method first to allocate the object"); + return *mc; +} + +static unsigned +ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method) +{ + const MachineFrameInfo& frameInfo = target.getFrameInfo(); + + unsigned int maxSize = 0; + + for (Method::const_inst_iterator I=method->inst_begin(),E=method->inst_end(); + I != E; ++I) + if ((*I)->getOpcode() == Instruction::Call) + { + CallInst* callInst = cast(*I); + unsigned int numOperands = callInst->getNumOperands() - 1; + int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs(); + if (numExtra <= 0) + continue; + + unsigned int sizeForThisCall; + if (frameInfo.argsOnStackHaveFixedSize()) + { + int argSize = frameInfo.getSizeOfEachArgOnStack(); + sizeForThisCall = numExtra * (unsigned) argSize; + } + else + { + assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize"); + sizeForThisCall = 0; + for (unsigned i=0; i < numOperands; ++i) + sizeForThisCall += target.findOptimalStorageSize(callInst-> + getOperand(i)->getType()); + } + + if (maxSize < sizeForThisCall) + maxSize = sizeForThisCall; + } + + return maxSize; +} + +// Align data larger than one L1 cache line on L1 cache line boundaries. +// Align all smaller data on the next higher 2^x boundary (4, 8, ...). +// +// THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND +// SHOULD BE USED DIRECTLY THERE +// +inline unsigned int +SizeToAlignment(unsigned int size, const TargetMachine& target) +{ + unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); + if (size > (unsigned) cacheLineSize / 2) + return cacheLineSize; + else + for (unsigned sz=1; /*no condition*/; sz *= 2) + if (sz >= size) + return sz; +} + + + +/*ctor*/ +MachineCodeForMethod::MachineCodeForMethod(const Method* _M, + const TargetMachine& target) + : Annotation(MCFM_AID), + method(_M), compiledAsLeaf(false), staticStackSize(0), + automaticVarsSize(0), regSpillsSize(0), + currentOptionalArgsSize(0), maxOptionalArgsSize(0), + currentTmpValuesSize(0) +{ + maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method); + staticStackSize = maxOptionalArgsSize + + target.getFrameInfo().getMinStackFrameSize(); +} + +int +MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, + const Value* val, + unsigned int size) +{ + // Check if we've allocated a stack slot for this value already + // + int offset = getOffset(val); + if (offset == INVALID_FRAME_OFFSET) + { + bool growUp; + int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, + growUp); + unsigned char align; + if (size == 0) + { + size = target.findOptimalStorageSize(val->getType()); + // align = target.DataLayout.getTypeAlignment(val->getType()); + } + + align = SizeToAlignment(size, target); + + offset = getAutomaticVarsSize(); + if (! growUp) + offset += size; + + if (unsigned int mod = offset % align) + { + offset += align - mod; + size += align - mod; + } + + offset = growUp? firstOffset + offset + : firstOffset - offset; + + offsets[val] = offset; + + incrementAutomaticVarsSize(size); + } + return offset; +} + +int +MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, + const Type* type) +{ + unsigned int size = target.findOptimalStorageSize(type); + unsigned char align = target.DataLayout.getTypeAlignment(type); + + bool growUp; + int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); + + int offset = getRegSpillsSize(); + if (! growUp) + offset += size; + + if (unsigned int mod = offset % align) + { + offset += align - mod; + size += align - mod; + } + + offset = growUp? firstOffset + offset + : firstOffset - offset; + + incrementRegSpillsSize(size); + + return offset; +} + +int +MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target, + const Type* type) +{ + const MachineFrameInfo& frameInfo = target.getFrameInfo(); + + int size = INT_MAX; + if (frameInfo.argsOnStackHaveFixedSize()) + size = frameInfo.getSizeOfEachArgOnStack(); + else + { + size = target.findOptimalStorageSize(type); + assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets"); + } + unsigned char align = target.DataLayout.getTypeAlignment(type); + + bool growUp; + int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp); + + int offset = getCurrentOptionalArgsSize(); + if (! growUp) + offset += size; + + if (unsigned int mod = offset % align) + { + offset += align - mod; + size += align - mod; + } + + offset = growUp? firstOffset + offset + : firstOffset - offset; + + incrementCurrentOptionalArgsSize(size); + + return offset; +} + +void +MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target) +{ + currentOptionalArgsSize = 0; +} + +int +MachineCodeForMethod::pushTempValue(const TargetMachine& target, + unsigned int size) +{ + // Compute a power-of-2 alignment according to the possible sizes, + // but not greater than the alignment of the largest type we support + // (currently a double word -- see class TargetData). + unsigned char align = 1; + for (; align < size && align < target.DataLayout.getDoubleAlignment(); + align = 2*align) + ; + + bool growUp; + int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); + + int offset = currentTmpValuesSize; + if (! growUp) + offset += size; + + if (unsigned int mod = offset % align) + { + offset += align - mod; + size += align - mod; + } + + offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset; + + currentTmpValuesSize += size; + return offset; +} + +void +MachineCodeForMethod::popAllTempValues(const TargetMachine& target) +{ + currentTmpValuesSize = 0; +} + +int +MachineCodeForMethod::getOffset(const Value* val) const +{ + std::hash_map::const_iterator pair = offsets.find(val); + return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; +} + +void +MachineCodeForMethod::dump() const +{ + cerr << "\n" << method->getReturnType() + << " \"" << method->getName() << "\"\n"; + + for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI) + { + BasicBlock* bb = *BI; + cerr << "\n" + << (bb->hasName()? bb->getName() : "Label") + << " (" << bb << ")" << ":\n"; + + MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec(); + for (unsigned i=0; i < mvec.size(); i++) + cerr << "\t" << *mvec[i]; + } + cerr << "\nEnd method \"" << method->getName() << "\"\n\n"; +} diff --git a/lib/Target/SparcV9/MachineCodeForInstruction.h b/lib/Target/SparcV9/MachineCodeForInstruction.h new file mode 100644 index 00000000000..5d0cdd91330 --- /dev/null +++ b/lib/Target/SparcV9/MachineCodeForInstruction.h @@ -0,0 +1,48 @@ +//===-- llvm/CodeGen/MachineCodeForInstruction.h -----------------*- C++ -*--=// +// +// Representation of the sequence of machine instructions created +// for a single VM instruction. Additionally records information +// about hidden and implicit values used by the machine instructions: +// about hidden values used by the machine instructions: +// +// "Temporary values" are intermediate values used in the machine +// instruction sequence, but not in the VM instruction +// Note that such values should be treated as pure SSA values with +// no interpretation of their operands (i.e., as a TmpInstruction +// object which actually represents such a value). +// +// (2) "Implicit uses" are values used in the VM instruction but not in +// the machine instruction sequence +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODE_FOR_INSTRUCTION_H +#define LLVM_CODEGEN_MACHINECODE_FOR_INSTRUCTION_H + +#include "llvm/Annotation.h" +#include +class MachineInstr; +class Instruction; +class Value; + +class MachineCodeForInstruction + : public Annotation, public std::vector { + std::vector tempVec; // used by m/c instr but not VM instr + +public: + MachineCodeForInstruction(); + ~MachineCodeForInstruction(); + + static MachineCodeForInstruction &get(const Instruction *I); + static void destroy(const Instruction *I); + + const std::vector &getTempValues() const { return tempVec; } + std::vector &getTempValues() { return tempVec; } + + inline MachineCodeForInstruction &addTemp(Value *tmp) { + tempVec.push_back(tmp); + return *this; + } +}; + +#endif