return false;
}
+static bool isThumb(const MCSubtargetInfo& STI) {
+ return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
+}
+
+void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
+ MCSubtargetInfo *EndInfo) const {
+ // If either end mode is unknown (EndInfo == NULL) or different than
+ // the start mode, then restore the start mode.
+ const bool WasThumb = isThumb(StartInfo);
+ if (EndInfo == NULL || WasThumb != isThumb(*EndInfo)) {
+ OutStreamer.EmitAssemblerFlag(WasThumb ? MCAF_Code16 : MCAF_Code32);
+ if (EndInfo)
+ EndInfo->ToggleFeature(ARM::ModeThumb);
+ }
+}
+
void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
if (Subtarget->isTargetMachO()) {
Reloc::Model RelocM = TM.getRelocationModel();
}
// Compiling with debug info should not affect the code
- // generation! Since some of the data sections are first switched
- // to only in ASMPrinter::doFinalization(), the debug info
- // sections would come before the data sections in the object
- // file. This is problematic, since PC-relative loads have to use
- // different instruction sequences in order to reach global data
- // in the same object file.
+ // generation. Ensure the cstring section comes before the
+ // optional __DWARF secion. Otherwise, PC-relative loads would
+ // have to use different instruction sequences at "-g" in order to
+ // reach global data in the same object file.
OutStreamer.SwitchSection(getObjFileLowering().getCStringSection());
- OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
- OutStreamer.SwitchSection(getObjFileLowering().getDataCommonSection());
- OutStreamer.SwitchSection(getObjFileLowering().getDataBSSSection());
- OutStreamer.SwitchSection(getObjFileLowering().getNonLazySymbolPointerSection());
}
// Use unified assembler syntax.
// FIXME: add more flags to ARMBuildAttributes.h
// 8-bytes alignment stuff.
- ATS.emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
- ATS.emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1);
// ABI_HardFP_use attribute to indicate single precision FP.
if (Subtarget->isFPOnlySP())
if (Subtarget->hasMPExtension())
ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
- if (Subtarget->hasDivide()) {
- // Check if hardware divide is only available in thumb2 or ARM as well.
- ATS.emitAttribute(ARMBuildAttrs::DIV_use,
- Subtarget->hasDivideInARMMode() ? ARMBuildAttrs::AllowDIVExt :
- ARMBuildAttrs::AllowDIVIfExists);
- }
+ // Hardware divide in ARM mode is part of base arch, starting from ARMv8.
+ // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
+ // It is not possible to produce DisallowDIV: if hwdiv is present in the base
+ // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
+ // AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
+ // otherwise, the default value (AllowDIVIfExists) applies.
+ if (Subtarget->hasDivideInARMMode() && !Subtarget->hasV8Ops())
+ ATS.emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);
if (Subtarget->hasTrustZone() && Subtarget->hasVirtualization())
ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
ATS.finishAttributeSection();
}
-void ARMAsmPrinter::emitARMAttributeSection() {
- // <format-version>
- // [ <section-length> "vendor-name"
- // [ <file-tag> <size> <attribute>*
- // | <section-tag> <size> <section-number>* 0 <attribute>*
- // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
- // ]+
- // ]*
-
- if (OutStreamer.hasRawTextSupport())
- return;
-
- const ARMElfTargetObjectFile &TLOFELF =
- static_cast<const ARMElfTargetObjectFile &>
- (getObjFileLowering());
-
- OutStreamer.SwitchSection(TLOFELF.getAttributesSection());
-
- // Format version
- OutStreamer.EmitIntValue(0x41, 1);
-}
-
//===----------------------------------------------------------------------===//
static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
OutContext);
// If this isn't a TBB or TBH, the entries are direct branch instructions.
if (OffsetWidth == 4) {
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2B)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::t2B)
.addExpr(MBBSymbolExpr)
.addImm(ARMCC::AL)
.addReg(0));
case ARM::t2LEApcrel: {
// FIXME: Need to also handle globals and externals
MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
- OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() ==
+ EmitToStreamer(OutStreamer, MCInstBuilder(MI->getOpcode() ==
ARM::t2LEApcrel ? ARM::t2ADR
: (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
: ARM::ADR))
MCSymbol *JTIPICSymbol =
GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(),
MI->getOperand(2).getImm());
- OutStreamer.EmitInstruction(MCInstBuilder(MI->getOpcode() ==
+ EmitToStreamer(OutStreamer, MCInstBuilder(MI->getOpcode() ==
ARM::t2LEApcrelJT ? ARM::t2ADR
: (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
: ARM::ADR))
// Darwin call instructions are just normal call instructions with different
// clobber semantics (they clobber R9).
case ARM::BX_CALL: {
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
.addReg(ARM::LR)
.addReg(ARM::PC)
// Add predicate operands.
// Add 's' bit operand (always reg0 for this)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::BX)
.addReg(MI->getOperand(0).getReg()));
return;
}
case ARM::tBX_CALL: {
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
.addReg(ARM::LR)
.addReg(ARM::PC)
// Add predicate operands.
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tBX)
.addReg(MI->getOperand(0).getReg())
// Add predicate operands.
.addImm(ARMCC::AL)
return;
}
case ARM::BMOVPCRX_CALL: {
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
.addReg(ARM::LR)
.addReg(ARM::PC)
// Add predicate operands.
// Add 's' bit operand (always reg0 for this)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
.addReg(ARM::PC)
.addReg(MI->getOperand(0).getReg())
// Add predicate operands.
return;
}
case ARM::BMOVPCB_CALL: {
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
.addReg(ARM::LR)
.addReg(ARM::PC)
// Add predicate operands.
const GlobalValue *GV = MI->getOperand(0).getGlobal();
MCSymbol *GVSym = getSymbol(GV);
const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::Bcc)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::Bcc)
.addExpr(GVSymExpr)
// Add predicate operands.
.addImm(ARMCC::AL)
TmpInst.addOperand(MCOperand::CreateReg(0));
// Add 's' bit operand (always reg0 for this)
TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.EmitInstruction(TmpInst);
+ EmitToStreamer(OutStreamer, TmpInst);
return;
}
case ARM::MOVTi16_ga_pcrel:
TmpInst.addOperand(MCOperand::CreateReg(0));
// Add 's' bit operand (always reg0 for this)
TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.EmitInstruction(TmpInst);
+ EmitToStreamer(OutStreamer, TmpInst);
return;
}
case ARM::tPICADD: {
OutContext));
// Form and emit the add.
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDhirr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tADDhirr)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(0).getReg())
.addReg(ARM::PC)
OutContext));
// Form and emit the add.
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDrr)
.addReg(MI->getOperand(0).getReg())
.addReg(ARM::PC)
.addReg(MI->getOperand(1).getReg())
case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
}
- OutStreamer.EmitInstruction(MCInstBuilder(Opcode)
+ EmitToStreamer(OutStreamer, MCInstBuilder(Opcode)
.addReg(MI->getOperand(0).getReg())
.addReg(ARM::PC)
.addReg(MI->getOperand(1).getReg())
}
case ARM::t2BR_JT: {
// Lower and emit the instruction itself, then the jump table following it.
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
.addReg(ARM::PC)
.addReg(MI->getOperand(0).getReg())
// Add predicate operands.
}
case ARM::t2TBB_JT: {
// Lower and emit the instruction itself, then the jump table following it.
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBB)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::t2TBB)
.addReg(ARM::PC)
.addReg(MI->getOperand(0).getReg())
// Add predicate operands.
}
case ARM::t2TBH_JT: {
// Lower and emit the instruction itself, then the jump table following it.
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::t2TBH)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::t2TBH)
.addReg(ARM::PC)
.addReg(MI->getOperand(0).getReg())
// Add predicate operands.
// Add 's' bit operand (always reg0 for this)
if (Opc == ARM::MOVr)
TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.EmitInstruction(TmpInst);
+ EmitToStreamer(OutStreamer, TmpInst);
// Make sure the Thumb jump table is 4-byte aligned.
if (Opc == ARM::tMOVr)
// Add predicate operands.
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
TmpInst.addOperand(MCOperand::CreateReg(0));
- OutStreamer.EmitInstruction(TmpInst);
+ EmitToStreamer(OutStreamer, TmpInst);
// Output the data for the jump table itself
EmitJumpTable(MI);
case ARM::BR_JTadd: {
// Lower and emit the instruction itself, then the jump table following it.
// add pc, target, idx
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDrr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDrr)
.addReg(ARM::PC)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
unsigned ValReg = MI->getOperand(1).getReg();
MCSymbol *Label = GetARMSJLJEHLabel();
OutStreamer.AddComment("eh_setjmp begin");
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
.addReg(ValReg)
.addReg(ARM::PC)
// Predicate.
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tADDi3)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tADDi3)
.addReg(ValReg)
// 's' bit operand
.addReg(ARM::CPSR)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tSTRi)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tSTRi)
.addReg(ValReg)
.addReg(SrcReg)
// The offset immediate is #4. The operand value is scaled by 4 for the
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVi8)
.addReg(ARM::R0)
.addReg(ARM::CPSR)
.addImm(0)
.addReg(0));
const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tB)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tB)
.addExpr(SymbolExpr)
.addImm(ARMCC::AL)
.addReg(0));
OutStreamer.AddComment("eh_setjmp end");
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVi8)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVi8)
.addReg(ARM::R0)
.addReg(ARM::CPSR)
.addImm(1)
unsigned ValReg = MI->getOperand(1).getReg();
OutStreamer.AddComment("eh_setjmp begin");
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDri)
.addReg(ValReg)
.addReg(ARM::PC)
.addImm(8)
// 's' bit operand (always reg0 for this).
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::STRi12)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::STRi12)
.addReg(ValReg)
.addReg(SrcReg)
.addImm(4)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVi)
.addReg(ARM::R0)
.addImm(0)
// Predicate.
// 's' bit operand (always reg0 for this).
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::ADDri)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDri)
.addReg(ARM::PC)
.addReg(ARM::PC)
.addImm(0)
.addReg(0));
OutStreamer.AddComment("eh_setjmp end");
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::MOVi)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVi)
.addReg(ARM::R0)
.addImm(1)
// Predicate.
// bx $scratch
unsigned SrcReg = MI->getOperand(0).getReg();
unsigned ScratchReg = MI->getOperand(1).getReg();
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::LDRi12)
.addReg(ARM::SP)
.addReg(SrcReg)
.addImm(8)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::LDRi12)
.addReg(ScratchReg)
.addReg(SrcReg)
.addImm(4)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::LDRi12)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::LDRi12)
.addReg(ARM::R7)
.addReg(SrcReg)
.addImm(0)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::BX)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::BX)
.addReg(ScratchReg)
// Predicate.
.addImm(ARMCC::AL)
// bx $scratch
unsigned SrcReg = MI->getOperand(0).getReg();
unsigned ScratchReg = MI->getOperand(1).getReg();
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tLDRi)
.addReg(ScratchReg)
.addReg(SrcReg)
// The offset immediate is #8. The operand value is scaled by 4 for the
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tMOVr)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
.addReg(ARM::SP)
.addReg(ScratchReg)
// Predicate.
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tLDRi)
.addReg(ScratchReg)
.addReg(SrcReg)
.addImm(1)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tLDRi)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tLDRi)
.addReg(ARM::R7)
.addReg(SrcReg)
.addImm(0)
.addImm(ARMCC::AL)
.addReg(0));
- OutStreamer.EmitInstruction(MCInstBuilder(ARM::tBX)
+ EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tBX)
.addReg(ScratchReg)
// Predicate.
.addImm(ARMCC::AL)
MCInst TmpInst;
LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
- OutStreamer.EmitInstruction(TmpInst);
+ EmitToStreamer(OutStreamer, TmpInst);
}
//===----------------------------------------------------------------------===//