Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -645,6 +645,14 @@ const MCSubtargetInfo &STI) : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { MCAssembler &MCA = getStreamer().getAssembler(); + + // It's possible that MCObjectFileInfo isn't fully initialized at this point + // due to an initialization order problem where LLVMTargetMachine creates the + // target streamer before TargetLoweringObjectFile calls + // InitializeMCObjectFileInfo. There doesn't seem to be a single place that + // covers all cases so this statement covers most cases and direct object + // emission must call setPic() once MCObjectFileInfo has been initialized. The + // cases we don't handle here are covered by MipsAsmPrinter. Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; const FeatureBitset &Features = STI.getFeatureBits(); Index: lib/Target/Mips/MipsAsmPrinter.cpp =================================================================== --- lib/Target/Mips/MipsAsmPrinter.cpp +++ lib/Target/Mips/MipsAsmPrinter.cpp @@ -669,6 +669,12 @@ } void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { + MipsTargetStreamer &TS = getTargetStreamer(); + + // MipsTargetStreamer has an initialization order problem when emitting an + // object file directly (see MipsTargetELFStreamer for full details). Work + // around it by re-initializing the PIC state here. + TS.setPic(OutContext.getObjectFileInfo()->getRelocM()); // Compute MIPS architecture attributes based on the default subtarget // that we'd have constructed. Module level directives aren't LTO @@ -684,14 +690,14 @@ bool IsABICalls = STI.isABICalls(); const MipsABIInfo &ABI = MTM.getABI(); if (IsABICalls) { - getTargetStreamer().emitDirectiveAbiCalls(); + TS.emitDirectiveAbiCalls(); Reloc::Model RM = TM.getRelocationModel(); // FIXME: This condition should be a lot more complicated that it is here. // Ideally it should test for properties of the ABI and not the ABI // itself. // For the moment, I'm only correcting enough to make MIPS-IV work. if (RM == Reloc::Static && !ABI.IsN64()) - getTargetStreamer().emitDirectiveOptionPic0(); + TS.emitDirectiveOptionPic0(); } // Tell the assembler which ABI we are using @@ -702,8 +708,8 @@ // NaN: At the moment we only support: // 1. .nan legacy (default) // 2. .nan 2008 - STI.isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008() - : getTargetStreamer().emitDirectiveNaNLegacy(); + STI.isNaN2008() ? TS.emitDirectiveNaN2008() + : TS.emitDirectiveNaNLegacy(); // TODO: handle O64 ABI @@ -716,19 +722,19 @@ ELF::SHT_PROGBITS, 0)); } - getTargetStreamer().updateABIInfo(STI); + TS.updateABIInfo(STI); // We should always emit a '.module fp=...' but binutils 2.24 does not accept // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or // -mfp64) and omit it otherwise. if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) - getTargetStreamer().emitDirectiveModuleFP(); + TS.emitDirectiveModuleFP(); // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not // accept it. We therefore emit it when it contradicts the default or an // option has changed the default (i.e. FPXX) and omit it otherwise. if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) - getTargetStreamer().emitDirectiveModuleOddSPReg(); + TS.emitDirectiveModuleOddSPReg(); } void MipsAsmPrinter::emitInlineAsmStart() const { Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -24,6 +24,9 @@ class MipsTargetStreamer : public MCTargetStreamer { public: MipsTargetStreamer(MCStreamer &S); + + virtual void setPic(bool Value) {} + virtual void emitDirectiveSetMicroMips(); virtual void emitDirectiveSetNoMicroMips(); virtual void emitDirectiveSetMips16(); @@ -260,6 +263,8 @@ MCELFStreamer &getStreamer(); MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); + void setPic(bool Value) override { Pic = Value; } + void emitLabel(MCSymbol *Symbol) override; void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void finish() override; Index: test/MC/Mips/init-order-bug.ll =================================================================== --- /dev/null +++ test/MC/Mips/init-order-bug.ll @@ -0,0 +1,12 @@ +; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=pic -filetype=asm < %s | \ +; RUN: llvm-mc -triple=mipsel-linux-gnu -relocation-model=pic -filetype=obj | \ +; RUN: llvm-objdump -d - | FileCheck %s +; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=pic -filetype=obj < %s | \ +; RUN: llvm-objdump -d - | FileCheck %s + +define void @foo() { + call void asm sideeffect "\09.cprestore 512", "~{$1}"() + ret void +} + +; CHECK: sw $gp, 512($sp)