diff options
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp | 15 | ||||
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsMCNaCl.cpp | 261 | ||||
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h | 19 | ||||
-rw-r--r-- | lib/Target/Mips/Mips.h | 14 | ||||
-rw-r--r-- | lib/Target/Mips/MipsAsmPrinter.cpp | 45 | ||||
-rw-r--r-- | lib/Target/Mips/MipsAsmPrinter.h | 4 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelDAGToDAG.cpp | 2 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelLowering.cpp | 58 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelLowering.h | 5 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrFPU.td | 9 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.td | 33 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMCInstLower.cpp | 45 | ||||
-rw-r--r-- | lib/Target/Mips/MipsNaClHeaders.cpp | 128 | ||||
-rw-r--r-- | lib/Target/Mips/MipsNaClRewritePass.cpp | 333 | ||||
-rw-r--r-- | lib/Target/Mips/MipsNaClRewritePass.h | 21 | ||||
-rw-r--r-- | lib/Target/Mips/MipsRegisterInfo.cpp | 1 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSubtarget.cpp | 3 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSubtarget.h | 9 | ||||
-rw-r--r-- | lib/Target/Mips/MipsTargetMachine.cpp | 8 | ||||
-rw-r--r-- | lib/Target/Mips/MipsTargetObjectFile.cpp | 23 |
20 files changed, 1030 insertions, 6 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/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 6ca41624d3..1bf4a542d8 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -229,13 +229,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); @@ -539,6 +550,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. @@ -560,7 +575,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/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index ceff6dd9b9..0d47303e92 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 d8097032ca..e9f330ffc1 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -321,6 +321,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); @@ -870,6 +877,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(); } @@ -1766,6 +1778,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 { @@ -1780,6 +1810,34 @@ 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 TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT); + + ArgListTy Args; + std::pair<SDValue, SDValue> CallResult = + LowerCallTo(DAG.getEntryNode(), + (Type *) Type::getInt32Ty(*DAG.getContext()), + false, false, false, false, 0, CallingConv::C, false, + false, true, TlsGetAddr, Args, DAG, dl); + + SDValue ThreadPointer = CallResult.first; + return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, 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 b4cc16c1ca..2dce449765 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -205,6 +205,11 @@ namespace llvm { SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) 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 685b785bd2..6fa94a96e5 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -170,6 +170,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]; @@ -810,6 +812,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..1d108ab192 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -160,3 +160,48 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { } } + + MCInst Instr4, Mask1, Mask2; // @LOCALMOD + // @LOCALMOD-START + MCOperand MaskReg = MCOperand::CreateReg(Mips::LoadStoreStackMaskReg); + // @LOCALMOD-END + + // @LOCALMOD-START + if (AsmPrinter.TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + Mask1.setOpcode(Mips::SFI_GUARD_LOADSTORE); + Mask1.addOperand(Base); + Mask1.addOperand(Base); + Mask1.addOperand(MaskReg); + + Mask2.setOpcode(Mips::SFI_GUARD_LOADSTORE); + Mask2.addOperand(Base); + Mask2.addOperand(Base); + Mask2.addOperand(MaskReg); + if (Opc == Mips::ULW || Opc == Mips::USW || Opc == Mips::ULHu) { + // FIXME: ULHu should be rewritten because it uses mips32r2 instr. INS + MCInsts.push_back(Mask1); + MCInsts.push_back(Instr1); + MCInsts.push_back(Mask2); + MCInsts.push_back(Instr2); + if (!TwoInstructions) MCInsts.push_back(Instr3); + return; + } else if (Opc == Mips::ULH) { + MCInsts.push_back(Mask1); + MCInsts.push_back(Instr1); + MCInsts.push_back(Mask2); + MCInsts.push_back(Instr2); + MCInsts.push_back(Instr3); + MCInsts.push_back(Instr4); + return; + } else if (Opc == Mips::USH) { + MCInsts.push_back(Mask1); + MCInsts.push_back(Instr1); + MCInsts.push_back(Instr2); + MCInsts.push_back(Mask2); + MCInsts.push_back(Instr3); + return; + } else { + llvm_unreachable("unaligned instruction not sandboxed"); + } + } + // @LOCALMOD-END
\ No newline at end of file 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.fill (((\\p3<<12)|(\\p2<<8)|(\\p1<<4)|\\p0)>>pos) & 15, 4, \\val\n" + "\t.endm\n" + "\n\n"; + + O << + "\t.macro sfi_nop_if_at_bundle_end\n" + "\tsfi_long_based_on_pos 0 0 0 1 0x00000000\n" + "\t.endm\n" + "\n\n"; + + O << + "\t.macro sfi_nops_to_force_slot3\n" + "\tsfi_long_based_on_pos 3 2 1 0 0x00000000\n" + "\t.endm\n" + "\n\n"; + + O << + "\t.macro sfi_nops_to_force_slot2\n" + "\tsfi_long_based_on_pos 2 1 0 3 0x00000000\n" + "\t.endm\n" + "\n\n"; + + O << + "\t.macro sfi_nops_to_force_slot1\n" + "\tsfi_long_based_on_pos 1 0 3 2 0x00000000\n" + "\t.endm\n" + "\n\n"; + + O << " # ========================================\n"; + O << + "\t.macro sfi_data_mask reg1 reg2 maskreg\n" + "\tand \\reg1, \\reg2, \\maskreg\n" + "\t.endm\n" + "\n\n"; + + O << + "\t.macro sfi_code_mask reg1 reg2 maskreg\n" + "\tand \\reg1, \\reg2, \\maskreg\n" + "\t.endm\n" + "\n\n"; + + O << " # ========================================\n"; + if (FlagSfiBranch) { + O << + "\t.macro sfi_call_preamble\n" + "\tsfi_nops_to_force_slot2\n" + "\t.endm\n" + "\n\n"; + + O << + "\t.macro sfi_return_preamble reg1 reg2 maskreg\n" + "\tsfi_nop_if_at_bundle_end\n" + "\tsfi_code_mask \\reg1, \\reg2, \\maskreg\n" + "\t.endm\n" + "\n\n"; + + // This is used just before "jr" + O << + "\t.macro sfi_indirect_jump_preamble reg1 reg2 maskreg\n" + "\tsfi_nop_if_at_bundle_end\n" + "\tsfi_code_mask \\reg1, \\reg2, \\maskreg\n" + "\t.endm\n" + "\n\n"; + + // This is used just before "jalr" + O << + |