From aa507db59e085b1a6c728c2becef76e6dd9ab03a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 11 Jul 2005 05:17:18 +0000 Subject: [PATCH] add code to emit the .text section to the section header. Add a *VERY INITIAL* machine code emitter class. This is enough to take this C function: int foo(int X) { return X +1; } and make objdump produce the following: $ objdump -d t-llvm.o t-llvm.o: file format elf32-i386 Disassembly of section .text: 00000000 <.text>: 0: b8 01 00 00 00 mov $0x1,%eax 5: 03 44 24 04 add 0x4(%esp,1),%eax 9: c3 ret Anything using branches or refering to the constant pool or requiring relocations will not work yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22375 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ELFWriter.cpp | 93 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index bdf38fe6433..96668e29ecb 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -34,16 +34,92 @@ #include "llvm/CodeGen/ELFWriter.h" #include "llvm/Module.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Mangler.h" using namespace llvm; +namespace llvm { + class ELFCodeEmitter : public MachineCodeEmitter { + ELFWriter &EW; + std::vector &OutputBuffer; + size_t FnStart; + public: + ELFCodeEmitter(ELFWriter &ew) : EW(ew), OutputBuffer(EW.OutputBuffer) {} + + void startFunction(MachineFunction &F) { + // Align the output buffer to the appropriate alignment. + unsigned Align = 16; // FIXME: GENERICIZE!! + ELFWriter::ELFSection &TextSection = EW.SectionList.back(); + + // Upgrade the section alignment if required. + if (TextSection.Align < Align) TextSection.Align = Align; + + // Add padding zeros to the end of the buffer to make sure that the + // function will start on the correct byte alignment within the section. + size_t SectionOff = OutputBuffer.size()-TextSection.Offset; + if (SectionOff & (Align-1)) { + // Add padding to get alignment to the correct place. + size_t Pad = Align-(SectionOff & (Align-1)); + OutputBuffer.resize(OutputBuffer.size()+Pad); + } + + FnStart = OutputBuffer.size(); + } + void finishFunction(MachineFunction &F) {} + void emitConstantPool(MachineConstantPool *MCP) { + if (MCP->isEmpty()) return; + assert(0 && "unimp"); + } + virtual void emitByte(unsigned char B) { + OutputBuffer.push_back(B); + } + virtual void emitWordAt(unsigned W, unsigned *Ptr) { + assert(0 && "ni"); + } + virtual void emitWord(unsigned W) { + assert(0 && "ni"); + } + virtual uint64_t getCurrentPCValue() { + return OutputBuffer.size(); + } + virtual uint64_t getCurrentPCOffset() { + return OutputBuffer.size()-FnStart; + } + void addRelocation(const MachineRelocation &MR) { + assert(0 && "relo not handled yet!"); + } + virtual uint64_t getConstantPoolEntryAddress(unsigned Index) { + assert(0 && "CP not implementated yet!"); + } + /// JIT SPECIFIC FUNCTIONS + void startFunctionStub(unsigned StubSize) { + assert(0 && "JIT specific function called!"); + abort(); + } + void *finishFunctionStub(const Function *F) { + assert(0 && "JIT specific function called!"); + abort(); + return 0; + } + }; +} + + ELFWriter::ELFWriter(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { e_machine = 0; // e_machine defaults to 'No Machine' e_flags = 0; // e_flags defaults to 0, no flags. is64Bit = TM.getTargetData().getPointerSizeInBits() == 64; isLittleEndian = TM.getTargetData().isLittleEndian(); + + // Create the machine code emitter object for this target. + MCE = new ELFCodeEmitter(*this); +} + +ELFWriter::~ELFWriter() { + delete MCE; } // doInitialization - Emit the file header and all of the global variables for @@ -91,9 +167,8 @@ bool ELFWriter::doInitialization(Module &M) { // entry. SymbolTable.push_back(ELFSym(0)); + SectionList.push_back(ELFSection(".text", OutputBuffer.size())); - - // FIXME: Should start the .text section. return false; } @@ -180,14 +255,24 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV, ELFSection &DataSection, bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { + // Nothing to do here, this is all done through the MCE object above. return false; } /// doFinalization - Now that the module has been completely processed, emit /// the ELF file to 'O'. bool ELFWriter::doFinalization(Module &M) { - // Okay, the .text section has now been finalized. - // FIXME: finalize the .text section. + // Okay, the .text section has now been finalized. If it contains nothing, do + // not emit it. + uint64_t TextSize = OutputBuffer.size() - SectionList.back().Offset; + if (TextSize == 0) { + SectionList.pop_back(); + } else { + ELFSection &Text = SectionList.back(); + Text.Size = TextSize; + Text.Type = ELFSection::SHT_PROGBITS; + Text.Flags = ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC; + } // Okay, the ELF header and .text sections have been completed, build the // .data, .bss, and "common" sections next.