Changed ELFCodeEmitter to inherit from ObjectCodeEmitter

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74821 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2009-07-06 09:26:48 +00:00
parent d7649417d1
commit 6933d3eff8
4 changed files with 55 additions and 135 deletions

View File

@ -33,47 +33,30 @@ namespace llvm {
/// startFunction - This callback is invoked when a new machine function is /// startFunction - This callback is invoked when a new machine function is
/// about to be emitted. /// about to be emitted.
void ELFCodeEmitter::startFunction(MachineFunction &MF) { void ELFCodeEmitter::startFunction(MachineFunction &MF) {
DOUT << "processing function: " << MF.getFunction()->getName() << "\n";
// Get the ELF Section that this function belongs in. // Get the ELF Section that this function belongs in.
ES = &EW.getTextSection(); ES = &EW.getTextSection();
DOUT << "processing function: " << MF.getFunction()->getName() << "\n"; // Set the desired binary object to be used by the code emitters
setBinaryObject(ES);
// FIXME: better memory management, this will be replaced by BinaryObjects
BinaryData &BD = ES->getData();
BD.reserve(4096);
BufferBegin = &BD[0];
BufferEnd = BufferBegin + BD.capacity();
// Get the function alignment in bytes // Get the function alignment in bytes
unsigned Align = (1 << MF.getAlignment()); unsigned Align = (1 << MF.getAlignment());
// Align the section size with the function alignment, so the function can // The function must start on its required alignment
// start in a aligned offset, also update the section alignment if needed. ES->emitAlignment(Align);
// Update the section alignment if needed.
if (ES->Align < Align) ES->Align = Align; if (ES->Align < Align) ES->Align = Align;
ES->Size = (ES->Size + (Align-1)) & (-Align);
// Snaity check on allocated space for text section // Record the function start offset
assert( ES->Size < 4096 && "no more space in TextSection" ); FnStartOff = ES->getCurrentPCOffset();
// FIXME: Using ES->Size directly here instead of calculating it from the
// output buffer size (impossible because the code emitter deals only in raw
// bytes) forces us to manually synchronize size and write padding zero bytes
// to the output buffer for all non-text sections. For text sections, we do
// not synchonize the output buffer, and we just blow up if anyone tries to
// write non-code to it. An assert should probably be added to
// AddSymbolToSection to prevent calling it on the text section.
CurBufferPtr = BufferBegin + ES->Size;
// Record function start address relative to BufferBegin
FnStartPtr = CurBufferPtr;
} }
/// finishFunction - This callback is invoked after the function is completely /// finishFunction - This callback is invoked after the function is completely
/// finished. /// finished.
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
// Update Section Size
ES->Size = CurBufferPtr - BufferBegin;
// Add a symbol to represent the function. // Add a symbol to represent the function.
const Function *F = MF.getFunction(); const Function *F = MF.getFunction();
ELFSym FnSym(F); ELFSym FnSym(F);
@ -81,10 +64,10 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
FnSym.setBind(EW.getGlobalELFLinkage(F)); FnSym.setBind(EW.getGlobalELFLinkage(F));
FnSym.setVisibility(EW.getGlobalELFVisibility(F)); FnSym.setVisibility(EW.getGlobalELFVisibility(F));
FnSym.SectionIdx = ES->SectionIdx; FnSym.SectionIdx = ES->SectionIdx;
FnSym.Size = CurBufferPtr-FnStartPtr; FnSym.Size = ES->getCurrentPCOffset()-FnStartOff;
// Offset from start of Section // Offset from start of Section
FnSym.Value = FnStartPtr-BufferBegin; FnSym.Value = FnStartOff;
// Locals should go on the symbol list front // Locals should go on the symbol list front
if (!F->hasPrivateLinkage()) { if (!F->hasPrivateLinkage()) {

View File

@ -10,7 +10,7 @@
#ifndef ELFCODEEMITTER_H #ifndef ELFCODEEMITTER_H
#define ELFCODEEMITTER_H #define ELFCODEEMITTER_H
#include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/ObjectCodeEmitter.h"
#include <vector> #include <vector>
namespace llvm { namespace llvm {
@ -19,7 +19,7 @@ namespace llvm {
/// ELFCodeEmitter - This class is used by the ELFWriter to /// ELFCodeEmitter - This class is used by the ELFWriter to
/// emit the code for functions to the ELF file. /// emit the code for functions to the ELF file.
class ELFCodeEmitter : public MachineCodeEmitter { class ELFCodeEmitter : public ObjectCodeEmitter {
ELFWriter &EW; ELFWriter &EW;
/// Target machine description /// Target machine description
@ -28,30 +28,11 @@ namespace llvm {
/// Section containing code for functions /// Section containing code for functions
ELFSection *ES; ELFSection *ES;
/// Relocations - These are the relocations that the function needs, as /// Relocations - Record relocations needed by the current function
/// emitted.
std::vector<MachineRelocation> Relocations; std::vector<MachineRelocation> Relocations;
/// CPLocations - This is a map of constant pool indices to offsets from the /// FnStartPtr - Function offset from the beginning of ELFSection 'ES'
/// start of the section for that constant pool index. uintptr_t FnStartOff;
std::vector<uintptr_t> CPLocations;
/// CPSections - This is a map of constant pool indices to the MachOSection
/// containing the constant pool entry for that index.
std::vector<unsigned> CPSections;
/// JTLocations - This is a map of jump table indices to offsets from the
/// start of the section for that jump table index.
std::vector<uintptr_t> JTLocations;
/// MBBLocations - This vector is a mapping from MBB ID's to their address.
/// It is filled in by the StartMachineBasicBlock callback and queried by
/// the getMachineBasicBlockAddress callback.
std::vector<uintptr_t> MBBLocations;
/// FnStartPtr - Pointer to the start location of the current function
/// in the buffer
uint8_t *FnStartPtr;
/// JumpTableSectionIdx - Holds the index of the Jump Table Section /// JumpTableSectionIdx - Holds the index of the Jump Table Section
unsigned JumpTableSectionIdx; unsigned JumpTableSectionIdx;
@ -59,71 +40,36 @@ namespace llvm {
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM), explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM),
JumpTableSectionIdx(0) {} JumpTableSectionIdx(0) {}
void startFunction(MachineFunction &F); /// addRelocation - Register new relocations for this function
bool finishFunction(MachineFunction &F);
void addRelocation(const MachineRelocation &MR) { void addRelocation(const MachineRelocation &MR) {
Relocations.push_back(MR); Relocations.push_back(MR);
} }
virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { /// emitConstantPool - For each constant pool entry, figure out which
if (MBBLocations.size() <= (unsigned)MBB->getNumber()) /// section the constant should live in and emit data to it
MBBLocations.resize((MBB->getNumber()+1)*2);
MBBLocations[MBB->getNumber()] = getCurrentPCOffset();
}
virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
assert(CPLocations.size() > Index && "CP not emitted!");
return CPLocations[Index];
}
virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
assert(JTLocations.size() > Index && "JT not emitted!");
return JTLocations[Index];
}
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
assert(MBBLocations.size() > (unsigned)MBB->getNumber() &&
MBBLocations[MBB->getNumber()] && "MBB not emitted!");
return MBBLocations[MBB->getNumber()];
}
virtual uintptr_t getLabelAddress(uint64_t Label) const {
assert(0 && "Label address not implementated yet!");
abort();
return 0;
}
virtual void emitLabel(uint64_t LabelID) {
assert(0 && "emit Label not implementated yet!");
abort();
}
/// emitConstantPool - For each constant pool entry, figure out which section
/// the constant should live in and emit the constant.
void emitConstantPool(MachineConstantPool *MCP); void emitConstantPool(MachineConstantPool *MCP);
/// emitJumpTables - Emit all the jump tables for a given jump table info /// emitJumpTables - Emit all the jump tables for a given jump table
/// record to the appropriate section. /// info and record them to the appropriate section.
void emitJumpTables(MachineJumpTableInfo *MJTI); void emitJumpTables(MachineJumpTableInfo *MJTI);
void startFunction(MachineFunction &F);
bool finishFunction(MachineFunction &F);
/// emitLabel - Emits a label
virtual void emitLabel(uint64_t LabelID) {
assert("emitLabel not implemented");
}
/// getLabelAddress - Return the address of the specified LabelID,
/// only usable after the LabelID has been emitted.
virtual uintptr_t getLabelAddress(uint64_t Label) const {
assert("getLabelAddress not implemented");
return 0;
}
virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {} virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {}
/// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
void startGVStub(const GlobalValue* F, unsigned StubSize,
unsigned Alignment = 1) {
assert(0 && "JIT specific function called!");
abort();
}
void startGVStub(const GlobalValue* F, void *Buffer, unsigned StubSize) {
assert(0 && "JIT specific function called!");
abort();
}
void *finishGVStub(const GlobalValue *F) {
assert(0 && "JIT specific function called!");
abort();
return 0;
}
}; // end class ELFCodeEmitter }; // end class ELFCodeEmitter
} // end namespace llvm } // end namespace llvm

View File

@ -51,17 +51,18 @@
#include "llvm/Support/Streams.h" #include "llvm/Support/Streams.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
using namespace llvm; using namespace llvm;
char ELFWriter::ID = 0; char ELFWriter::ID = 0;
/// AddELFWriter - Concrete function to add the ELF writer to the function pass
/// manager. /// AddELFWriter - Add the ELF writer to the function pass manager
ObjectCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM, ObjectCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
raw_ostream &O, raw_ostream &O,
TargetMachine &TM) { TargetMachine &TM) {
ELFWriter *EW = new ELFWriter(O, TM); ELFWriter *EW = new ELFWriter(O, TM);
PM.add(EW); PM.add(EW);
return (ObjectCodeEmitter*) &EW->getMachineCodeEmitter(); return EW->getObjectCodeEmitter();
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -77,15 +78,15 @@ ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
TAI = TM.getTargetAsmInfo(); TAI = TM.getTargetAsmInfo();
TEW = TM.getELFWriterInfo(); TEW = TM.getELFWriterInfo();
// Create the machine code emitter object for this target. // Create the object code emitter object for this target.
MCE = new ELFCodeEmitter(*this); ElfCE = new ELFCodeEmitter(*this);
// Inital number of sections // Inital number of sections
NumSections = 0; NumSections = 0;
} }
ELFWriter::~ELFWriter() { ELFWriter::~ELFWriter() {
delete MCE; delete ElfCE;
} }
// doInitialization - Emit the file header and all of the global variables for // doInitialization - Emit the file header and all of the global variables for
@ -361,23 +362,13 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { bool ELFWriter::runOnMachineFunction(MachineFunction &MF) {
// Nothing to do here, this is all done through the MCE object above. // Nothing to do here, this is all done through the ElfCE object above.
return false; return false;
} }
/// doFinalization - Now that the module has been completely processed, emit /// doFinalization - Now that the module has been completely processed, emit
/// the ELF file to 'O'. /// the ELF file to 'O'.
bool ELFWriter::doFinalization(Module &M) { bool ELFWriter::doFinalization(Module &M) {
/// FIXME: This should be removed when moving to ObjectCodeEmiter. Since the
/// current ELFCodeEmiter uses CurrBuff, ... it doesn't update S.Data
/// vector size for .text sections, so this is a quick dirty fix
ELFSection &TS = getTextSection();
if (TS.Size) {
BinaryData &BD = TS.getData();
for (unsigned e=0; e<TS.Size; ++e)
BD.push_back(BD[e]);
}
// Emit .data section placeholder // Emit .data section placeholder
getDataSection(); getDataSection();

View File

@ -24,15 +24,16 @@ namespace llvm {
class Constant; class Constant;
class ConstantStruct; class ConstantStruct;
class ELFCodeEmitter; class ELFCodeEmitter;
class ELFRelocation;
class ELFSection;
class ELFSym;
class GlobalVariable; class GlobalVariable;
class Mangler; class Mangler;
class MachineCodeEmitter; class MachineCodeEmitter;
class ObjectCodeEmitter;
class TargetAsmInfo; class TargetAsmInfo;
class TargetELFWriterInfo; class TargetELFWriterInfo;
class raw_ostream; class raw_ostream;
class ELFSection;
class ELFSym;
class ELFRelocation;
/// ELFWriter - This class implements the common target-independent code for /// ELFWriter - This class implements the common target-independent code for
/// writing ELF files. Targets should derive a class from this to /// writing ELF files. Targets should derive a class from this to
@ -43,15 +44,14 @@ namespace llvm {
public: public:
static char ID; static char ID;
MachineCodeEmitter &getMachineCodeEmitter() const { /// Return the ELFCodeEmitter as an instance of ObjectCodeEmitter
return *(MachineCodeEmitter*)MCE; ObjectCodeEmitter *getObjectCodeEmitter() {
return reinterpret_cast<ObjectCodeEmitter*>(ElfCE);
} }
ELFWriter(raw_ostream &O, TargetMachine &TM); ELFWriter(raw_ostream &O, TargetMachine &TM);
~ELFWriter(); ~ELFWriter();
typedef std::vector<unsigned char> DataBuffer;
protected: protected:
/// Output stream to send the resultant object file to. /// Output stream to send the resultant object file to.
raw_ostream &O; raw_ostream &O;
@ -67,7 +67,7 @@ namespace llvm {
/// MCE - The MachineCodeEmitter object that we are exposing to emit machine /// MCE - The MachineCodeEmitter object that we are exposing to emit machine
/// code for functions to the .o file. /// code for functions to the .o file.
ELFCodeEmitter *MCE; ELFCodeEmitter *ElfCE;
/// TAI - Target Asm Info, provide information about section names for /// TAI - Target Asm Info, provide information about section names for
/// globals and other target specific stuff. /// globals and other target specific stuff.