aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp401
1 files changed, 253 insertions, 148 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 7ec7ffe309f7..a0c5498ee620 100644
--- a/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -32,6 +32,7 @@
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/FaultMaps.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -54,6 +55,7 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -69,12 +71,13 @@ namespace {
class AArch64AsmPrinter : public AsmPrinter {
AArch64MCInstLower MCInstLowering;
StackMaps SM;
+ FaultMaps FM;
const AArch64Subtarget *STI;
public:
AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this),
- SM(*this) {}
+ SM(*this), FM(*this) {}
StringRef getPassName() const override { return "AArch64 Assembly Printer"; }
@@ -86,17 +89,18 @@ public:
void emitStartOfAsmFile(Module &M) override;
void emitJumpTableInfo() override;
- void emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
- const MachineBasicBlock *MBB, unsigned JTI);
void emitFunctionEntryLabel() override;
- void LowerJumpTableDestSmall(MCStreamer &OutStreamer, const MachineInstr &MI);
+ void LowerJumpTableDest(MCStreamer &OutStreamer, const MachineInstr &MI);
void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
const MachineInstr &MI);
void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
const MachineInstr &MI);
+ void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
+ const MachineInstr &MI);
+ void LowerFAULTING_OP(const MachineInstr &MI);
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
@@ -191,58 +195,24 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
return;
// Assemble feature flags that may require creation of a note section.
- unsigned Flags = ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI |
- ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
-
- if (any_of(M, [](const Function &F) {
- return !F.isDeclaration() &&
- !F.hasFnAttribute("branch-target-enforcement");
- })) {
- Flags &= ~ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
- }
+ unsigned Flags = 0;
+ if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("branch-target-enforcement")))
+ if (BTE->getZExtValue())
+ Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
- if ((Flags & ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI) == 0 &&
- any_of(M, [](const Function &F) {
- return F.hasFnAttribute("branch-target-enforcement");
- })) {
- errs() << "warning: some functions compiled with BTI and some compiled "
- "without BTI\n"
- << "warning: not setting BTI in feature flags\n";
- }
-
- if (any_of(M, [](const Function &F) {
- if (F.isDeclaration())
- return false;
- Attribute A = F.getFnAttribute("sign-return-address");
- return !A.isStringAttribute() || A.getValueAsString() == "none";
- })) {
- Flags &= ~ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
- }
+ if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("sign-return-address")))
+ if (Sign->getZExtValue())
+ Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
if (Flags == 0)
return;
// Emit a .note.gnu.property section with the flags.
- MCSection *Cur = OutStreamer->getCurrentSectionOnly();
- MCSection *Nt = MMI->getContext().getELFSection(
- ".note.gnu.property", ELF::SHT_NOTE, ELF::SHF_ALLOC);
- OutStreamer->SwitchSection(Nt);
-
- // Emit the note header.
- emitAlignment(Align(8));
- OutStreamer->emitInt32(4); // data size for "GNU\0"
- OutStreamer->emitInt32(4 * 4); // Elf_Prop size
- OutStreamer->emitInt32(ELF::NT_GNU_PROPERTY_TYPE_0);
- OutStreamer->emitBytes(StringRef("GNU", 4)); // note name
-
- // Emit the PAC/BTI properties.
- OutStreamer->emitInt32(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND);
- OutStreamer->emitInt32(4); // data size
- OutStreamer->emitInt32(Flags); // data
- OutStreamer->emitInt32(0); // pad
-
- OutStreamer->endSection(Nt);
- OutStreamer->SwitchSection(Cur);
+ if (auto *TS = static_cast<AArch64TargetStreamer *>(
+ OutStreamer->getTargetStreamer()))
+ TS->emitNoteSection(Flags);
}
void AArch64AsmPrinter::emitFunctionHeaderComment() {
@@ -333,7 +303,7 @@ void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
std::string SymName = "__hwasan_check_x" + utostr(Reg - AArch64::X0) + "_" +
utostr(AccessInfo);
if (IsShort)
- SymName += "_short";
+ SymName += "_short_v2";
Sym = OutContext.getOrCreateSymbol(SymName);
}
@@ -350,6 +320,7 @@ void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
assert(TT.isOSBinFormatELF());
std::unique_ptr<MCSubtargetInfo> STI(
TM.getTarget().createMCSubtargetInfo(TT.str(), "", ""));
+ assert(STI && "Unable to create subtarget info");
MCSymbol *HwasanTagMismatchV1Sym =
OutContext.getOrCreateSymbol("__hwasan_tag_mismatch");
@@ -369,6 +340,15 @@ void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
MCSymbol *Sym = P.second;
+ bool HasMatchAllTag =
+ (AccessInfo >> HWASanAccessInfo::HasMatchAllShift) & 1;
+ uint8_t MatchAllTag =
+ (AccessInfo >> HWASanAccessInfo::MatchAllShift) & 0xff;
+ unsigned Size =
+ 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
+ bool CompileKernel =
+ (AccessInfo >> HWASanAccessInfo::CompileKernelShift) & 1;
+
OutStreamer->SwitchSection(OutContext.getELFSection(
".text.hot", ELF::SHT_PROGBITS,
ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
@@ -379,19 +359,20 @@ void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
OutStreamer->emitLabel(Sym);
- OutStreamer->emitInstruction(MCInstBuilder(AArch64::UBFMXri)
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::SBFMXri)
.addReg(AArch64::X16)
.addReg(Reg)
.addImm(4)
.addImm(55),
*STI);
- OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDRBBroX)
- .addReg(AArch64::W16)
- .addReg(AArch64::X9)
- .addReg(AArch64::X16)
- .addImm(0)
- .addImm(0),
- *STI);
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::LDRBBroX)
+ .addReg(AArch64::W16)
+ .addReg(IsShort ? AArch64::X20 : AArch64::X9)
+ .addReg(AArch64::X16)
+ .addImm(0)
+ .addImm(0),
+ *STI);
OutStreamer->emitInstruction(
MCInstBuilder(AArch64::SUBSXrs)
.addReg(AArch64::XZR)
@@ -412,6 +393,26 @@ void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
OutStreamer->emitLabel(HandleMismatchOrPartialSym);
+ if (HasMatchAllTag) {
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::UBFMXri)
+ .addReg(AArch64::X16)
+ .addReg(Reg)
+ .addImm(56)
+ .addImm(63),
+ *STI);
+ OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSXri)
+ .addReg(AArch64::XZR)
+ .addReg(AArch64::X16)
+ .addImm(MatchAllTag)
+ .addImm(0),
+ *STI);
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::Bcc)
+ .addImm(AArch64CC::EQ)
+ .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
+ *STI);
+ }
+
if (IsShort) {
OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSWri)
.addReg(AArch64::WZR)
@@ -432,7 +433,6 @@ void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
.addReg(Reg)
.addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
*STI);
- unsigned Size = 1 << (AccessInfo & 0xf);
if (Size != 1)
OutStreamer->emitInstruction(MCInstBuilder(AArch64::ADDXri)
.addReg(AArch64::X17)
@@ -500,32 +500,41 @@ void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
.addReg(Reg)
.addImm(0),
*STI);
- OutStreamer->emitInstruction(MCInstBuilder(AArch64::MOVZXi)
- .addReg(AArch64::X1)
- .addImm(AccessInfo)
- .addImm(0),
- *STI);
-
- // Intentionally load the GOT entry and branch to it, rather than possibly
- // late binding the function, which may clobber the registers before we have
- // a chance to save them.
OutStreamer->emitInstruction(
- MCInstBuilder(AArch64::ADRP)
- .addReg(AArch64::X16)
- .addExpr(AArch64MCExpr::create(
- HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
- OutContext)),
+ MCInstBuilder(AArch64::MOVZXi)
+ .addReg(AArch64::X1)
+ .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask)
+ .addImm(0),
*STI);
- OutStreamer->emitInstruction(
- MCInstBuilder(AArch64::LDRXui)
- .addReg(AArch64::X16)
- .addReg(AArch64::X16)
- .addExpr(AArch64MCExpr::create(
- HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
- OutContext)),
- *STI);
- OutStreamer->emitInstruction(
- MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
+
+ if (CompileKernel) {
+ // The Linux kernel's dynamic loader doesn't support GOT relative
+ // relocations, but it doesn't support late binding either, so just call
+ // the function directly.
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef), *STI);
+ } else {
+ // Intentionally load the GOT entry and branch to it, rather than possibly
+ // late binding the function, which may clobber the registers before we
+ // have a chance to save them.
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::ADRP)
+ .addReg(AArch64::X16)
+ .addExpr(AArch64MCExpr::create(
+ HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
+ OutContext)),
+ *STI);
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::LDRXui)
+ .addReg(AArch64::X16)
+ .addReg(AArch64::X16)
+ .addExpr(AArch64MCExpr::create(
+ HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
+ OutContext)),
+ *STI);
+ OutStreamer->emitInstruction(
+ MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
+ }
}
}
@@ -541,7 +550,11 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
// generates code that does this, it is always safe to set.
OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
}
+
+ // Emit stack and fault map information.
emitStackMaps(SM);
+ FM.serializeToFaultMapSection();
+
}
void AArch64AsmPrinter::EmitLOHs() {
@@ -634,7 +647,8 @@ bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
const TargetRegisterInfo *RI = STI->getRegisterInfo();
Register Reg = MO.getReg();
unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
- assert(RI->regsOverlap(RegToPrint, Reg));
+ if (!RI->regsOverlap(RegToPrint, Reg))
+ return true;
O << AArch64InstPrinter::getRegisterName(RegToPrint, AltName);
return false;
}
@@ -795,33 +809,25 @@ void AArch64AsmPrinter::emitJumpTableInfo() {
emitAlignment(Align(Size));
OutStreamer->emitLabel(GetJTISymbol(JTI));
- for (auto *JTBB : JTBBs)
- emitJumpTableEntry(MJTI, JTBB, JTI);
- }
-}
+ const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
+ const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
-void AArch64AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
- const MachineBasicBlock *MBB,
- unsigned JTI) {
- const MCExpr *Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
- auto AFI = MF->getInfo<AArch64FunctionInfo>();
- unsigned Size = AFI->getJumpTableEntrySize(JTI);
+ for (auto *JTBB : JTBBs) {
+ const MCExpr *Value =
+ MCSymbolRefExpr::create(JTBB->getSymbol(), OutContext);
- if (Size == 4) {
- // .word LBB - LJTI
- const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
- const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, JTI, OutContext);
- Value = MCBinaryExpr::createSub(Value, Base, OutContext);
- } else {
- // .byte (LBB - LBB) >> 2 (or .hword)
- const MCSymbol *BaseSym = AFI->getJumpTableEntryPCRelSymbol(JTI);
- const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
- Value = MCBinaryExpr::createSub(Value, Base, OutContext);
- Value = MCBinaryExpr::createLShr(
- Value, MCConstantExpr::create(2, OutContext), OutContext);
- }
+ // Each entry is:
+ // .byte/.hword (LBB - Lbase)>>2
+ // or plain:
+ // .word LBB - Lbase
+ Value = MCBinaryExpr::createSub(Value, Base, OutContext);
+ if (Size != 4)
+ Value = MCBinaryExpr::createLShr(
+ Value, MCConstantExpr::create(2, OutContext), OutContext);
- OutStreamer->emitValue(Value, Size);
+ OutStreamer->emitValue(Value, Size);
+ }
+ }
}
void AArch64AsmPrinter::emitFunctionEntryLabel() {
@@ -845,9 +851,9 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() {
///
/// adr xDest, .LBB0_0
/// ldrb wScratch, [xTable, xEntry] (with "lsl #1" for ldrh).
-/// add xDest, xDest, xScratch, lsl #2
-void AArch64AsmPrinter::LowerJumpTableDestSmall(llvm::MCStreamer &OutStreamer,
- const llvm::MachineInstr &MI) {
+/// add xDest, xDest, xScratch (with "lsl #2" for smaller entries)
+void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
+ const llvm::MachineInstr &MI) {
Register DestReg = MI.getOperand(0).getReg();
Register ScratchReg = MI.getOperand(1).getReg();
Register ScratchRegW =
@@ -855,33 +861,50 @@ void AArch64AsmPrinter::LowerJumpTableDestSmall(llvm::MCStreamer &OutStreamer,
Register TableReg = MI.getOperand(2).getReg();
Register EntryReg = MI.getOperand(3).getReg();
int JTIdx = MI.getOperand(4).getIndex();
- bool IsByteEntry = MI.getOpcode() == AArch64::JumpTableDest8;
+ int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
// This has to be first because the compression pass based its reachability
// calculations on the start of the JumpTableDest instruction.
auto Label =
MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
+
+ // If we don't already have a symbol to use as the base, use the ADR
+ // instruction itself.
+ if (!Label) {
+ Label = MF->getContext().createTempSymbol();
+ AArch64FI->setJumpTableEntryInfo(JTIdx, Size, Label);
+ OutStreamer.emitLabel(Label);
+ }
+
+ auto LabelExpr = MCSymbolRefExpr::create(Label, MF->getContext());
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
.addReg(DestReg)
- .addExpr(MCSymbolRefExpr::create(
- Label, MF->getContext())));
+ .addExpr(LabelExpr));
// Load the number of instruction-steps to offset from the label.
- unsigned LdrOpcode = IsByteEntry ? AArch64::LDRBBroX : AArch64::LDRHHroX;
+ unsigned LdrOpcode;
+ switch (Size) {
+ case 1: LdrOpcode = AArch64::LDRBBroX; break;
+ case 2: LdrOpcode = AArch64::LDRHHroX; break;
+ case 4: LdrOpcode = AArch64::LDRSWroX; break;
+ default:
+ llvm_unreachable("Unknown jump table size");
+ }
+
EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
- .addReg(ScratchRegW)
+ .addReg(Size == 4 ? ScratchReg : ScratchRegW)
.addReg(TableReg)
.addReg(EntryReg)
.addImm(0)
- .addImm(IsByteEntry ? 0 : 1));
+ .addImm(Size == 1 ? 0 : 1));
- // Multiply the steps by 4 and add to the already materialized base label
- // address.
+ // Add to the already materialized base label address, multiplying by 4 if
+ // compressed.
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
.addReg(DestReg)
.addReg(DestReg)
.addReg(ScratchReg)
- .addImm(2));
+ .addImm(Size == 4 ? 0 : 2));
}
void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
@@ -959,6 +982,83 @@ void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
}
+void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
+ const MachineInstr &MI) {
+ StatepointOpers SOpers(&MI);
+ if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
+ assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
+ for (unsigned i = 0; i < PatchBytes; i += 4)
+ EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
+ } else {
+ // Lower call target and choose correct opcode
+ const MachineOperand &CallTarget = SOpers.getCallTarget();
+ MCOperand CallTargetMCOp;
+ unsigned CallOpcode;
+ switch (CallTarget.getType()) {
+ case MachineOperand::MO_GlobalAddress:
+ case MachineOperand::MO_ExternalSymbol:
+ MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
+ CallOpcode = AArch64::BL;
+ break;
+ case MachineOperand::MO_Immediate:
+ CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
+ CallOpcode = AArch64::BL;
+ break;
+ case MachineOperand::MO_Register:
+ CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
+ CallOpcode = AArch64::BLR;
+ break;
+ default:
+ llvm_unreachable("Unsupported operand type in statepoint call target");
+ break;
+ }
+
+ EmitToStreamer(OutStreamer,
+ MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp));
+ }
+
+ auto &Ctx = OutStreamer.getContext();
+ MCSymbol *MILabel = Ctx.createTempSymbol();
+ OutStreamer.emitLabel(MILabel);
+ SM.recordStatepoint(*MILabel, MI);
+}
+
+void AArch64AsmPrinter::LowerFAULTING_OP(const MachineInstr &FaultingMI) {
+ // FAULTING_LOAD_OP <def>, <faltinf type>, <MBB handler>,
+ // <opcode>, <operands>
+
+ Register DefRegister = FaultingMI.getOperand(0).getReg();
+ FaultMaps::FaultKind FK =
+ static_cast<FaultMaps::FaultKind>(FaultingMI.getOperand(1).getImm());
+ MCSymbol *HandlerLabel = FaultingMI.getOperand(2).getMBB()->getSymbol();
+ unsigned Opcode = FaultingMI.getOperand(3).getImm();
+ unsigned OperandsBeginIdx = 4;
+
+ auto &Ctx = OutStreamer->getContext();
+ MCSymbol *FaultingLabel = Ctx.createTempSymbol();
+ OutStreamer->emitLabel(FaultingLabel);
+
+ assert(FK < FaultMaps::FaultKindMax && "Invalid Faulting Kind!");
+ FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
+
+ MCInst MI;
+ MI.setOpcode(Opcode);
+
+ if (DefRegister != (Register)0)
+ MI.addOperand(MCOperand::createReg(DefRegister));
+
+ for (auto I = FaultingMI.operands_begin() + OperandsBeginIdx,
+ E = FaultingMI.operands_end();
+ I != E; ++I) {
+ MCOperand Dest;
+ lowerOperand(*I, Dest);
+ MI.addOperand(Dest);
+ }
+
+ OutStreamer->AddComment("on-fault: " + HandlerLabel->getName());
+ OutStreamer->emitInstruction(MI, getSubtargetInfo());
+}
+
void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) {
Register DestReg = MI.getOperand(0).getReg();
if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) {
@@ -1172,17 +1272,28 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, Adrp);
MCInst Ldr;
- Ldr.setOpcode(AArch64::LDRXui);
- Ldr.addOperand(MCOperand::createReg(AArch64::X1));
+ if (STI->isTargetILP32()) {
+ Ldr.setOpcode(AArch64::LDRWui);
+ Ldr.addOperand(MCOperand::createReg(AArch64::W1));
+ } else {
+ Ldr.setOpcode(AArch64::LDRXui);
+ Ldr.addOperand(MCOperand::createReg(AArch64::X1));
+ }
Ldr.addOperand(MCOperand::createReg(AArch64::X0));
Ldr.addOperand(SymTLSDescLo12);
Ldr.addOperand(MCOperand::createImm(0));
EmitToStreamer(*OutStreamer, Ldr);
MCInst Add;
- Add.setOpcode(AArch64::ADDXri);
- Add.addOperand(MCOperand::createReg(AArch64::X0));
- Add.addOperand(MCOperand::createReg(AArch64::X0));
+ if (STI->isTargetILP32()) {
+ Add.setOpcode(AArch64::ADDWri);
+ Add.addOperand(MCOperand::createReg(AArch64::W0));
+ Add.addOperand(MCOperand::createReg(AArch64::W0));
+ } else {
+ Add.setOpcode(AArch64::ADDXri);
+ Add.addOperand(MCOperand::createReg(AArch64::X0));
+ Add.addOperand(MCOperand::createReg(AArch64::X0));
+ }
Add.addOperand(SymTLSDescLo12);
Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
EmitToStreamer(*OutStreamer, Add);
@@ -1202,30 +1313,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
return;
}
- case AArch64::JumpTableDest32: {
- // We want:
- // ldrsw xScratch, [xTable, xEntry, lsl #2]
- // add xDest, xTable, xScratch
- unsigned DestReg = MI->getOperand(0).getReg(),
- ScratchReg = MI->getOperand(1).getReg(),
- TableReg = MI->getOperand(2).getReg(),
- EntryReg = MI->getOperand(3).getReg();
- EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
- .addReg(ScratchReg)
- .addReg(TableReg)
- .addReg(EntryReg)
- .addImm(0)
- .addImm(1));
- EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
- .addReg(DestReg)
- .addReg(TableReg)
- .addReg(ScratchReg)
- .addImm(0));
- return;
- }
+ case AArch64::JumpTableDest32:
case AArch64::JumpTableDest16:
case AArch64::JumpTableDest8:
- LowerJumpTableDestSmall(*OutStreamer, *MI);
+ LowerJumpTableDest(*OutStreamer, *MI);
return;
case AArch64::FMOVH0:
@@ -1240,6 +1331,12 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
case TargetOpcode::PATCHPOINT:
return LowerPATCHPOINT(*OutStreamer, SM, *MI);
+ case TargetOpcode::STATEPOINT:
+ return LowerSTATEPOINT(*OutStreamer, SM, *MI);
+
+ case TargetOpcode::FAULTING_OP:
+ return LowerFAULTING_OP(*MI);
+
case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
LowerPATCHABLE_FUNCTION_ENTER(*MI);
return;
@@ -1284,6 +1381,14 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
return;
case AArch64::SEH_SaveRegP:
+ if (MI->getOperand(1).getImm() == 30 && MI->getOperand(0).getImm() >= 19 &&
+ MI->getOperand(0).getImm() <= 28) {
+ assert((MI->getOperand(0).getImm() - 19) % 2 == 0 &&
+ "Register paired with LR must be odd");
+ TS->EmitARM64WinCFISaveLRPair(MI->getOperand(0).getImm(),
+ MI->getOperand(2).getImm());
+ return;
+ }
assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
"Non-consecutive registers not allowed for save_regp");
TS->EmitARM64WinCFISaveRegP(MI->getOperand(0).getImm(),