diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td index a76715a092f..46915eecf6f 100644 --- a/lib/Target/ARM/ARM.td +++ b/lib/Target/ARM/ARM.td @@ -110,6 +110,11 @@ def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true", def FeatureMClass : SubtargetFeature<"mclass", "IsMClass", "true", "Is microcontroller profile ('M' series)">; +// Special TRAP encoding for NaCl, which looks like a TRAP in Thumb too. +// See ARMInstrInfo.td for details. +def FeatureNaClTrap : SubtargetFeature<"nacl-trap", "UseNaClTrap", "true", + "NaCl trap">; + // ARM ISAs. def HasV4TOps : SubtargetFeature<"v4t", "HasV4TOps", "true", "Support ARM v4T instructions">; diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 397736a2bf3..577cdb09dba 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1693,6 +1693,13 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } break; } + case ARM::TRAPNaCl: { + //.long 0xe7fedef0 @ trap + uint32_t Val = 0xe7fedef0UL; + OutStreamer.AddComment("trap"); + OutStreamer.EmitIntValue(Val, 4); + return; + } case ARM::tTRAP: { // Non-Darwin binutils don't yet support the "trap" mnemonic. // FIXME: Remove this special case when they do. diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 94c574aa7e2..a2d0cde526f 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -2562,7 +2562,8 @@ bool ARMFastISel::SelectIntrinsicCall(const IntrinsicInst &I) { return SelectCall(&I, "memset"); } case Intrinsic::trap: { - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(ARM::TRAP)); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get( + Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP)); return true; } } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 6beb1abd222..82b475a44f3 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -6303,7 +6303,16 @@ EmitSjLjDispatchBlock(MachineInstr *MI, MachineBasicBlock *MBB) const { DispatchBB->setIsLandingPad(); MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); - BuildMI(TrapBB, dl, TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP)); + unsigned trap_opcode; + if (Subtarget->isThumb()) { + trap_opcode = ARM::tTRAP; + } else { + if (Subtarget->useNaClTrap()) + trap_opcode = ARM::TRAPNaCl; + else + trap_opcode = ARM::TRAP; + } + BuildMI(TrapBB, dl, TII->get(trap_opcode)); DispatchBB->addSuccessor(TrapBB); MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock(); @@ -10317,4 +10326,3 @@ bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, return false; } - diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 12712c007b2..e31c479ffc2 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -239,6 +239,9 @@ def IsARM : Predicate<"!Subtarget->isThumb()">, def IsIOS : Predicate<"Subtarget->isTargetIOS()">; def IsNotIOS : Predicate<"!Subtarget->isTargetIOS()">; def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; +def UseNaClTrap : Predicate<"Subtarget->useNaClTrap()">, + AssemblerPredicate<"FeatureNaClTrap", "NaCl">; +def DontUseNaClTrap : Predicate<"!Subtarget->useNaClTrap()">; // FIXME: Eventually this will be just "hasV6T2Ops". def UseMovt : Predicate<"Subtarget->useMovt()">; @@ -1762,11 +1765,32 @@ def DBG : AI<(outs), (ins imm0_15:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt", let Inst{3-0} = opt; } -// A5.4 Permanently UNDEFINED instructions. +/* + * A5.4 Permanently UNDEFINED instructions. + * + * For most targets use UDF #65006, for which the OS will generate SIGTRAP. + * Other UDF encodings generate SIGILL. + * + * NaCl's OS instead chooses an ARM UDF encoding that's also a UDF in Thumb. + * Encoding A1: + * 1110 0111 1111 iiii iiii iiii 1111 iiii + * Encoding T1: + * 1101 1110 iiii iiii + * It uses the following encoding: + * 1110 0111 1111 1110 1101 1110 1111 0000 + * - In ARM: UDF #60896; + * - In Thumb: UDF #254 followed by a branch-to-self. + */ +let isBarrier = 1, isTerminator = 1 in +def TRAPNaCl : AXI<(outs), (ins), MiscFrm, NoItinerary, + "trap", [(trap)]>, + Requires<[IsARM,UseNaClTrap]> { + let Inst = 0xe7fedef0; +} let isBarrier = 1, isTerminator = 1 in def TRAP : AXI<(outs), (ins), MiscFrm, NoItinerary, "trap", [(trap)]>, - Requires<[IsARM]> { + Requires<[IsARM,DontUseNaClTrap]> { let Inst = 0xe7ffdefe; } diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index f84e7a28d36..c3dea00de88 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -80,6 +80,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, , FPOnlySP(false) , AllowsUnalignedMem(false) , Thumb2DSP(false) + , UseNaClTrap(false) , stackAlignment(4) , CPUString(CPU) , TargetTriple(TT) diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 64878cd9ba1..33efabfc000 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -156,6 +156,9 @@ protected: /// and such) instructions in Thumb2 code. bool Thumb2DSP; + /// NaCl TRAP instruction is generated instead of the regular TRAP. + bool UseNaClTrap; + /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. unsigned stackAlignment; @@ -241,6 +244,7 @@ protected: bool hasRAS() const { return HasRAS; } bool hasMPExtension() const { return HasMPExtension; } bool hasThumb2DSP() const { return Thumb2DSP; } + bool useNaClTrap() const { return UseNaClTrap; } bool hasFP16() const { return HasFP16; } bool hasD16() const { return HasD16; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index f4958f3a380..f09fb5a94fd 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "ARMMCTargetDesc.h" #include "ARMBaseInfo.h" #include "ARMELFStreamer.h" #include "ARMMCAsmInfo.h" +#include "ARMMCTargetDesc.h" #include "InstPrinter/ARMInstPrinter.h" +#include "llvm/ADT/Triple.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" @@ -37,6 +38,8 @@ using namespace llvm; std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { + Triple triple(TT); + // Set the boolean corresponding to the current target triple, or the default // if one cannot be determined, to true. unsigned Len = TT.size(); @@ -119,6 +122,13 @@ std::string ARM_MC::ParseARMTriple(StringRef TT, StringRef CPU) { ARMArchFeature += ",+thumb-mode"; } + if (triple.isOSNaCl()) { + if (ARMArchFeature.empty()) + ARMArchFeature = "+nacl-trap"; + else + ARMArchFeature += ",+nacl-trap"; + } + return ARMArchFeature; } diff --git a/test/CodeGen/ARM/trap.ll b/test/CodeGen/ARM/trap.ll index 21865f8e4ae..a4e3c3c0efa 100644 --- a/test/CodeGen/ARM/trap.ll +++ b/test/CodeGen/ARM/trap.ll @@ -1,5 +1,23 @@ ; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s -check-prefix=INSTR ; RUN: llc < %s -mtriple=arm-apple-darwin -trap-func=_trap | FileCheck %s -check-prefix=FUNC +; RUN: llc -mtriple=armv7-unknown-nacl -filetype=obj %s -o - \ +; RUN: | llvm-objdump -disassemble -triple armv7-unknown-nacl - \ +; RUN: | FileCheck %s -check-prefix=ENCODING-NACL +; RUN: llc -mtriple=armv7-unknown-nacl -filetype=obj %s -o - \ +; RUN: | llvm-objdump -disassemble -triple armv7 -mattr=+nacl-trap - \ +; RUN: | FileCheck %s -check-prefix=ENCODING-NACL +; RUN: llc -mtriple=armv7 -mattr=+nacl-trap -filetype=obj %s -o - \ +; RUN: | llvm-objdump -disassemble -triple armv7 -mattr=+nacl-trap - \ +; RUN: | FileCheck %s -check-prefix=ENCODING-NACL +; RUN: llc -fast-isel -mtriple=armv7-unknown-nacl -filetype=obj %s -o - \ +; RUN: | llvm-objdump -disassemble -triple armv7-unknown-nacl - \ +; RUN: | FileCheck %s -check-prefix=ENCODING-NACL +; RUN: llc -mtriple=armv7 -filetype=obj %s -o - \ +; RUN: | llvm-objdump -disassemble -triple armv7 - \ +; RUN: | FileCheck %s -check-prefix=ENCODING-ALL +; RUN: llc -fast-isel -mtriple=armv7 -filetype=obj %s -o - \ +; RUN: | llvm-objdump -disassemble -triple armv7 - \ +; RUN: | FileCheck %s -check-prefix=ENCODING-ALL ; rdar://7961298 ; rdar://9249183 @@ -10,6 +28,11 @@ entry: ; FUNC: t: ; FUNC: bl __trap + +; ENCODING-NACL: f0 de fe e7 + +; ENCODING-ALL: fe de ff e7 + call void @llvm.trap() unreachable } @@ -21,6 +44,11 @@ entry: ; FUNC: t2: ; FUNC: bl __trap + +; ENCODING-NACL: f0 de fe e7 + +; ENCODING-ALL: fe de ff e7 + call void @llvm.debugtrap() unreachable } diff --git a/test/MC/ARM/arm_instructions.s b/test/MC/ARM/arm_instructions.s index ce7e036b3be..a4b6bda880c 100644 --- a/test/MC/ARM/arm_instructions.s +++ b/test/MC/ARM/arm_instructions.s @@ -1,7 +1,14 @@ -@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s +@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s \ +@ RUN: | FileCheck %s -check-prefix=ALL +@ RUN: llvm-mc -mcpu=cortex-a9-mp -triple armv7-unknown-nacl -show-encoding %s \ +@ RUN: | FileCheck %s -check-prefix=NACL +@ RUN: llvm-mc -mcpu=cortex-a8 -mattr=+nacl-trap -triple armv7 -show-encoding %s \ +@ RUN: | FileCheck %s -check-prefix=NACL -@ CHECK: trap -@ CHECK: encoding: [0xfe,0xde,0xff,0xe7] +@ ALL: trap +@ ALL: encoding: [0xfe,0xde,0xff,0xe7] +@ NACL: trap +@ NACL: encoding: [0xf0,0xde,0xfe,0xe7] trap @ CHECK: bx lr