diff --git a/llvm/include/llvm/CodeGen/MachOWriter.h b/llvm/include/llvm/CodeGen/MachOWriter.h index 5ec4f5033182..0d13c909a94c 100644 --- a/llvm/include/llvm/CodeGen/MachOWriter.h +++ b/llvm/include/llvm/CodeGen/MachOWriter.h @@ -307,16 +307,25 @@ namespace llvm { uint8_t r_length; // length = 2 ^ r_length bool r_extern; // uint8_t r_type; // if not 0, machine-specific relocation type. + bool r_scattered; // 1 = scattered, 0 = non-scattered + int32_t r_value; // the value the item to be relocated is referring + // to. - uint32_t getPackedFields() { - return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) | - (r_extern << 4) | (r_type & 15); + uint32_t getPackedFields() { + if (r_scattered) + return (1 << 31) | (r_pcrel << 30) | ((r_length & 3) << 28) | + ((r_type & 15) << 24) | (r_address & 0x00FFFFFF); + else + return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) | + (r_extern << 4) | (r_type & 15); } + uint32_t getAddress() { return r_scattered ? r_value : r_address; } MachORelocation(uint32_t addr, uint32_t index, bool pcrel, uint8_t len, - bool ext, uint8_t type) : r_address(addr), - r_symbolnum(index), r_pcrel(pcrel), r_length(len), r_extern(ext), - r_type(type) {} + bool ext, uint8_t type, bool scattered = false, + int32_t value = 0) : + r_address(addr), r_symbolnum(index), r_pcrel(pcrel), r_length(len), + r_extern(ext), r_type(type), r_scattered(scattered), r_value(value) {} }; /// MachOSection - This struct contains information about each section in a @@ -621,7 +630,7 @@ namespace llvm { return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB); } virtual void GetTargetRelocation(MachineRelocation &MR, MachOSection &From, - MachOSection &To) = 0; + MachOSection &To, bool Scattered) = 0; }; } diff --git a/llvm/lib/CodeGen/MachOWriter.cpp b/llvm/lib/CodeGen/MachOWriter.cpp index bc54728f58ba..63f1ad4da8f8 100644 --- a/llvm/lib/CodeGen/MachOWriter.cpp +++ b/llvm/lib/CodeGen/MachOWriter.cpp @@ -145,6 +145,15 @@ void MachOCodeEmitter::startFunction(MachineFunction &F) { BufferBegin = &MOS->SectionData[0]; BufferEnd = BufferBegin + MOS->SectionData.capacity(); + // Upgrade the section alignment if required. + if (MOS->align < Align) MOS->align = Align; + + // Round the size up to the correct alignment for starting the new function. + if ((MOS->size & ((1 << Align) - 1)) != 0) { + MOS->size += (1 << Align); + MOS->size &= ~((1 << Align) - 1); + } + // FIXME: Using MOS->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 @@ -154,9 +163,6 @@ void MachOCodeEmitter::startFunction(MachineFunction &F) { // AddSymbolToSection to prevent calling it on the text section. CurBufferPtr = BufferBegin + MOS->size; - // Upgrade the section alignment if required. - if (MOS->align < Align) MOS->align = Align; - // Clear per-function data structures. CPLocations.clear(); CPSections.clear(); @@ -170,12 +176,15 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) { // Get the Mach-O Section that this function belongs in. MachOWriter::MachOSection *MOS = MOW.getTextSection(); - MOS->size += CurBufferPtr - BufferBegin; - // Get a symbol for the function to add to the symbol table + // 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(); 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()); @@ -635,6 +644,7 @@ void MachOWriter::BufferSymbolAndStringTable() { if (PartitionByLocal(*I)) { ++DySymTab.nlocalsym; ++DySymTab.iextdefsym; + ++DySymTab.iundefsym; } else if (PartitionByDefined(*I)) { ++DySymTab.nextdefsym; ++DySymTab.iundefsym; @@ -692,6 +702,10 @@ 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(); + + // This is a scattered relocation entry if it points to a global value with + // a non-zero offset. + bool Scattered = 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 @@ -699,15 +713,16 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { if (MR.isGlobalValue()) { GlobalValue *GV = MR.getGlobalValue(); MachOSection *MOSPtr = GVSection[GV]; - intptr_t offset = GVOffset[GV]; + intptr_t Offset = GVOffset[GV]; + Scattered = TargetSection != 0; assert(MOSPtr && "Trying to relocate unknown global!"); TargetSection = MOSPtr->Index; - MR.setResultPointer((void*)offset); + MR.setResultPointer((void*)Offset); } - GetTargetRelocation(MR, MOS, *SectionList[TargetSection-1]); + GetTargetRelocation(MR, MOS, *SectionList[TargetSection-1], Scattered); } } @@ -721,6 +736,8 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, WorkList.push_back(CPair(C,(intptr_t)Addr + Offset)); + intptr_t ScatteredOffset = 0; + while (!WorkList.empty()) { const Constant *PC = WorkList.back().first; intptr_t PA = WorkList.back().second; @@ -737,7 +754,13 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, // FIXME: Handle ConstantExpression. See EE::getConstantValue() // switch (CE->getOpcode()) { - case Instruction::GetElementPtr: + case Instruction::GetElementPtr: { + std::vector Indexes(CE->op_begin()+1, CE->op_end()); + ScatteredOffset = TD->getIndexedOffset(CE->getOperand(0)->getType(), + Indexes); + WorkList.push_back(CPair(CE->getOperand(0), PA)); + break; + } case Instruction::Add: default: cerr << "ConstantExpr not handled as global var init: " << *CE << "\n"; @@ -805,14 +828,16 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, break; } case Type::PointerTyID: - if (isa(C)) + if (isa(PC)) memset(ptr, 0, TD->getPointerSize()); - else if (const GlobalValue* GV = dyn_cast(C)) + else if (const GlobalValue* GV = dyn_cast(PC)) { // FIXME: what about function stubs? MRs.push_back(MachineRelocation::getGV(PA-(intptr_t)Addr, MachineRelocation::VANILLA, - const_cast(GV))); - else + const_cast(GV), + ScatteredOffset)); + ScatteredOffset = 0; + } else assert(0 && "Unknown constant pointer type!"); break; default: @@ -853,10 +878,10 @@ MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, assert(!isa(gv) && "Unexpected linkage type for Function!"); case GlobalValue::ExternalLinkage: GVName = TAI->getGlobalPrefix() + name; - n_type |= N_EXT; + n_type |= GV->hasHiddenVisibility() ? N_PEXT : N_EXT; break; case GlobalValue::InternalLinkage: - GVName = TAI->getPrivateGlobalPrefix() + name; + GVName = TAI->getGlobalPrefix() + name; break; } } diff --git a/llvm/lib/Target/PowerPC/PPCMachOWriter.cpp b/llvm/lib/Target/PowerPC/PPCMachOWriter.cpp index c3cc74e156a8..9a1a608db10d 100644 --- a/llvm/lib/Target/PowerPC/PPCMachOWriter.cpp +++ b/llvm/lib/Target/PowerPC/PPCMachOWriter.cpp @@ -27,7 +27,7 @@ namespace { : MachOWriter(O, TM) {} virtual void GetTargetRelocation(MachineRelocation &MR, MachOSection &From, - MachOSection &To); + MachOSection &To, bool Scattered); // Constants for the relocation r_type field. // see @@ -59,7 +59,8 @@ void llvm::addPPCMachOObjectWriterPass(FunctionPassManager &FPM, /// by that relocation type. void PPCMachOWriter::GetTargetRelocation(MachineRelocation &MR, MachOSection &From, - MachOSection &To) { + MachOSection &To, + bool Scattered) { uint64_t Addr = 0; // Keep track of whether or not this is an externally defined relocation. @@ -77,18 +78,30 @@ void PPCMachOWriter::GetTargetRelocation(MachineRelocation &MR, case PPC::reloc_vanilla: { // FIXME: need to handle 64 bit vanilla relocs - MachORelocation VANILLA(MR.getMachineCodeOffset(), To.Index, false, 2, - isExtern, PPC_RELOC_VANILLA); + MachORelocation VANILLA(MR.getMachineCodeOffset(), To.Index, false, 2, + isExtern, PPC_RELOC_VANILLA, Scattered, + (intptr_t)MR.getResultPointer()); ++From.nreloc; - OutputBuffer RelocOut(From.RelocBuffer, is64Bit, isLittleEndian); - RelocOut.outword(VANILLA.r_address); - RelocOut.outword(VANILLA.getPackedFields()); - OutputBuffer SecOut(From.SectionData, is64Bit, isLittleEndian); - SecOut.fixword(Addr, MR.getMachineCodeOffset()); - break; + + if (Scattered) { + RelocOut.outword(VANILLA.getPackedFields()); + RelocOut.outword(VANILLA.getAddress()); + } else { + RelocOut.outword(VANILLA.getAddress()); + RelocOut.outword(VANILLA.getPackedFields()); + } + + intptr_t SymbolOffset; + if (Scattered) + SymbolOffset = Addr + MR.getConstantVal(); + else + SymbolOffset = Addr; + printf("vanilla fixup: sec_%x[%x] = %x\n", From.Index, unsigned(MR.getMachineCodeOffset()), (unsigned)SymbolOffset); + SecOut.fixword(SymbolOffset, MR.getMachineCodeOffset()); } + break; case PPC::reloc_pcrel_bx: { Addr -= MR.getMachineCodeOffset(); @@ -124,7 +137,6 @@ void PPCMachOWriter::GetTargetRelocation(MachineRelocation &MR, RelocOut.outword(HA16.getPackedFields()); RelocOut.outword(PAIR.r_address); RelocOut.outword(PAIR.getPackedFields()); - printf("ha16: %x\n", (unsigned)Addr); Addr += 0x8000; OutputBuffer SecOut(From.SectionData, is64Bit, isLittleEndian); @@ -145,7 +157,6 @@ void PPCMachOWriter::GetTargetRelocation(MachineRelocation &MR, RelocOut.outword(LO16.getPackedFields()); RelocOut.outword(PAIR.r_address); RelocOut.outword(PAIR.getPackedFields()); - printf("lo16: %x\n", (unsigned)Addr); OutputBuffer SecOut(From.SectionData, is64Bit, isLittleEndian); SecOut.fixhalf(Addr, MR.getMachineCodeOffset() + 2);