X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FMachOWriter.cpp;h=0c743759da6c0aef0a4e80fc01edba2e1f9c514e;hb=5c0d6ed325417baa5d119af9c2b6790231d8565f;hp=63f1ad4da8f849835400d77e8bcfd2d1e5b105c5;hpb=6635f35cae9d5a5d363d3ba425d4b1f323fc689d;p=oota-llvm.git diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index 63f1ad4da8f..0c743759da6 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -22,14 +22,15 @@ // //===----------------------------------------------------------------------===// +#include "MachOWriter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/FileWriters.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachOWriter.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetJITInfo.h" #include "llvm/Support/Mangler.h" @@ -37,9 +38,18 @@ #include "llvm/Support/OutputBuffer.h" #include "llvm/Support/Streams.h" #include - using namespace llvm; +/// AddMachOWriter - Concrete function to add the Mach-O writer to the function +/// pass manager. +MachineCodeEmitter *llvm::AddMachOWriter(FunctionPassManager &FPM, + std::ostream &O, + TargetMachine &TM) { + MachOWriter *MOW = new MachOWriter(O, TM); + FPM.add(MOW); + return &MOW->getMachineCodeEmitter(); +} + //===----------------------------------------------------------------------===// // MachOCodeEmitter Implementation //===----------------------------------------------------------------------===// @@ -84,8 +94,8 @@ namespace llvm { isLittleEndian = TM.getTargetData()->isLittleEndian(); } - virtual void startFunction(MachineFunction &F); - virtual bool finishFunction(MachineFunction &F); + virtual void startFunction(MachineFunction &MF); + virtual bool finishFunction(MachineFunction &MF); virtual void addRelocation(const MachineRelocation &MR) { Relocations.push_back(MR); @@ -130,12 +140,15 @@ namespace llvm { /// startFunction - This callback is invoked when a new machine function is /// about to be emitted. -void MachOCodeEmitter::startFunction(MachineFunction &F) { +void MachOCodeEmitter::startFunction(MachineFunction &MF) { + const TargetData *TD = TM.getTargetData(); + const Function *F = MF.getFunction(); + // Align the output buffer to the appropriate alignment, power of 2. - // FIXME: MachineFunction or TargetData should probably carry an alignment - // field for functions that we can query here instead of hard coding 4 in both - // the object writer and asm printer. - unsigned Align = 4; + unsigned FnAlign = F->getAlignment(); + unsigned TDAlign = TD->getPrefTypeAlignment(F->getType()); + unsigned Align = Log2_32(std::max(FnAlign, TDAlign)); + assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); // Get the Mach-O Section that this function belongs in. MachOWriter::MachOSection *MOS = MOW.getTextSection(); @@ -172,7 +185,7 @@ void MachOCodeEmitter::startFunction(MachineFunction &F) { /// finishFunction - This callback is invoked after the function is completely /// finished. -bool MachOCodeEmitter::finishFunction(MachineFunction &F) { +bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { // Get the Mach-O Section that this function belongs in. MachOWriter::MachOSection *MOS = MOW.getTextSection(); @@ -180,16 +193,16 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) { // FIXME: it seems like we should call something like AddSymbolToSection // in startFunction rather than changing the section size and symbol n_value // here. - const GlobalValue *FuncV = F.getFunction(); + const GlobalValue *FuncV = MF.getFunction(); MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index, TM); FnSym.n_value = MOS->size; MOS->size = CurBufferPtr - BufferBegin; // Emit constant pool to appropriate section(s) - emitConstantPool(F.getConstantPool()); + emitConstantPool(MF.getConstantPool()); // Emit jump tables to appropriate section - emitJumpTables(F.getJumpTableInfo()); + emitJumpTables(MF.getJumpTableInfo()); // If we have emitted any relocations to function-specific objects such as // basic blocks, constant pools entries, or jump tables, record their @@ -211,7 +224,10 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) { Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); MR.setResultPointer((void*)Addr); - } else if (!MR.isGlobalValue()) { + } else if (MR.isGlobalValue()) { + // FIXME: This should be a set or something that uniques + MOW.PendingGlobals.push_back(MR.getGlobalValue()); + } else { assert(0 && "Unhandled relocation type"); } MOS->Relocations.push_back(MR); @@ -245,7 +261,7 @@ void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { const Type *Ty = CP[i].getType(); unsigned Size = TM.getTargetData()->getTypeSize(Ty); - MachOWriter::MachOSection *Sec = MOW.getConstSection(Ty); + MachOWriter::MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal); OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); CPLocations.push_back(Sec->SectionData.size()); @@ -301,7 +317,9 @@ void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { // MachOWriter Implementation //===----------------------------------------------------------------------===// -MachOWriter::MachOWriter(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { +char MachOWriter::ID = 0; +MachOWriter::MachOWriter(std::ostream &o, TargetMachine &tm) + : MachineFunctionPass((intptr_t)&ID), O(o), TM(tm) { is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; isLittleEndian = TM.getTargetData()->isLittleEndian(); @@ -318,9 +336,7 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { unsigned Size = TM.getTargetData()->getTypeSize(Ty); unsigned Align = GV->getAlignment(); if (Align == 0) - Align = TM.getTargetData()->getTypeAlignmentPref(Ty); - - MachOSym Sym(GV, Mang->getValueName(GV), Sec->Index, TM); + Align = TM.getTargetData()->getPrefTypeAlignment(Ty); // Reserve space in the .bss section for this symbol while maintaining the // desired section alignment, which must be at least as much as required by @@ -339,12 +355,17 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { for (unsigned i = 0; i < AlignedSize; ++i) SecDataOut.outbyte(0); } + // Globals without external linkage apparently do not go in the symbol table. + if (GV->getLinkage() != GlobalValue::InternalLinkage) { + MachOSym Sym(GV, Mang->getValueName(GV), Sec->Index, TM); + Sym.n_value = Sec->size; + SymbolTable.push_back(Sym); + } + // Record the offset of the symbol, and then allocate space for it. // FIXME: remove when we have unified size + output buffer - Sym.n_value = Sec->size; Sec->size += Size; - SymbolTable.push_back(Sym); - + // Now that we know what section the GlovalVariable is going to be emitted // into, update our mappings. // FIXME: We may also need to update this when outputting non-GlobalVariable @@ -373,12 +394,9 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in // bytes of the symbol. ExtOrCommonSym.n_value = Size; - // If the symbol is external, we'll put it on a list of symbols whose - // addition to the symbol table is being pended until we find a reference - if (NoInit) - PendingSyms.push_back(ExtOrCommonSym); - else - SymbolTable.push_back(ExtOrCommonSym); + SymbolTable.push_back(ExtOrCommonSym); + // Remember that we've seen this symbol + GVOffset[GV] = Size; return; } // Otherwise, this symbol is part of the .bss section. @@ -390,7 +408,8 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { // Scalar read-only data goes in a literal section if the scalar is 4, 8, or // 16 bytes, or a cstring. Other read only data goes into a regular const // section. Read-write data goes in the data section. - MachOSection *Sec = GV->isConstant() ? getConstSection(Ty) : getDataSection(); + MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : + getDataSection(); AddSymbolToSection(Sec, GV); InitMem(GV->getInitializer(), &Sec->SectionData[0], GVOffset[GV], TM.getTargetData(), Sec->Relocations); @@ -511,7 +530,13 @@ void MachOWriter::EmitHeaderAndLoadCommands() { currentAddr += MOS->size; } - // Step #6: Calculate the number of relocations for each section and write out + // Step #6: Emit the symbol table to temporary buffers, so that we know the + // size of the string table when we write the next load command. This also + // sorts and assigns indices to each of the symbols, which is necessary for + // emitting relocations to externally-defined objects. + BufferSymbolAndStringTable(); + + // Step #7: Calculate the number of relocations for each section and write out // the section commands for each section currentAddr += SEG.fileoff; for (std::vector::iterator I = SectionList.begin(), @@ -539,10 +564,6 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(MOS->reserved3); } - // Step #7: Emit the symbol table to temporary buffers, so that we know the - // size of the string table when we write the next load command. - BufferSymbolAndStringTable(); - // Step #8: Emit LC_SYMTAB/LC_DYSYMTAB load commands SymTab.symoff = currentAddr; SymTab.nsyms = SymbolTable.size(); @@ -617,6 +638,17 @@ void MachOWriter::BufferSymbolAndStringTable() { // 2. defined external symbols (sorted by name) // 3. undefined external symbols (sorted by name) + // Before sorting the symbols, check the PendingGlobals for any undefined + // globals that need to be put in the symbol table. + for (std::vector::iterator I = PendingGlobals.begin(), + E = PendingGlobals.end(); I != E; ++I) { + if (GVOffset[*I] == 0 && GVSection[*I] == 0) { + MachOSym UndfSym(*I, Mang->getValueName(*I), MachOSym::NO_SECT, TM); + SymbolTable.push_back(UndfSym); + GVOffset[*I] = -1; + } + } + // Sort the symbols by name, so that when we partition the symbols by scope // of definition, we won't have to sort by name within each partition. std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSymCmp()); @@ -675,14 +707,17 @@ void MachOWriter::BufferSymbolAndStringTable() { OutputBuffer SymTOut(SymT, is64Bit, isLittleEndian); + unsigned index = 0; for (std::vector::iterator I = SymbolTable.begin(), - E = SymbolTable.end(); I != E; ++I) { + E = SymbolTable.end(); I != E; ++I, ++index) { // Add the section base address to the section offset in the n_value field // to calculate the full address. // FIXME: handle symbols where the n_value field is not the address GlobalValue *GV = const_cast(I->GV); if (GV && GVSection[GV]) I->n_value += GVSection[GV]->addr; + if (GV && (GVOffset[GV] == -1)) + GVOffset[GV] = index; // Emit nlist to buffer SymTOut.outword(I->n_strx); @@ -702,11 +737,14 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { for (unsigned i = 0, e = MOS.Relocations.size(); i != e; ++i) { MachineRelocation &MR = MOS.Relocations[i]; unsigned TargetSection = MR.getConstantVal(); + unsigned TargetAddr = 0; + unsigned TargetIndex = 0; // This is a scattered relocation entry if it points to a global value with // a non-zero offset. bool Scattered = false; - + bool Extern = false; + // Since we may not have seen the GlobalValue we were interested in yet at // the time we emitted the relocation for it, fix it up now so that it // points to the offset into the correct section. @@ -714,15 +752,34 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { GlobalValue *GV = MR.getGlobalValue(); MachOSection *MOSPtr = GVSection[GV]; intptr_t Offset = GVOffset[GV]; - Scattered = TargetSection != 0; - - assert(MOSPtr && "Trying to relocate unknown global!"); - TargetSection = MOSPtr->Index; + // If we have never seen the global before, it must be to a symbol + // defined in another module (N_UNDF). + if (!MOSPtr) { + // FIXME: need to append stub suffix + Extern = true; + TargetAddr = 0; + TargetIndex = GVOffset[GV]; + } else { + Scattered = TargetSection != 0; + TargetSection = MOSPtr->Index; + } MR.setResultPointer((void*)Offset); } - GetTargetRelocation(MR, MOS, *SectionList[TargetSection-1], Scattered); + // If the symbol is locally defined, pass in the address of the section and + // the section index to the code which will generate the target relocation. + if (!Extern) { + MachOSection &To = *SectionList[TargetSection - 1]; + TargetAddr = To.addr; + TargetIndex = To.Index; + } + + OutputBuffer RelocOut(MOS.RelocBuffer, is64Bit, isLittleEndian); + OutputBuffer SecOut(MOS.SectionData, is64Bit, isLittleEndian); + + MOS.nreloc += GetTargetRelocation(MR, MOS.Index, TargetAddr, TargetIndex, + RelocOut, SecOut, Scattered, Extern); } } @@ -745,7 +802,7 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, if (isa(PC)) { continue; - } else if (const ConstantPacked *CP = dyn_cast(PC)) { + } else if (const ConstantVector *CP = dyn_cast(PC)) { unsigned ElementSize = TD->getTypeSize(CP->getType()->getElementType()); for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) WorkList.push_back(CPair(CP->getOperand(i), PA+i*ElementSize)); @@ -755,9 +812,9 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, // switch (CE->getOpcode()) { case Instruction::GetElementPtr: { - std::vector Indexes(CE->op_begin()+1, CE->op_end()); + SmallVector Indices(CE->op_begin()+1, CE->op_end()); ScatteredOffset = TD->getIndexedOffset(CE->getOperand(0)->getType(), - Indexes); + &Indices[0], Indices.size()); WorkList.push_back(CPair(CE->getOperand(0), PA)); break; } @@ -804,7 +861,8 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, break; } case Type::FloatTyID: { - uint64_t val = FloatToBits(cast(PC)->getValue()); + uint32_t val = cast(PC)->getValueAPF().convertToAPInt(). + getZExtValue(); if (TD->isBigEndian()) val = ByteSwap_32(val); ptr[0] = val; @@ -814,7 +872,8 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, break; } case Type::DoubleTyID: { - uint64_t val = DoubleToBits(cast(PC)->getValue()); + uint64_t val = cast(PC)->getValueAPF().convertToAPInt(). + getZExtValue(); if (TD->isBigEndian()) val = ByteSwap_64(val); ptr[0] = val; @@ -854,7 +913,8 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, const StructLayout *SL = TD->getStructLayout(cast(CPS->getType())); for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) - WorkList.push_back(CPair(CPS->getOperand(i), PA+SL->MemberOffsets[i])); + WorkList.push_back(CPair(CPS->getOperand(i), + PA+SL->getElementOffset(i))); } else { cerr << "Bad Type: " << *PC->getType() << "\n"; assert(0 && "Unknown constant type to initialize memory with!");