diff options
Diffstat (limited to 'lib/Target/Mips')
22 files changed, 1015 insertions, 7 deletions
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 9a35bb6bd7..9a94c75e2f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -14,6 +14,7 @@ #include "MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" +#include "MCTargetDesc/MipsMCNaCl.h" // @LOCALMOD #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" @@ -239,6 +240,20 @@ public: OW->Write32(0); return true; } + + // @LOCALMOD-BEGIN + // FIXME! NaCl should INHERIT from MipsAsmBackend, not add to it. + unsigned getBundleSize() const { + return (OSType == Triple::NativeClient) ? 16 : 0; + } + + bool CustomExpandInst(const MCInst &Inst, MCStreamer &Out) const { + if (OSType == Triple::NativeClient) { + return CustomExpandInstNaClMips(Inst, Out); + } + return false; + } + // @LOCALMOD-END }; // class MipsAsmBackend } // namespace diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 5d240fe847..6ad8669d04 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -18,6 +18,13 @@ #include "llvm/Support/ErrorHandling.h" #include <list> +// @LOCALMOD-START +// TODO(petarj): HACK! Find better way to set ELF::EF_MIPS_PIC flag. +// See also file lib/MC/MCObjectFileInfo.cpp. +#include "llvm/Support/CodeGen.h" +extern llvm::Reloc::Model RelocModelOption; +// @LOCALMOD-END + using namespace llvm; namespace { @@ -71,6 +78,10 @@ unsigned MipsELFObjectWriter::getEFlags() const { Flag |= ELF::EF_MIPS_ARCH_64R2; else Flag |= ELF::EF_MIPS_ARCH_32R2; + /* @LOCLAMOD-START */ + if (RelocModelOption == Reloc::PIC_ || RelocModelOption == Reloc::Default) + Flag |= ELF::EF_MIPS_PIC; + /* @LOCLAMOD-END */ return Flag; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.cpp new file mode 100644 index 0000000000..d39a60d41c --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.cpp @@ -0,0 +1,261 @@ +//=== MipsMCNaCl.cpp - Expansion of NaCl pseudo-instructions --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "mips-mc-nacl" + +#include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +/// Two helper functions for emitting the actual guard instructions + +static void EmitMask(MCStreamer &Out, + unsigned Addr, unsigned Mask) { + // and \Addr, \Addr, \Mask + MCInst MaskInst; + MaskInst.setOpcode(Mips::AND); + MaskInst.addOperand(MCOperand::CreateReg(Addr)); + MaskInst.addOperand(MCOperand::CreateReg(Addr)); + MaskInst.addOperand(MCOperand::CreateReg(Mask)); + Out.EmitInstruction(MaskInst); +} + +// This is ONLY used for sandboxing stack changes. +// The reason why SFI_NOP_IF_AT_BUNDLE_END gets handled here is that +// it must ensure that the two instructions are in the same bundle. +// It just so happens that the SFI_NOP_IF_AT_BUNDLE_END is always +// emitted in conjunction with a SFI_DATA_MASK +// +static void EmitDataMask(int I, MCInst Saved[], MCStreamer &Out) { + assert(I == 3 && + (Mips::SFI_NOP_IF_AT_BUNDLE_END == Saved[0].getOpcode()) && + (Mips::SFI_DATA_MASK == Saved[2].getOpcode()) && + "Unexpected SFI Pseudo while lowering"); + + unsigned Addr = Saved[2].getOperand(0).getReg(); + unsigned Mask = Saved[2].getOperand(2).getReg(); + assert((Mips::SP == Addr) && "Unexpected register at stack guard"); + + Out.EmitBundleLock(); + Out.EmitInstruction(Saved[1]); + EmitMask(Out, Addr, Mask); + Out.EmitBundleUnlock(); +} + +static void EmitDirectGuardCall(int I, MCInst Saved[], + MCStreamer &Out) { + // sfi_call_preamble ---> + // sfi_nops_to_force_slot2 + assert(I == 3 && (Mips::SFI_GUARD_CALL == Saved[0].getOpcode()) && + "Unexpected SFI Pseudo while lowering SFI_GUARD_CALL"); + Out.EmitBundleAlignEnd(); + Out.EmitBundleLock(); + Out.EmitInstruction(Saved[1]); + Out.EmitInstruction(Saved[2]); + Out.EmitBundleUnlock(); +} + +static void EmitIndirectGuardCall(int I, MCInst Saved[], + MCStreamer &Out) { + // sfi_indirect_call_preamble link ---> + // sfi_nops_to_force_slot1 + // sfi_code_mask \link \link \maskreg + assert(I == 3 && (Mips::SFI_GUARD_INDIRECT_CALL == Saved[0].getOpcode()) && + "Unexpected SFI Pseudo while lowering SFI_GUARD_INDIRECT_CALL"); + + unsigned Addr = Saved[0].getOperand(0).getReg(); + unsigned Mask = Saved[0].getOperand(2).getReg(); + + Out.EmitBundleAlignEnd(); + Out.EmitBundleLock(); + EmitMask(Out, Addr, Mask); + Out.EmitInstruction(Saved[1]); + Out.EmitInstruction(Saved[2]); + Out.EmitBundleUnlock(); +} + +static void EmitIndirectGuardJmp(int I, MCInst Saved[], MCStreamer &Out) { + // sfi_indirect_jump_preamble link ---> + // sfi_nop_if_at_bundle_end + // sfi_code_mask \link \link \maskreg + assert(I == 2 && (Mips::SFI_GUARD_INDIRECT_JMP == Saved[0].getOpcode()) && + "Unexpected SFI Pseudo while lowering SFI_GUARD_INDIRECT_JMP"); + unsigned Addr = Saved[0].getOperand(0).getReg(); + unsigned Mask = Saved[0].getOperand(2).getReg(); + + Out.EmitBundleLock(); + EmitMask(Out, Addr, Mask); + Out.EmitInstruction(Saved[1]); + Out.EmitBundleUnlock(); +} + +static void EmitGuardReturn(int I, MCInst Saved[], MCStreamer &Out) { + // sfi_return_preamble reg ---> + // sfi_nop_if_at_bundle_end + // sfi_code_mask \reg \reg \maskreg + assert(I == 2 && (Mips::SFI_GUARD_RETURN == Saved[0].getOpcode()) && + "Unexpected SFI Pseudo while lowering SFI_GUARD_RETURN"); + unsigned Reg = Saved[0].getOperand(0).getReg(); + unsigned Mask = Saved[0].getOperand(2).getReg(); + + Out.EmitBundleLock(); + EmitMask(Out, Reg, Mask); + Out.EmitInstruction(Saved[1]); + Out.EmitBundleUnlock(); +} + +static void EmitGuardLoadOrStore(int I, MCInst Saved[], MCStreamer &Out) { + // sfi_load_store_preamble reg ---> + // sfi_nop_if_at_bundle_end + // sfi_data_mask \reg \reg \maskreg + assert(I == 2 && (Mips::SFI_GUARD_LOADSTORE == Saved[0].getOpcode()) && + "Unexpected SFI Pseudo while lowering SFI_GUARD_LOADSTORE"); + unsigned Reg = Saved[0].getOperand(0).getReg(); + unsigned Mask = Saved[0].getOperand(2).getReg(); + + Out.EmitBundleLock(); + EmitMask(Out, Reg, Mask); + Out.EmitInstruction(Saved[1]); + Out.EmitBundleUnlock(); +} + +namespace llvm { +// CustomExpandInstNaClMips - +// If Inst is a NaCl pseudo instruction, emits the substitute +// expansion to the MCStreamer and returns true. +// Otherwise, returns false. +// +// NOTE: Each time this function calls Out.EmitInstruction(), it will be +// called again recursively to rewrite the new instruction being emitted. +// Care must be taken to ensure that this does not result in an infinite +// loop. Also, global state must be managed carefully so that it is +// consistent during recursive calls. +// +// We need global state to keep track of the explicit prefix (PREFIX_*) +// instructions. Unfortunately, the assembly parser prefers to generate +// these instead of combined instructions. At this time, having only +// one explicit prefix is supported. + + +bool CustomExpandInstNaClMips(const MCInst &Inst, MCStreamer &Out) { + const int MaxSaved = 4; + static MCInst Saved[MaxSaved]; + static int SaveCount = 0; + static int I = 0; + // This routine only executes if RecurseGuard == 0 + static bool RecurseGuard = false; + + // If we are emitting to .s, just emit all pseudo-instructions directly. + if (Out.hasRawTextSupport()) { + return false; + } + + //No recursive calls allowed; + if (RecurseGuard) return false; + + unsigned Opc = Inst.getOpcode(); + + DEBUG(dbgs() << "CustomExpandInstNaClMips("; Inst.dump(); dbgs() << ")\n"); + + // Note: SFI_NOP_IF_AT_BUNDLE_END is only emitted directly as part of + // a stack guard in conjunction with a SFI_DATA_MASK + + // Logic: + // This is somewhat convoluted, but in the current model, the SFI + // guard pseudo instructions occur PRIOR to the actual instruction. + // So, the bundling/alignment operation has to refer to the FOLLOWING + // one or two instructions. + // + // When a SFI_* pseudo is detected, it is saved. Then, the saved SFI_* + // pseudo and the very next one or two instructions are used as arguments to + // the Emit*() functions in this file. This is the reason why we have a + // doublely nested switch here. First, to save the SFI_* pseudo, then to + // emit it and the next instruction + + // By default, we only need to save two or three instructions + + if ((I == 0) && (SaveCount == 0)) { + // Base State, no saved instructions. + // If the current instruction is a SFI instruction, set the SaveCount + // and fall through. + switch (Opc) { + default: + SaveCount = 0; // Nothing to do. + return false; // Handle this Inst elsewhere. + case Mips::SFI_NOP_IF_AT_BUNDLE_END: + case Mips::SFI_GUARD_CALL: + case Mips::SFI_GUARD_INDIRECT_CALL: + SaveCount = 3; + break; + case Mips::SFI_DATA_MASK: + SaveCount = 0; // Do nothing. + break; + case Mips::SFI_GUARD_INDIRECT_JMP: + case Mips::SFI_GUARD_RETURN: + case Mips::SFI_GUARD_LOADSTORE: + SaveCount = 2; + break; + } + } + + if (I < SaveCount) { + // Othewise, save the current Inst and return + Saved[I++] = Inst; + if (I < SaveCount) + return true; + // Else fall through to next stat + } + + if (SaveCount > 0) { + assert(I == SaveCount && "Bookeeping Error"); + SaveCount = 0; // Reset for next iteration + // The following calls may call Out.EmitInstruction() + // which must not again call CustomExpandInst ... + // So set RecurseGuard = 1; + RecurseGuard = true; + + switch (Saved[0].getOpcode()) { + default: /* No action required */ break; + case Mips::SFI_NOP_IF_AT_BUNDLE_END: + EmitDataMask(I, Saved, Out); + break; + case Mips::SFI_DATA_MASK: + assert(0 && "Unexpected NOP_IF_AT_BUNDLE_END as a Saved Inst"); + break; + case Mips::SFI_GUARD_CALL: + EmitDirectGuardCall(I, Saved, Out); + break; + case Mips::SFI_GUARD_INDIRECT_CALL: + EmitIndirectGuardCall(I, Saved, Out); + break; + case Mips::SFI_GUARD_INDIRECT_JMP: + EmitIndirectGuardJmp(I, Saved, Out); + break; + case Mips::SFI_GUARD_RETURN: + EmitGuardReturn(I, Saved, Out); + break; + case Mips::SFI_GUARD_LOADSTORE: + EmitGuardLoadOrStore(I, Saved, Out); + break; + } + I = 0; // Reset I for next. + assert(RecurseGuard && "Illegal Depth"); + RecurseGuard = false; + return true; + } + return false; +} + +} // namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h new file mode 100644 index 0000000000..c90502ec33 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h @@ -0,0 +1,19 @@ +//===-- MipsMCNaCl.h - Prototype for CustomExpandInstNaClMips ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMCNACL_H +#define MIPSMCNACL_H + +namespace llvm { + class MCInst; + class MCStreamer; + bool CustomExpandInstNaClMips(const MCInst &Inst, MCStreamer &Out); +} + +#endif diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 2963f7e7fa..411030aaa1 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -18,6 +18,16 @@ #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/Target/TargetMachine.h" +/* @LOCALMOD-START */ +namespace llvm { + +namespace Mips { + extern unsigned LoadStoreStackMaskReg; + extern unsigned IndirectBranchMaskReg; +} +} // End llvm namespace +/* @LOCALMOD-END */ + namespace llvm { class MipsTargetMachine; class FunctionPass; @@ -28,6 +38,10 @@ namespace llvm { FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM, JITCodeEmitter &JCE); + // @LOCALMOD-START + FunctionPass *createMipsNaClRewritePass(); + // @LOCALMOD-END + } // end namespace llvm; #endif diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 83cca4752d..b45e7af102 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -212,13 +212,24 @@ const char *MipsAsmPrinter::getCurrentABIString() const { } void MipsAsmPrinter::EmitFunctionEntryLabel() { - if (OutStreamer.hasRawTextSupport()) { + // @LOCALMOD-START + // make sure function entry is aligned. We use XmagicX as our basis + // for alignment decisions (c.f. assembler sfi macros). + int alignment = MF->getAlignment(); + if (alignment < 4) alignment = 4; + EmitAlignment(alignment); + if (Subtarget->isTargetNaCl() && OutStreamer.hasRawTextSupport()) { if (Subtarget->inMips16Mode()) OutStreamer.EmitRawText(StringRef("\t.set\tmips16")); else OutStreamer.EmitRawText(StringRef("\t.set\tnomips16")); // leave out until FSF available gas has micromips changes // OutStreamer.EmitRawText(StringRef("\t.set\tnomicromips")); + OutStreamer.EmitRawText(StringRef("\t.set XmagicX, .\n")); + } + // @LOCALMOD-END + + if (OutStreamer.hasRawTextSupport()) { OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); } OutStreamer.EmitLabel(CurrentFnSym); @@ -522,6 +533,10 @@ printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } +// @LOCALMOD-START +extern void EmitMipsSFIHeaders(raw_ostream &O); +// @LOCALMOD-END + void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // FIXME: Use SwitchSection. @@ -543,7 +558,35 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // return to previous section if (OutStreamer.hasRawTextSupport()) OutStreamer.EmitRawText(StringRef("\t.previous")); + + // @LOCALMOD-START + if (Subtarget->isTargetNaCl() && OutStreamer.hasRawTextSupport()) { + std::string str; + raw_string_ostream OS(str); + EmitMipsSFIHeaders(OS); + OutStreamer.EmitRawText(StringRef(OS.str())); + } + // @LOCALMOD-END +} + +// @LOCALMOD-START +unsigned MipsAsmPrinter::GetTargetLabelAlign(const MachineInstr *MI) const { + if (Subtarget->isTargetNaCl()) { + switch (MI->getOpcode()) { + default: return 0; + // These labels may indicate an indirect entry point that is + // externally reachable and hence must be bundle aligned. + // Note: these labels appear to be always at basic block beginnings + // so it may be possible to simply set the MBB alignment. + // However, it is unclear whether this always holds. + case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: + return 4; + } + } + return 0; } +// @LOCALMOD-END MachineLocation MipsAsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index 94d8bfa105..efed6357a4 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -82,6 +82,10 @@ public: void EmitStartOfAsmFile(Module &M); virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); + + // @LOCALMOD-START + virtual unsigned GetTargetLabelAlign(const MachineInstr *MI) const; + // @LOCALMOD-END }; } diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index e3c8ed75cf..d014ba1792 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -141,6 +141,11 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { return new Filler(tm); } +// @LOCALMOD-START +extern bool IsDangerousLoad(const MachineInstr &MI, int *AddrIdx); +extern bool IsDangerousStore(const MachineInstr &MI, int *AddrIdx); +// @LOCALMOD-END + bool Filler::findDelayInstr(MachineBasicBlock &MBB, InstrIter slot, InstrIter &Filler) { @@ -160,11 +165,18 @@ bool Filler::findDelayInstr(MachineBasicBlock &MBB, // Convert to forward iterator. InstrIter FI(llvm::next(I).base()); + int Dummy; // @LOCALMOD if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() || FI == LastFiller || I->isPseudo() + // @LOCALMOD-START + // Don't put in delay slot instructions that could be masked. + || IsDangerousLoad(*FI, &Dummy) + || IsDangerousStore(*FI, &Dummy) + || FI->modifiesRegister(Mips::SP, TM.getRegisterInfo()) + // @LOCALMOD-END // // Should not allow: // ERET, DERET or WAIT, PAUSE. Need to add these to instruction diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index fceb63a1bc..f99ff15157 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -353,7 +353,7 @@ SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { if (LS && (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && - Subtarget.hasMips32r2Or64()) + Subtarget.hasMips32r2Or64() && !Subtarget.isTargetNaCl()/*@LOCALMOD*/) return false; } diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 91bb0373b7..ae89cdd693 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -330,6 +330,13 @@ MipsTargetLowering(MipsTargetMachine &TM) setTruncStoreAction(MVT::i64, MVT::i32, Custom); } + // @LOCALMOD-BEGIN + if (Subtarget->isTargetNaCl()) { + setOperationAction(ISD::NACL_TP_TLS_OFFSET, MVT::i32, Custom); + setOperationAction(ISD::NACL_TP_TDB_OFFSET, MVT::i32, Custom); + } + // @LOCALMOD-END + setTargetDAGCombine(ISD::ADDE); setTargetDAGCombine(ISD::SUBE); setTargetDAGCombine(ISD::SDIVREM); @@ -879,6 +886,11 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::STORE: return LowerSTORE(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); case ISD::INTRINSIC_W_CHAIN: return LowerINTRINSIC_W_CHAIN(Op, DAG); + + // @LOCALMOD-BEGIN + case ISD::NACL_TP_TLS_OFFSET: return LowerNaClTpTlsOffset(Op, DAG); + case ISD::NACL_TP_TDB_OFFSET: return LowerNaClTpTdbOffset(Op, DAG); + // @LOCALMOD-END } return SDValue(); } @@ -1777,6 +1789,24 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, return DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo); } +// @LOCALMOD-BEGIN + +// NaCl TLS setup / layout intrinsics. +// See: native_client/src/untrusted/nacl/tls_params.h +SDValue MipsTargetLowering::LowerNaClTpTlsOffset(SDValue Op, + SelectionDAG &DAG) const { + return DAG.getConstant(0, Op.getValueType().getSimpleVT()); +} + +SDValue MipsTargetLowering::LowerNaClTpTdbOffset(SDValue Op, + SelectionDAG &DAG) const { + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ISD::SUB, dl, Op.getValueType().getSimpleVT(), + DAG.getConstant(0, Op.getValueType().getSimpleVT()), + Op.getOperand(0)); +} +// @LOCALMOD-END + SDValue MipsTargetLowering:: LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { @@ -1791,6 +1821,38 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const TLSModel::Model model = getTargetMachine().getTLSModel(GV); + // @LOCALMOD-BEGIN + if (getTargetMachine().getSubtarget<MipsSubtarget>().isTargetNaCl()) { + SDVTList VTs = DAG.getVTList(MVT::i32); + SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_TPREL_HI); + SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + MipsII::MO_TPREL_LO); + SDValue Hi = DAG.getNode(MipsISD::Hi, dl, VTs, &TGAHi, 1); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, TGALo); + SDValue Offset = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); + + unsigned PtrSize = PtrVT.getSizeInBits(); + IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); + + SDValue TlsReadTp = DAG.getExternalSymbol("__nacl_read_tp", PtrVT); + + ArgListTy Args; + TargetLowering::CallLoweringInfo CLI(DAG.getEntryNode(), PtrTy, + false, false, false, false, 0, CallingConv::C, + /*isTailCall=*/false, /*doesNotRet=*/false, + /*isReturnValueUsed=*/true, + TlsReadTp, Args, DAG, dl); + std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); + + SDValue ThreadPointer = CallResult.first; + SDValue TPOffset = DAG.getConstant(0x7000, MVT::i32); + SDValue ThreadPointer2 = DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, + TPOffset); + return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer2, Offset); + } + // @LOCALMOD-END + if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { // General Dynamic and Local Dynamic TLS Model. unsigned Flag = (model == TLSModel::LocalDynamic) ? MipsII::MO_TLSLDM diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index b75a513fa7..18b9db7bc6 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -213,6 +213,11 @@ namespace llvm { bool IsEligibleForTailCallOptimization(CallingConv::ID CalleeCC, unsigned NextStackOffset) const; + // @LOCALMOD-BEGIN + SDValue LowerNaClTpTlsOffset(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerNaClTpTdbOffset(SDValue Op, SelectionDAG &DAG) const; + // @LOCALMOD-END + virtual SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 441d2e8702..fa6faf242d 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -281,23 +281,24 @@ let Predicates = [NotN64, NotMips64, HasStandardEncoding] in { } // Indexed loads and stores. -let Predicates = [HasMips32r2Or64, HasStandardEncoding] in { +let Predicates = [HasMips32r2Or64, NotNaCl/*@LOCALMOD*/] in { def LWXC1 : FPIdxLoad<0x0, "lwxc1", FGR32, CPURegs, load>; def SWXC1 : FPIdxStore<0x8, "swxc1", FGR32, CPURegs, store>; } -let Predicates = [HasMips32r2, NotMips64, HasStandardEncoding] in { +let Predicates = [HasMips32r2, NotMips64, NotNaCl/*@LOCALMOD*/] in { def LDXC1 : FPIdxLoad<0x1, "ldxc1", AFGR64, CPURegs, load>; def SDXC1 : FPIdxStore<0x9, "sdxc1", AFGR64, CPURegs, store>; } -let Predicates = [HasMips64, NotN64, HasStandardEncoding], DecoderNamespace="Mips64" in { +let Predicates = [HasMips64, NotN64, NotNaCl/*@LOCALMOD*/], + DecoderNamespace="Mips64" in { def LDXC164 : FPIdxLoad<0x1, "ldxc1", FGR64, CPURegs, load>; def SDXC164 : FPIdxStore<0x9, "sdxc1", FGR64, CPURegs, store>; } // n64 -let Predicates = [IsN64, HasStandardEncoding], isCodeGenOnly=1 in { +let Predicates = [IsN64, NotNaCl/*@LOCALMOD*/], isCodeGenOnly=1 in { def LWXC1_P8 : FPIdxLoad<0x0, "lwxc1", FGR32, CPU64Regs, load>; def LDXC164_P8 : FPIdxLoad<0x1, "ldxc1", FGR64, CPU64Regs, load>; def SWXC1_P8 : FPIdxStore<0x8, "swxc1", FGR32, CPU64Regs, store>; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index cc216c391d..bab26c3aa9 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -174,6 +174,8 @@ def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">, AssemblerPredicate<"FeatureMips32">; def HasStandardEncoding : Predicate<"Subtarget.hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; +def IsNaCl : Predicate<"Subtarget.isTargetNaCl()">; +def NotNaCl : Predicate<"!Subtarget.isTargetNaCl()">; class MipsPat<dag pattern, dag result> : Pat<pattern, result> { let Predicates = [HasStandardEncoding]; @@ -851,6 +853,37 @@ class SCBase<bits<6> Opc, string opstring, RegisterClass RC, Operand Mem> : // Pseudo instructions //===----------------------------------------------------------------------===// +// @LOCALMOD-START + +// Older Macro based SFI Model +def SFI_GUARD_LOADSTORE : +MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$src1, CPURegs:$src2), + "sfi_load_store_preamble\t$dst, $src1, $src2", []>; + +def SFI_GUARD_INDIRECT_CALL : +MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$src1, CPURegs:$src2), + "sfi_indirect_call_preamble\t$dst, $src1, $src2", []>; + +def SFI_GUARD_INDIRECT_JMP : +MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$src1, CPURegs:$src2), + "sfi_indirect_jump_preamble\t$dst, $src1, $src2", []>; + +def SFI_GUARD_CALL : +MipsPseudo<(outs), (ins), "sfi_call_preamble", []>; + +def SFI_GUARD_RETURN : +MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$src1, CPURegs:$src2), + "sfi_return_preamble\t$dst, $src1, $src2", []>; + +def SFI_NOP_IF_AT_BUNDLE_END : +MipsPseudo<(outs), (ins), "sfi_nop_if_at_bundle_end", []>; + +def SFI_DATA_MASK : +MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$src1, CPURegs:$src2), + "sfi_data_mask\t$dst, $src1, $src2", []>; + +// @LOCALMOD-END + // Return RA. let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in def RetRA : PseudoSE<(outs), (ins), "", [(MipsRet)]>; diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 5fa6339338..d8119ff75c 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -160,3 +160,4 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { } } + diff --git a/lib/Target/Mips/MipsNaClHeaders.cpp b/lib/Target/Mips/MipsNaClHeaders.cpp new file mode 100644 index 0000000000..375c287d67 --- /dev/null +++ b/lib/Target/Mips/MipsNaClHeaders.cpp @@ -0,0 +1,128 @@ +//===-- MipsNaClHeaders.cpp - Print SFI headers to an Mips .s file --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the initial header string needed +// for the Native Client target in Mips assembly. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_ostream.h" +#include "MipsNaClRewritePass.h" +#include <string> + +using namespace llvm; + +void EmitMipsSFIHeaders(raw_ostream &O) { + O << " # ========================================\n"; + O << "# Branch: " << FlagSfiBranch << "\n"; + O << "# Stack: " << FlagSfiStack << "\n"; + O << "# Store: " << FlagSfiStore << "\n"; + O << "# Load: " << FlagSfiLoad << "\n"; + + O << " # ========================================\n"; + // NOTE: this macro does bundle alignment as follows + // if current bundle pos is X emit pX data items of value "val" + // NOTE: that pos will be one of: 0,4,8,12 + // + O << + "\t.macro sfi_long_based_on_pos p0 p1 p2 p3 val\n" + "\t.set pos, (. - XmagicX) % 16\n" + "\t.fil |