Index: lib/Target/X86/X86MCInstLower.cpp |
diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp |
index b853110fac332a3eca0f2610bba7277bfc94f8e1..93c2e8a38effac5d633c9e762708499b89e80ab9 100644 |
--- a/lib/Target/X86/X86MCInstLower.cpp |
+++ b/lib/Target/X86/X86MCInstLower.cpp |
@@ -689,6 +689,18 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, |
MCContext &context = OutStreamer.getContext(); |
+ // @LOCALMOD-START |
+ // TODO(dschuff): Instead of testing the target OS we should add (upstream) a |
+ // method to one of the MC classes to test whether bundle alignment is enabled |
+ // (currently only the AsmBackend has this, which can't be used when emitting |
+ // asm files). That facility should be used here and in MCAsmStreamer.cpp |
+ // (this should be done once we are unblocked from switching to gas by |
+ // default, so we know exactly where we need it). |
+ Triple TT(getSubtargetInfo().getTargetTriple()); |
+ const bool needsBundleLock = TT.getOS() == Triple::NaCl; |
+ if (needsBundleLock) |
+ OutStreamer.EmitBundleLock(false); |
+ // @LOCALMOD-END |
if (needsPadding) |
EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); |
@@ -755,6 +767,10 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, |
EmitAndCountInstruction(MCInstBuilder(is64Bits ? X86::CALL64pcrel32 |
: X86::CALLpcrel32) |
.addExpr(tlsRef)); |
+ // @LOCALMOD-START |
+ if (needsBundleLock) |
+ OutStreamer.EmitBundleUnlock(); |
+ // @LOCALMOD-END |
} |
/// \brief Emit the optimal amount of multi-byte nops on X86. |
@@ -1071,6 +1087,29 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { |
// MYGLOBAL + (. - PICBASE) |
// However, we can't generate a ".", so just emit a new label here and refer |
// to it. |
+ |
+ // @LOCALMOD-START |
+ // When using the gas assembler, emitting a new label and then using it in |
+ // the difference expression gives the wrong value when the instruction |
+ // following the label gets bundle padding added to it. (The label will |
+ // point to the nop padding instead of the instruction, which works when |
+ // jumping to the label, but not when calculating GOT addresses. See |
+ // https://code.google.com/p/nativeclient/issues/detail?id=3982) For this |
+ // case, just emit the instruction using the "." directly rather than going |
+ // through all the MC layers. The LLVM assembler is smart enough to make the |
+ // label point to the actual instruction rather than the nop, so this hack |
+ // isn't necessary. |
+ if (Subtarget->isTargetNaCl32() && |
+ OutStreamer.hasRawTextSupport()) { |
+ std::string OS; |
+ raw_string_ostream ROS(OS); |
+ ROS << "\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-" << *MF->getPICBaseSymbol() |
+ << "), %" |
+ << X86ATTInstPrinter::getRegisterName(MI->getOperand(0).getReg()); |
+ OutStreamer.EmitRawText(ROS.str()); |
+ return; |
+ } |
+ // @LOCALMOD-END |
MCSymbol *DotSym = OutContext.CreateTempSymbol(); |
OutStreamer.EmitLabel(DotSym); |