+/// CalculateRelocations - For each MachineRelocation in the current section,
+/// calculate the index of the section containing the object to be relocated,
+/// and the offset into that section. From this information, create the
+/// appropriate target-specific MachORelocation type and add buffer it to be
+/// written out after we are finished writing out sections.
+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.
+ if (MR.isGlobalValue()) {
+ GlobalValue *GV = MR.getGlobalValue();
+ MachOSection *MOSPtr = GVSection[GV];
+ intptr_t Offset = GVOffset[GV];
+
+ // 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);
+ }
+
+ // 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);
+ }
+}
+
+// InitMem - Write the value of a Constant to the specified memory location,
+// converting it into bytes and relocations.
+void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset,
+ const TargetData *TD,
+ std::vector<MachineRelocation> &MRs) {
+ typedef std::pair<const Constant*, intptr_t> CPair;
+ std::vector<CPair> WorkList;
+
+ 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;
+ WorkList.pop_back();
+
+ if (isa<UndefValue>(PC)) {
+ continue;
+ } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(PC)) {
+ unsigned ElementSize =
+ TD->getABITypeSize(CP->getType()->getElementType());
+ for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
+ WorkList.push_back(CPair(CP->getOperand(i), PA+i*ElementSize));
+ } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(PC)) {
+ //
+ // FIXME: Handle ConstantExpression. See EE::getConstantValue()
+ //
+ switch (CE->getOpcode()) {
+ case Instruction::GetElementPtr: {
+ SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end());
+ ScatteredOffset = TD->getIndexedOffset(CE->getOperand(0)->getType(),
+ &Indices[0], Indices.size());
+ WorkList.push_back(CPair(CE->getOperand(0), PA));
+ break;
+ }
+ case Instruction::Add:
+ default:
+ cerr << "ConstantExpr not handled as global var init: " << *CE << "\n";
+ abort();
+ break;
+ }
+ } else if (PC->getType()->isFirstClassType()) {
+ unsigned char *ptr = (unsigned char *)PA;
+ switch (PC->getType()->getTypeID()) {
+ case Type::IntegerTyID: {
+ unsigned NumBits = cast<IntegerType>(PC->getType())->getBitWidth();
+ uint64_t val = cast<ConstantInt>(PC)->getZExtValue();
+ if (NumBits <= 8)
+ ptr[0] = val;
+ else if (NumBits <= 16) {
+ if (TD->isBigEndian())
+ val = ByteSwap_16(val);
+ ptr[0] = val;
+ ptr[1] = val >> 8;
+ } else if (NumBits <= 32) {
+ if (TD->isBigEndian())
+ val = ByteSwap_32(val);
+ ptr[0] = val;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+ } else if (NumBits <= 64) {
+ if (TD->isBigEndian())
+ val = ByteSwap_64(val);
+ ptr[0] = val;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+ ptr[4] = val >> 32;
+ ptr[5] = val >> 40;
+ ptr[6] = val >> 48;
+ ptr[7] = val >> 56;
+ } else {
+ assert(0 && "Not implemented: bit widths > 64");
+ }
+ break;
+ }
+ case Type::FloatTyID: {
+ uint32_t val = cast<ConstantFP>(PC)->getValueAPF().convertToAPInt().
+ getZExtValue();
+ if (TD->isBigEndian())
+ val = ByteSwap_32(val);
+ ptr[0] = val;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+ break;
+ }
+ case Type::DoubleTyID: {
+ uint64_t val = cast<ConstantFP>(PC)->getValueAPF().convertToAPInt().
+ getZExtValue();
+ if (TD->isBigEndian())
+ val = ByteSwap_64(val);
+ ptr[0] = val;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+ ptr[4] = val >> 32;
+ ptr[5] = val >> 40;
+ ptr[6] = val >> 48;
+ ptr[7] = val >> 56;
+ break;
+ }
+ case Type::PointerTyID:
+ if (isa<ConstantPointerNull>(PC))
+ memset(ptr, 0, TD->getPointerSize());
+ else if (const GlobalValue* GV = dyn_cast<GlobalValue>(PC)) {
+ // FIXME: what about function stubs?
+ MRs.push_back(MachineRelocation::getGV(PA-(intptr_t)Addr,
+ MachineRelocation::VANILLA,
+ const_cast<GlobalValue*>(GV),
+ ScatteredOffset));
+ ScatteredOffset = 0;
+ } else
+ assert(0 && "Unknown constant pointer type!");
+ break;
+ default:
+ cerr << "ERROR: Constant unimp for type: " << *PC->getType() << "\n";
+ abort();
+ }
+ } else if (isa<ConstantAggregateZero>(PC)) {
+ memset((void*)PA, 0, (size_t)TD->getABITypeSize(PC->getType()));
+ } else if (const ConstantArray *CPA = dyn_cast<ConstantArray>(PC)) {
+ unsigned ElementSize =
+ TD->getABITypeSize(CPA->getType()->getElementType());
+ for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i)
+ WorkList.push_back(CPair(CPA->getOperand(i), PA+i*ElementSize));
+ } else if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(PC)) {
+ const StructLayout *SL =
+ TD->getStructLayout(cast<StructType>(CPS->getType()));
+ for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++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!");
+ }
+ }
+}
+
+MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect,
+ TargetMachine &TM) :
+ GV(gv), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect),
+ n_desc(0), n_value(0) {
+
+ const TargetAsmInfo *TAI = TM.getTargetAsmInfo();
+
+ switch (GV->getLinkage()) {
+ default:
+ assert(0 && "Unexpected linkage type!");
+ break;
+ case GlobalValue::WeakLinkage:
+ case GlobalValue::LinkOnceLinkage:
+ assert(!isa<Function>(gv) && "Unexpected linkage type for Function!");
+ case GlobalValue::ExternalLinkage:
+ GVName = TAI->getGlobalPrefix() + name;
+ n_type |= GV->hasHiddenVisibility() ? N_PEXT : N_EXT;
+ break;
+ case GlobalValue::InternalLinkage:
+ GVName = TAI->getGlobalPrefix() + name;
+ break;