diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 173 |
1 files changed, 167 insertions, 6 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 04d6529a073d..2a9d96205eb9 100644 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -39,6 +39,7 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbolELF.h" @@ -79,6 +80,9 @@ bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { NaClAlignIndirectJumpTargets(MF); AsmPrinter::runOnMachineFunction(MF); + + EmitXRayTable(); + return true; } @@ -132,6 +136,7 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsTargetStreamer &TS = getTargetStreamer(); + unsigned Opc = MI->getOpcode(); TS.forbidModuleDirective(); if (MI->isDebugValue()) { @@ -143,20 +148,20 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { } // If we just ended a constant pool, mark it as such. - if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { + if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) { OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); InConstantPool = false; } - if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { + if (Opc == Mips::CONSTPOOL_ENTRY) { // CONSTPOOL_ENTRY - This instruction represents a floating - //constant pool in the function. The first operand is the ID# + // constant pool in the function. The first operand is the ID# // for this instruction, the second is the index into the // MachineConstantPool that this is, the third is the size in // bytes of this constant pool entry. // The required alignment is specified on the basic block holding this MI. // unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); - unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); + unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); // If this is the first entry of the pool, mark it. if (!InConstantPool) { @@ -174,6 +179,17 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { return; } + switch (Opc) { + case Mips::PATCHABLE_FUNCTION_ENTER: + LowerPATCHABLE_FUNCTION_ENTER(*MI); + return; + case Mips::PATCHABLE_FUNCTION_EXIT: + LowerPATCHABLE_FUNCTION_EXIT(*MI); + return; + case Mips::PATCHABLE_TAIL_CALL: + LowerPATCHABLE_TAIL_CALL(*MI); + return; + } MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); @@ -574,6 +590,8 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, case MipsII::MO_GOT: O << "%got("; break; case MipsII::MO_ABS_HI: O << "%hi("; break; case MipsII::MO_ABS_LO: O << "%lo("; break; + case MipsII::MO_HIGHER: O << "%higher("; break; + case MipsII::MO_HIGHEST: O << "%highest(("; break; case MipsII::MO_TLSGD: O << "%tlsgd("; break; case MipsII::MO_GOTTPREL: O << "%gottprel("; break; case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; @@ -698,7 +716,7 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // 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 (!isPositionIndependent() && !ABI.IsN64()) + if (!isPositionIndependent() && STI.hasSym32()) TS.emitDirectiveOptionPic0(); } @@ -1032,6 +1050,149 @@ void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); } +void MipsAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { + const uint8_t NoopsInSledCount = Subtarget->isGP64bit() ? 15 : 11; + // For mips32 we want to emit the following pattern: + // + // .Lxray_sled_N: + // ALIGN + // B .tmpN + // 11 NOP instructions (44 bytes) + // ADDIU T9, T9, 52 + // .tmpN + // + // We need the 44 bytes (11 instructions) because at runtime, we'd + // be patching over the full 48 bytes (12 instructions) with the following + // pattern: + // + // ADDIU SP, SP, -8 + // NOP + // SW RA, 4(SP) + // SW T9, 0(SP) + // LUI T9, %hi(__xray_FunctionEntry/Exit) + // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) + // LUI T0, %hi(function_id) + // JALR T9 + // ORI T0, T0, %lo(function_id) + // LW T9, 0(SP) + // LW RA, 4(SP) + // ADDIU SP, SP, 8 + // + // We add 52 bytes to t9 because we want to adjust the function pointer to + // the actual start of function i.e. the address just after the noop sled. + // We do this because gp displacement relocation is emitted at the start of + // of the function i.e after the nop sled and to correctly calculate the + // global offset table address, t9 must hold the address of the instruction + // containing the gp displacement relocation. + // FIXME: Is this correct for the static relocation model? + // + // For mips64 we want to emit the following pattern: + // + // .Lxray_sled_N: + // ALIGN + // B .tmpN + // 15 NOP instructions (60 bytes) + // .tmpN + // + // We need the 60 bytes (15 instructions) because at runtime, we'd + // be patching over the full 64 bytes (16 instructions) with the following + // pattern: + // + // DADDIU SP, SP, -16 + // NOP + // SD RA, 8(SP) + // SD T9, 0(SP) + // LUI T9, %highest(__xray_FunctionEntry/Exit) + // ORI T9, T9, %higher(__xray_FunctionEntry/Exit) + // DSLL T9, T9, 16 + // ORI T9, T9, %hi(__xray_FunctionEntry/Exit) + // DSLL T9, T9, 16 + // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) + // LUI T0, %hi(function_id) + // JALR T9 + // ADDIU T0, T0, %lo(function_id) + // LD T9, 0(SP) + // LD RA, 8(SP) + // DADDIU SP, SP, 16 + // + OutStreamer->EmitCodeAlignment(4); + auto CurSled = OutContext.createTempSymbol("xray_sled_", true); + OutStreamer->EmitLabel(CurSled); + auto Target = OutContext.createTempSymbol(); + + // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual + // start of function + const MCExpr *TargetExpr = MCSymbolRefExpr::create( + Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BEQ) + .addReg(Mips::ZERO) + .addReg(Mips::ZERO) + .addExpr(TargetExpr)); + + for (int8_t I = 0; I < NoopsInSledCount; I++) + EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL) + .addReg(Mips::ZERO) + .addReg(Mips::ZERO) + .addImm(0)); + + OutStreamer->EmitLabel(Target); + + if (!Subtarget->isGP64bit()) { + EmitToStreamer(*OutStreamer, + MCInstBuilder(Mips::ADDiu) + .addReg(Mips::T9) + .addReg(Mips::T9) + .addImm(0x34)); + } + + recordSled(CurSled, MI, Kind); +} + +void MipsAsmPrinter::EmitXRayTable() { + if (Sleds.empty()) + return; + if (Subtarget->isTargetELF()) { + auto PrevSection = OutStreamer->getCurrentSectionOnly(); + auto Fn = MF->getFunction(); + MCSection *Section; + + if (Fn->hasComdat()) + Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, + Fn->getComdat()->getName()); + else + Section = + OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, 0, CurrentFnSym->getName()); + + OutStreamer->SwitchSection(Section); + for (const auto &Sled : Sleds) { + OutStreamer->EmitSymbolValue(Sled.Sled, Subtarget->isGP64bit() ? 8 : 4); + OutStreamer->EmitSymbolValue(CurrentFnSym, Subtarget->isGP64bit() ? 8 : 4); + auto Kind = static_cast<uint8_t>(Sled.Kind); + OutStreamer->EmitBytes( + StringRef(reinterpret_cast<const char *>(&Kind), 1)); + OutStreamer->EmitBytes( + StringRef(reinterpret_cast<const char *>(&Sled.AlwaysInstrument), 1)); + OutStreamer->EmitZeros(Subtarget->isGP64bit() ? 14 : 6); + } + OutStreamer->SwitchSection(PrevSection); + } + Sleds.clear(); +} + +void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { + EmitSled(MI, SledKind::FUNCTION_ENTER); +} + +void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { + EmitSled(MI, SledKind::FUNCTION_EXIT); +} + +void MipsAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { + EmitSled(MI, SledKind::TAIL_CALL); +} + void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS) { // TODO: implement @@ -1039,7 +1200,7 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, // Emit .dtprelword or .dtpreldword directive // and value for debug thread local expression. -void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value, +void MipsAsmPrinter::EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const { switch (Size) { case 4: |