+ // Encode the new instruction.
+ //
+ // FIXME-PERF: If it matters, we could let the target do this. It can
+ // probably do so more efficiently in many cases.
+ SmallVector<MCFixup, 4> Fixups;
+ SmallString<256> Code;
+ raw_svector_ostream VecOS(Code);
+ getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
+ VecOS.flush();
+
+ // Update the fragment.
+ F.setInst(Relaxed);
+ F.getContents() = Code;
+ F.getFixups() = Fixups;
+
+ return true;
+}
+
+bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
+ int64_t Value = 0;
+ uint64_t OldSize = LF.getContents().size();
+ bool IsAbs = LF.getValue().EvaluateAsAbsolute(Value, Layout);
+ (void)IsAbs;
+ assert(IsAbs);
+ SmallString<8> &Data = LF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
+ if (LF.isSigned())
+ encodeSLEB128(Value, OSE);
+ else
+ encodeULEB128(Value, OSE);
+ OSE.flush();
+ return OldSize != LF.getContents().size();
+}
+
+bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
+ MCDwarfLineAddrFragment &DF) {
+ MCContext &Context = Layout.getAssembler().getContext();
+ int64_t AddrDelta = 0;
+ uint64_t OldSize = DF.getContents().size();
+ bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout);
+ (void)IsAbs;
+ assert(IsAbs);
+ int64_t LineDelta;
+ LineDelta = DF.getLineDelta();
+ SmallString<8> &Data = DF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
+ MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OSE);
+ OSE.flush();
+ return OldSize != Data.size();
+}
+
+bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
+ MCDwarfCallFrameFragment &DF) {
+ MCContext &Context = Layout.getAssembler().getContext();
+ int64_t AddrDelta = 0;
+ uint64_t OldSize = DF.getContents().size();
+ bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout);
+ (void)IsAbs;
+ assert(IsAbs);
+ SmallString<8> &Data = DF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
+ MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
+ OSE.flush();
+ return OldSize != Data.size();
+}
+
+bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) {
+ // Holds the first fragment which needed relaxing during this layout. It will
+ // remain NULL if none were relaxed.
+ // When a fragment is relaxed, all the fragments following it should get
+ // invalidated because their offset is going to change.
+ MCFragment *FirstRelaxedFragment = NULL;
+
+ // Attempt to relax all the fragments in the section.
+ for (MCSectionData::iterator I = SD.begin(), IE = SD.end(); I != IE; ++I) {
+ // Check if this is a fragment that needs relaxation.
+ bool RelaxedFrag = false;
+ switch(I->getKind()) {
+ default:
+ break;
+ case MCFragment::FT_Relaxable:
+ assert(!getRelaxAll() &&
+ "Did not expect a MCRelaxableFragment in RelaxAll mode");
+ RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I));
+ break;
+ case MCFragment::FT_Dwarf:
+ RelaxedFrag = relaxDwarfLineAddr(Layout,
+ *cast<MCDwarfLineAddrFragment>(I));
+ break;
+ case MCFragment::FT_DwarfFrame:
+ RelaxedFrag =
+ relaxDwarfCallFrameFragment(Layout,
+ *cast<MCDwarfCallFrameFragment>(I));
+ break;
+ case MCFragment::FT_LEB:
+ RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
+ break;
+ }
+ if (RelaxedFrag && !FirstRelaxedFragment)
+ FirstRelaxedFragment = I;
+ }
+ if (FirstRelaxedFragment) {
+ Layout.invalidateFragmentsFrom(FirstRelaxedFragment);
+ return true;
+ }
+ return false;
+}
+
+bool MCAssembler::layoutOnce(MCAsmLayout &Layout) {
+ ++stats::RelaxationSteps;