Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: lib/Target/X86/MCTargetDesc/X86MCNaCl.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Target/X86/MCTargetDesc/X86MCNaCl.h ('k') | lib/Target/X86/X86.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //=== X86MCNaCl.cpp - Expansion of NaCl pseudo-instructions --*- C++ -*-=//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //===----------------------------------------------------------------------===//
11 #define DEBUG_TYPE "x86-sandboxing"
12
13 #include "MCTargetDesc/X86MCTargetDesc.h"
14 #include "MCTargetDesc/X86BaseInfo.h"
15 #include "MCTargetDesc/X86MCNaCl.h"
16 #include "X86NaClDecls.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCObjectFileInfo.h"
24 #include "llvm/MC/MCStreamer.h"
25 #include "llvm/CodeGen/ValueTypes.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Debug.h"
28
29 using namespace llvm;
30
31 cl::opt<bool> FlagUseZeroBasedSandbox("sfi-zero-based-sandbox",
32 cl::desc("Use a zero-based sandbox model"
33 " for the NaCl SFI."),
34 cl::init(false));
35 // This flag can be set to false to test the performance impact of
36 // hiding the sandbox base.
37 cl::opt<bool> FlagHideSandboxBase("sfi-hide-sandbox-base",
38 cl::desc("Prevent 64-bit NaCl sandbox"
39 " pointers from being written to"
40 " the stack. [default=true]"),
41 cl::init(true));
42
43 const int kNaClX86InstructionBundleSize = 32;
44
45 // See the notes below where these functions are defined.
46 namespace {
47 unsigned getX86SubSuperRegister_(unsigned Reg, EVT VT, bool High=false);
48 unsigned DemoteRegTo32_(unsigned RegIn);
49 } // namespace
50
51 static MCSymbol *CreateTempLabel(MCContext &Context, const char *Prefix) {
52 SmallString<128> NameSV;
53 raw_svector_ostream(NameSV)
54 << Context.getAsmInfo()->getPrivateGlobalPrefix() // get internal label
55 << Prefix << Context.getUniqueSymbolID();
56 return Context.GetOrCreateSymbol(NameSV);
57 }
58
59 static void PushReturnAddress(const llvm::MCSubtargetInfo &STI,
60 MCContext &Context, MCStreamer &Out,
61 MCSymbol *RetTarget) {
62 const MCExpr *RetTargetExpr = MCSymbolRefExpr::Create(RetTarget, Context);
63 if (Context.getObjectFileInfo()->getRelocM() == Reloc::PIC_) {
64 // Calculate return_addr
65 // The return address should not be calculated into R11 because if the push
66 // instruction ends up at the start of a bundle, an attacker could arrange
67 // an indirect jump to it, which would push the full jump target
68 // (which itself was calculated into r11) onto the stack.
69 MCInst LEAInst;
70 LEAInst.setOpcode(X86::LEA64_32r);
71 LEAInst.addOperand(MCOperand::CreateReg(X86::R10D)); // DestReg
72 LEAInst.addOperand(MCOperand::CreateReg(X86::RIP)); // BaseReg
73 LEAInst.addOperand(MCOperand::CreateImm(1)); // Scale
74 LEAInst.addOperand(MCOperand::CreateReg(0)); // IndexReg
75 LEAInst.addOperand(MCOperand::CreateExpr(RetTargetExpr)); // Offset
76 LEAInst.addOperand(MCOperand::CreateReg(0)); // SegmentReg
77 Out.EmitInstruction(LEAInst, STI);
78 // push return_addr
79 MCInst PUSHInst;
80 PUSHInst.setOpcode(X86::PUSH64r);
81 PUSHInst.addOperand(MCOperand::CreateReg(X86::R10));
82 Out.EmitInstruction(PUSHInst, STI);
83 } else {
84 // push return_addr
85 MCInst PUSHInst;
86 PUSHInst.setOpcode(X86::PUSH64i32);
87 PUSHInst.addOperand(MCOperand::CreateExpr(RetTargetExpr));
88 Out.EmitInstruction(PUSHInst, STI);
89 }
90 }
91
92 static void EmitDirectCall(const llvm::MCSubtargetInfo &STI,
93 const MCOperand &Op, bool Is64Bit, MCStreamer &Out) {
94 const bool HideSandboxBase =
95 (FlagHideSandboxBase && Is64Bit && !FlagUseZeroBasedSandbox);
96 if (HideSandboxBase) {
97 // For NaCl64, the sequence
98 // call target
99 // return_addr:
100 // is changed to
101 // push return_addr
102 // jmp target
103 // .align 32
104 // return_addr:
105 // This avoids exposing the sandbox base address via the return
106 // address on the stack.
107
108 // When generating PIC code, calculate the return address manually:
109 // leal return_addr(%rip), %r10d
110 // push %r10
111 // jmp target
112 // .align 32
113 // return_addr:
114
115 MCContext &Context = Out.getContext();
116
117 // Generate a label for the return address.
118 MCSymbol *RetTarget = CreateTempLabel(Context, "DirectCallRetAddr");
119
120 PushReturnAddress(STI, Context, Out, RetTarget);
121
122 // jmp target
123 MCInst JMPInst;
124 JMPInst.setOpcode(X86::JMP_4);
125 JMPInst.addOperand(Op);
126 Out.EmitInstruction(JMPInst, STI);
127
128 Out.EmitCodeAlignment(kNaClX86InstructionBundleSize);
129 Out.EmitLabel(RetTarget);
130 } else {
131 Out.EmitBundleLock(true);
132
133 MCInst CALLInst;
134 CALLInst.setOpcode(Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);
135 CALLInst.addOperand(Op);
136 Out.EmitInstruction(CALLInst, STI);
137 Out.EmitBundleUnlock();
138 }
139 }
140
141 static void EmitIndirectBranch(const llvm::MCSubtargetInfo &STI,
142 const MCOperand &Op, bool Is64Bit, bool IsCall,
143 MCStreamer &Out) {
144 const bool HideSandboxBase =
145 (FlagHideSandboxBase && Is64Bit && !FlagUseZeroBasedSandbox);
146 const int JmpMask = -kNaClX86InstructionBundleSize;
147 unsigned Reg32 = Op.getReg();
148
149 // For NaCl64, the sequence
150 // jmp *%rXX
151 // is changed to
152 // mov %rXX,%r11d
153 // and $0xffffffe0,%r11d
154 // add %r15,%r11
155 // jmpq *%r11
156 //
157 // And the sequence
158 // call *%rXX
159 // return_addr:
160 // is changed to
161 // mov %rXX,%r11d
162 // push return_addr
163 // and $0xffffffe0,%r11d
164 // add %r15,%r11
165 // jmpq *%r11
166 // .align 32
167 // return_addr:
168 //
169 // This avoids exposing the sandbox base address via the return
170 // address on the stack.
171
172 // When generating PIC code for calls, calculate the return address manually:
173 // mov %rXX,%r11d
174 // leal return_addr(%rip), %r10d
175 // pushq %r10
176 // and $0xffffffe0,%r11d
177 // add %r15,%r11
178 // jmpq *%r11
179 // .align 32
180 // return_addr:
181
182 MCSymbol *RetTarget = NULL;
183
184 // For NaCl64, force an assignment of the branch target into r11,
185 // and subsequently use r11 as the ultimate branch target, so that
186 // only r11 (which will never be written to memory) exposes the
187 // sandbox base address. But avoid a redundant assignment if the
188 // original branch target is already r11 or r11d.
189 const unsigned SafeReg32 = X86::R11D;
190 const unsigned SafeReg64 = X86::R11;
191 if (HideSandboxBase) {
192 // In some cases, EmitIndirectBranch() is called with a 32-bit
193 // register Op (e.g. r11d), and in other cases a 64-bit register
194 // (e.g. r11), so we need to test both variants to avoid a
195 // redundant assignment. TODO(stichnot): Make callers consistent
196 // on 32 vs 64 bit register.
197 if ((Reg32 != SafeReg32) && (Reg32 != SafeReg64)) {
198 MCInst MOVInst;
199 MOVInst.setOpcode(X86::MOV32rr);
200 MOVInst.addOperand(MCOperand::CreateReg(SafeReg32));
201 MOVInst.addOperand(MCOperand::CreateReg(Reg32));
202 Out.EmitInstruction(MOVInst, STI);
203 Reg32 = SafeReg32;
204 }
205 if (IsCall) {
206 MCContext &Context = Out.getContext();
207 // Generate a label for the return address.
208 RetTarget = CreateTempLabel(Context, "IndirectCallRetAddr");
209 // Explicitly push the (32-bit) return address for a NaCl64 call
210 // instruction.
211 PushReturnAddress(STI, Context, Out, RetTarget);
212 }
213 }
214 const unsigned Reg64 = getX86SubSuperRegister_(Reg32, MVT::i64);
215
216 const bool WillEmitCallInst = IsCall && !HideSandboxBase;
217 Out.EmitBundleLock(WillEmitCallInst);
218
219 MCInst ANDInst;
220 ANDInst.setOpcode(X86::AND32ri8);
221 ANDInst.addOperand(MCOperand::CreateReg(Reg32));
222 ANDInst.addOperand(MCOperand::CreateReg(Reg32));
223 ANDInst.addOperand(MCOperand::CreateImm(JmpMask));
224 Out.EmitInstruction(ANDInst, STI);
225
226 if (Is64Bit && !FlagUseZeroBasedSandbox) {
227 MCInst InstADD;
228 InstADD.setOpcode(X86::ADD64rr);
229 InstADD.addOperand(MCOperand::CreateReg(Reg64));
230 InstADD.addOperand(MCOperand::CreateReg(Reg64));
231 InstADD.addOperand(MCOperand::CreateReg(X86::R15));
232 Out.EmitInstruction(InstADD, STI);
233 }
234
235 if (WillEmitCallInst) {
236 // callq *%rXX
237 MCInst CALLInst;
238 CALLInst.setOpcode(Is64Bit ? X86::CALL64r : X86::CALL32r);
239 CALLInst.addOperand(MCOperand::CreateReg(Is64Bit ? Reg64 : Reg32));
240 Out.EmitInstruction(CALLInst, STI);
241 } else {
242 // jmpq *%rXX -or- jmpq *%r11
243 MCInst JMPInst;
244 JMPInst.setOpcode(Is64Bit ? X86::JMP64r : X86::JMP32r);
245 JMPInst.addOperand(MCOperand::CreateReg(Is64Bit ? Reg64 : Reg32));
246 Out.EmitInstruction(JMPInst, STI);
247 }
248 Out.EmitBundleUnlock();
249 if (RetTarget) {
250 Out.EmitCodeAlignment(kNaClX86InstructionBundleSize);
251 Out.EmitLabel(RetTarget);
252 }
253 }
254
255 static void EmitRet(const llvm::MCSubtargetInfo &STI, const MCOperand *AmtOp,
256 bool Is64Bit, MCStreamer &Out) {
257 // For NaCl64 returns, follow the convention of using r11 to hold
258 // the target of an indirect jump to avoid potentially leaking the
259 // sandbox base address.
260 const bool HideSandboxBase = (FlagHideSandboxBase &&
261 Is64Bit && !FlagUseZeroBasedSandbox);
262 // For NaCl64 sandbox hiding, use r11 to hold the branch target.
263 // Otherwise, use rcx/ecx for fewer instruction bytes (no REX
264 // prefix).
265 const unsigned RegTarget = HideSandboxBase ? X86::R11 :
266 (Is64Bit ? X86::RCX : X86::ECX);
267 MCInst POPInst;
268 POPInst.setOpcode(Is64Bit ? X86::POP64r : X86::POP32r);
269 POPInst.addOperand(MCOperand::CreateReg(RegTarget));
270 Out.EmitInstruction(POPInst, STI);
271
272 if (AmtOp) {
273 assert(!Is64Bit);
274 MCInst ADDInst;
275 unsigned ADDReg = X86::ESP;
276 ADDInst.setOpcode(X86::ADD32ri);
277 ADDInst.addOperand(MCOperand::CreateReg(ADDReg));
278 ADDInst.addOperand(MCOperand::CreateReg(ADDReg));
279 ADDInst.addOperand(*AmtOp);
280 Out.EmitInstruction(ADDInst, STI);
281 }
282
283 EmitIndirectBranch(STI, MCOperand::CreateReg(RegTarget), Is64Bit, false, Out);
284 }
285
286 // Fix a register after being truncated to 32-bits.
287 static void EmitRegFix(const llvm::MCSubtargetInfo &STI, unsigned Reg64,
288 MCStreamer &Out) {
289 // lea (%rsp, %r15, 1), %rsp
290 // We do not need to add the R15 base for the zero-based sandbox model
291 if (!FlagUseZeroBasedSandbox) {
292 MCInst Tmp;
293 Tmp.setOpcode(X86::LEA64r);
294 Tmp.addOperand(MCOperand::CreateReg(Reg64)); // DestReg
295 Tmp.addOperand(MCOperand::CreateReg(Reg64)); // BaseReg
296 Tmp.addOperand(MCOperand::CreateImm(1)); // Scale
297 Tmp.addOperand(MCOperand::CreateReg(X86::R15)); // IndexReg
298 Tmp.addOperand(MCOperand::CreateImm(0)); // Offset
299 Tmp.addOperand(MCOperand::CreateReg(0)); // SegmentReg
300 Out.EmitInstruction(Tmp, STI);
301 }
302 }
303
304 static void EmitSPArith(const llvm::MCSubtargetInfo &STI, unsigned Opc,
305 const MCOperand &ImmOp, MCStreamer &Out) {
306 Out.EmitBundleLock(false);
307
308 MCInst Tmp;
309 Tmp.setOpcode(Opc);
310 Tmp.addOperand(MCOperand::CreateReg(X86::ESP));
311 Tmp.addOperand(MCOperand::CreateReg(X86::ESP));
312 Tmp.addOperand(ImmOp);
313 Out.EmitInstruction(Tmp, STI);
314
315 EmitRegFix(STI, X86::RSP, Out);
316 Out.EmitBundleUnlock();
317 }
318
319 static void EmitSPAdj(const llvm::MCSubtargetInfo &STI, const MCOperand &ImmOp,
320 MCStreamer &Out) {
321 Out.EmitBundleLock(false);
322
323 MCInst Tmp;
324 Tmp.setOpcode(X86::LEA64_32r);
325 Tmp.addOperand(MCOperand::CreateReg(X86::RSP)); // DestReg
326 Tmp.addOperand(MCOperand::CreateReg(X86::RBP)); // BaseReg
327 Tmp.addOperand(MCOperand::CreateImm(1)); // Scale
328 Tmp.addOperand(MCOperand::CreateReg(0)); // IndexReg
329 Tmp.addOperand(ImmOp); // Offset
330 Tmp.addOperand(MCOperand::CreateReg(0)); // SegmentReg
331 Out.EmitInstruction(Tmp, STI);
332
333 EmitRegFix(STI, X86::RSP, Out);
334 Out.EmitBundleUnlock();
335 }
336
337 static void EmitPrefix(const llvm::MCSubtargetInfo &STI, unsigned Opc,
338 MCStreamer &Out, X86MCNaClSFIState &State) {
339 assert(State.PrefixSaved == 0);
340 assert(State.PrefixPass == false);
341
342 MCInst PrefixInst;
343 PrefixInst.setOpcode(Opc);
344 State.PrefixPass = true;
345 Out.EmitInstruction(PrefixInst, STI);
346
347 assert(State.PrefixSaved == 0);
348 assert(State.PrefixPass == false);
349 }
350
351 static void EmitMoveRegReg(const llvm::MCSubtargetInfo &STI, bool Is64Bit,
352 unsigned ToReg, unsigned FromReg, MCStreamer &Out) {
353 MCInst Move;
354 Move.setOpcode(Is64Bit ? X86::MOV64rr : X86::MOV32rr);
355 Move.addOperand(MCOperand::CreateReg(ToReg));
356 Move.addOperand(MCOperand::CreateReg(FromReg));
357 Out.EmitInstruction(Move, STI);
358 }
359
360 static void EmitRegTruncate(const llvm::MCSubtargetInfo &STI, unsigned Reg64,
361 MCStreamer &Out) {
362 unsigned Reg32 = getX86SubSuperRegister_(Reg64, MVT::i32);
363 EmitMoveRegReg(STI, false, Reg32, Reg32, Out);
364 }
365
366 static void HandleMemoryRefTruncation(const llvm::MCSubtargetInfo &STI,
367 MCInst *Inst, unsigned IndexOpPosition,
368 MCStreamer &Out) {
369 unsigned IndexReg = Inst->getOperand(IndexOpPosition).getReg();
370 if (FlagUseZeroBasedSandbox) {
371 // With the zero-based sandbox, we use a 32-bit register on the index
372 Inst->getOperand(IndexOpPosition).setReg(DemoteRegTo32_(IndexReg));
373 } else {
374 EmitRegTruncate(STI, IndexReg, Out);
375 }
376 }
377
378 static void ShortenMemoryRef(MCInst *Inst, unsigned IndexOpPosition) {
379 unsigned ImmOpPosition = IndexOpPosition - 1;
380 unsigned BaseOpPosition = IndexOpPosition - 2;
381 unsigned IndexReg = Inst->getOperand(IndexOpPosition).getReg();
382 // For the SIB byte, if the scale is 1 and the base is 0, then
383 // an equivalent setup moves index to base, and index to 0. The
384 // equivalent setup is optimized to remove the SIB byte in
385 // X86MCCodeEmitter.cpp.
386 if (Inst->getOperand(ImmOpPosition).getImm() == 1 &&
387 Inst->getOperand(BaseOpPosition).getReg() == 0) {
388 Inst->getOperand(BaseOpPosition).setReg(IndexReg);
389 Inst->getOperand(IndexOpPosition).setReg(0);
390 }
391 }
392
393 static void EmitLoad(const llvm::MCSubtargetInfo &STI, bool Is64Bit,
394 unsigned DestReg, unsigned BaseReg, unsigned Scale,
395 unsigned IndexReg, unsigned Offset, unsigned SegmentReg,
396 MCStreamer &Out) {
397 // Load DestReg from address BaseReg + Scale * IndexReg + Offset
398 MCInst Load;
399 Load.setOpcode(Is64Bit ? X86::MOV64rm : X86::MOV32rm);
400 Load.addOperand(MCOperand::CreateReg(DestReg));
401 Load.addOperand(MCOperand::CreateReg(BaseReg));
402 Load.addOperand(MCOperand::CreateImm(Scale));
403 Load.addOperand(MCOperand::CreateReg(IndexReg));
404 Load.addOperand(MCOperand::CreateImm(Offset));
405 Load.addOperand(MCOperand::CreateReg(SegmentReg));
406 Out.EmitInstruction(Load, STI);
407 }
408
409 static bool SandboxMemoryRef(MCInst *Inst,
410 unsigned *IndexOpPosition) {
411 for (unsigned i = 0, last = Inst->getNumOperands(); i < last; i++) {
412 if (!Inst->getOperand(i).isReg() ||
413 Inst->getOperand(i).getReg() != X86::PSEUDO_NACL_SEG) {
414 continue;
415 }
416 // Return the index register that will need to be truncated.
417 // The order of operands on a memory reference is always:
418 // (BaseReg, ScaleImm, IndexReg, DisplacementImm, SegmentReg),
419 // So if we found a match for a segment register value, we know that
420 // the index register is exactly two operands prior.
421 *IndexOpPosition = i - 2;
422
423 // Remove the PSEUDO_NACL_SEG annotation.
424 Inst->getOperand(i).setReg(0);
425 return true;
426 }
427 return false;
428 }
429
430 static void EmitREST(const llvm::MCSubtargetInfo &STI, const MCInst &Inst,
431 unsigned Reg32, bool IsMem, MCStreamer &Out) {
432 unsigned Reg64 = getX86SubSuperRegister_(Reg32, MVT::i64);
433 Out.EmitBundleLock(false);
434 if (!IsMem) {
435 EmitMoveRegReg(STI, false, Reg32, Inst.getOperand(0).getReg(), Out);
436 } else {
437 unsigned IndexOpPosition;
438 MCInst SandboxedInst = Inst;
439 if (SandboxMemoryRef(&SandboxedInst, &IndexOpPosition)) {
440 HandleMemoryRefTruncation(STI, &SandboxedInst, IndexOpPosition, Out);
441 ShortenMemoryRef(&SandboxedInst, IndexOpPosition);
442 }
443 EmitLoad(STI, false, Reg32,
444 SandboxedInst.getOperand(0).getReg(), // BaseReg
445 SandboxedInst.getOperand(1).getImm(), // Scale
446 SandboxedInst.getOperand(2).getReg(), // IndexReg
447 SandboxedInst.getOperand(3).getImm(), // Offset
448 SandboxedInst.getOperand(4).getReg(), // SegmentReg
449 Out);
450 }
451
452 EmitRegFix(STI, Reg64, Out);
453 Out.EmitBundleUnlock();
454 }
455
456
457 namespace {
458 // RAII holder for the recursion guard.
459 class EmitRawState {
460 public:
461 EmitRawState(X86MCNaClSFIState &S) : State(S) {
462 State.EmitRaw = true;
463 }
464 ~EmitRawState() {
465 State.EmitRaw = false;
466 }
467 private:
468 X86MCNaClSFIState &State;
469 };
470 }
471
472 namespace llvm {
473 // CustomExpandInstNaClX86 -
474 // If Inst is a NaCl pseudo instruction, emits the substitute
475 // expansion to the MCStreamer and returns true.
476 // Otherwise, returns false.
477 //
478 // NOTE: Each time this function calls Out.EmitInstruction(), it will be
479 // called again recursively to rewrite the new instruction being emitted.
480 // Care must be taken to ensure that this does not result in an infinite
481 // loop. Also, global state must be managed carefully so that it is
482 // consistent during recursive calls.
483 //
484 // We need global state to keep track of the explicit prefix (PREFIX_*)
485 // instructions. Unfortunately, the assembly parser prefers to generate
486 // these instead of combined instructions. At this time, having only
487 // one explicit prefix is supported.
488 bool CustomExpandInstNaClX86(const llvm::MCSubtargetInfo &STI,
489 const MCInst &Inst, MCStreamer &Out,
490 X86MCNaClSFIState &State) {
491 // If we are emitting to .s, only sandbox pseudos not supported by gas.
492 if (Out.hasRawTextSupport()) {
493 if (!(Inst.getOpcode() == X86::NACL_ANDSPi8 ||
494 Inst.getOpcode() == X86::NACL_ANDSPi32))
495 return false;
496 }
497 // If we make a call to EmitInstruction, we will be called recursively. In
498 // this case we just want the raw instruction to be emitted instead of
499 // handling the insruction here.
500 if (State.EmitRaw == true && !State.PrefixPass) {
501 return false;
502 }
503 EmitRawState E(State);
504 unsigned Opc = Inst.getOpcode();
505 DEBUG(dbgs() << "CustomExpandInstNaClX86("; Inst.dump(); dbgs() << ")\n");
506 switch (Opc) {
507 case X86::LOCK_PREFIX:
508 case X86::REP_PREFIX:
509 case X86::REPNE_PREFIX:
510 case X86::REX64_PREFIX:
511 // Ugly hack because LLVM AsmParser is not smart enough to combine
512 // prefixes back into the instruction they modify.
513 if (State.PrefixPass) {
514 State.PrefixPass = false;
515 State.PrefixSaved = 0;
516 return false;
517 }
518 assert(State.PrefixSaved == 0);
519 State.PrefixSaved = Opc;
520 return true;
521 case X86::CALLpcrel32:
522 assert(State.PrefixSaved == 0);
523 EmitDirectCall(STI, Inst.getOperand(0), false, Out);
524 return true;
525 case X86::CALL64pcrel32:
526 case X86::NACL_CALL64d:
527 assert(State.PrefixSaved == 0);
528 EmitDirectCall(STI, Inst.getOperand(0), true, Out);
529 return true;
530 case X86::NACL_CALL32r:
531 assert(State.PrefixSaved == 0);
532 EmitIndirectBranch(STI, Inst.getOperand(0), false, true, Out);
533 return true;
534 case X86::NACL_CALL64r:
535 assert(State.PrefixSaved == 0);
536 EmitIndirectBranch(STI, Inst.getOperand(0), true, true, Out);
537 return true;
538 case X86::NACL_JMP32r:
539 assert(State.PrefixSaved == 0);
540 EmitIndirectBranch(STI, Inst.getOperand(0), false, false, Out);
541 return true;
542 case X86::NACL_JMP64r:
543 case X86::NACL_JMP64z:
544 assert(State.PrefixSaved == 0);
545 EmitIndirectBranch(STI, Inst.getOperand(0), true, false, Out);
546 return true;
547 case X86::NACL_RET32:
548 assert(State.PrefixSaved == 0);
549 EmitRet(STI, NULL, false, Out);
550 return true;
551 case X86::NACL_RET64:
552 assert(State.PrefixSaved == 0);
553 EmitRet(STI, NULL, true, Out);
554 return true;
555 case X86::NACL_RETI32:
556 assert(State.PrefixSaved == 0);
557 EmitRet(STI, &Inst.getOperand(0), false, Out);
558 return true;
559 case X86::NACL_ASPi8:
560 assert(State.PrefixSaved == 0);
561 EmitSPArith(STI, X86::ADD32ri8, Inst.getOperand(0), Out);
562 return true;
563 case X86::NACL_ASPi32:
564 assert(State.PrefixSaved == 0);
565 EmitSPArith(STI, X86::ADD32ri, Inst.getOperand(0), Out);
566 return true;
567 case X86::NACL_SSPi8:
568 assert(State.PrefixSaved == 0);
569 EmitSPArith(STI, X86::SUB32ri8, Inst.getOperand(0), Out);
570 return true;
571 case X86::NACL_SSPi32:
572 assert(State.PrefixSaved == 0);
573 EmitSPArith(STI, X86::SUB32ri, Inst.getOperand(0), Out);
574 return true;
575 case X86::NACL_ANDSPi8:
576 assert(State.PrefixSaved == 0);
577 EmitSPArith(STI, X86::AND32ri8, Inst.getOperand(0), Out);
578 return true;
579 case X86::NACL_ANDSPi32:
580 assert(State.PrefixSaved == 0);
581 EmitSPArith(STI, X86::AND32ri, Inst.getOperand(0), Out);
582 return true;
583 case X86::NACL_SPADJi32:
584 assert(State.PrefixSaved == 0);
585 EmitSPAdj(STI, Inst.getOperand(0), Out);
586 return true;
587 case X86::NACL_RESTBPm:
588 assert(State.PrefixSaved == 0);
589 EmitREST(STI, Inst, X86::EBP, true, Out);
590 return true;
591 case X86::NACL_RESTBPr:
592 case X86::NACL_RESTBPrz:
593 assert(State.PrefixSaved == 0);
594 EmitREST(STI, Inst, X86::EBP, false, Out);
595 return true;
596 case X86::NACL_RESTSPm:
597 assert(State.PrefixSaved == 0);
598 EmitREST(STI, Inst, X86::ESP, true, Out);
599 return true;
600 case X86::NACL_RESTSPr:
601 case X86::NACL_RESTSPrz:
602 assert(State.PrefixSaved == 0);
603 EmitREST(STI, Inst, X86::ESP, false, Out);
604 return true;
605 }
606
607 unsigned IndexOpPosition;
608 MCInst SandboxedInst = Inst;
609 // If we need to sandbox a memory reference and we have a saved prefix,
610 // use a single bundle-lock/unlock for the whole sequence of
611 // added_truncating_inst + prefix + mem_ref_inst.
612 if (SandboxMemoryRef(&SandboxedInst, &IndexOpPosition)) {
613 unsigned PrefixLocal = State.PrefixSaved;
614 State.PrefixSaved = 0;
615
616 if (PrefixLocal || !FlagUseZeroBasedSandbox)
617 Out.EmitBundleLock(false);
618
619 HandleMemoryRefTruncation(STI, &SandboxedInst, IndexOpPosition, Out);
620 ShortenMemoryRef(&SandboxedInst, IndexOpPosition);
621
622 if (PrefixLocal)
623 EmitPrefix(STI, PrefixLocal, Out, State);
624 Out.EmitInstruction(SandboxedInst, STI);
625
626 if (PrefixLocal || !FlagUseZeroBasedSandbox)
627 Out.EmitBundleUnlock();
628 return true;
629 }
630
631 // If the special case above doesn't apply, but there is still a saved prefix,
632 // then the saved prefix should be bundled-locked with Inst, so that it cannot
633 // be separated by bundle padding.
634 if (State.PrefixSaved) {
635 unsigned PrefixLocal = State.PrefixSaved;
636 State.PrefixSaved = 0;
637 Out.EmitBundleLock(false);
638 EmitPrefix(STI, PrefixLocal, Out, State);
639 Out.EmitInstruction(Inst, STI);
640 Out.EmitBundleUnlock();
641 return true;
642 }
643 return false;
644 }
645
646 } // namespace llvm
647
648
649
650
651 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
652 //
653 // This is an exact copy of getX86SubSuperRegister from X86RegisterInfo.h
654 // We cannot use the original because it is part of libLLVMX86CodeGen,
655 // which cannot be a dependency of this module (libLLVMX86Desc).
656 //
657 // However, in all likelyhood, the real getX86SubSuperRegister will
658 // eventually be moved to MCTargetDesc, and then this copy can be
659 // removed.
660
661 namespace {
662 unsigned getX86SubSuperRegister_(unsigned Reg, EVT VT, bool High) {
663 switch (VT.getSimpleVT().SimpleTy) {
664 default: return Reg;
665 case MVT::i8:
666 if (High) {
667 switch (Reg) {
668 default: return 0;
669 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
670 return X86::AH;
671 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
672 return X86::DH;
673 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
674 return X86::CH;
675 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
676 return X86::BH;
677 }
678 } else {
679 switch (Reg) {
680 default: return 0;
681 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
682 return X86::AL;
683 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
684 return X86::DL;
685 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
686 return X86::CL;
687 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
688 return X86::BL;
689 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
690 return X86::SIL;
691 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
692 return X86::DIL;
693 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
694 return X86::BPL;
695 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
696 return X86::SPL;
697 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
698 return X86::R8B;
699 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
700 return X86::R9B;
701 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
702 return X86::R10B;
703 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
704 return X86::R11B;
705 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
706 return X86::R12B;
707 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
708 return X86::R13B;
709 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
710 return X86::R14B;
711 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
712 return X86::R15B;
713 }
714 }
715 case MVT::i16:
716 switch (Reg) {
717 default: return Reg;
718 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
719 return X86::AX;
720 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
721 return X86::DX;
722 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
723 return X86::CX;
724 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
725 return X86::BX;
726 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
727 return X86::SI;
728 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
729 return X86::DI;
730 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
731 return X86::BP;
732 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
733 return X86::SP;
734 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
735 return X86::R8W;
736 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
737 return X86::R9W;
738 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
739 return X86::R10W;
740 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
741 return X86::R11W;
742 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
743 return X86::R12W;
744 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
745 return X86::R13W;
746 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
747 return X86::R14W;
748 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
749 return X86::R15W;
750 }
751 case MVT::i32:
752 switch (Reg) {
753 default: return Reg;
754 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
755 return X86::EAX;
756 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
757 return X86::EDX;
758 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
759 return X86::ECX;
760 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
761 return X86::EBX;
762 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
763 return X86::ESI;
764 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
765 return X86::EDI;
766 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
767 return X86::EBP;
768 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
769 return X86::ESP;
770 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
771 return X86::R8D;
772 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
773 return X86::R9D;
774 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
775 return X86::R10D;
776 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
777 return X86::R11D;
778 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
779 return X86::R12D;
780 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
781 return X86::R13D;
782 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
783 return X86::R14D;
784 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
785 return X86::R15D;
786 }
787 case MVT::i64:
788 switch (Reg) {
789 default: return Reg;
790 case X86::AH: case X86::AL: case X86::AX: case X86::EAX: case X86::RAX:
791 return X86::RAX;
792 case X86::DH: case X86::DL: case X86::DX: case X86::EDX: case X86::RDX:
793 return X86::RDX;
794 case X86::CH: case X86::CL: case X86::CX: case X86::ECX: case X86::RCX:
795 return X86::RCX;
796 case X86::BH: case X86::BL: case X86::BX: case X86::EBX: case X86::RBX:
797 return X86::RBX;
798 case X86::SIL: case X86::SI: case X86::ESI: case X86::RSI:
799 return X86::RSI;
800 case X86::DIL: case X86::DI: case X86::EDI: case X86::RDI:
801 return X86::RDI;
802 case X86::BPL: case X86::BP: case X86::EBP: case X86::RBP:
803 return X86::RBP;
804 case X86::SPL: case X86::SP: case X86::ESP: case X86::RSP:
805 return X86::RSP;
806 case X86::R8B: case X86::R8W: case X86::R8D: case X86::R8:
807 return X86::R8;
808 case X86::R9B: case X86::R9W: case X86::R9D: case X86::R9:
809 return X86::R9;
810 case X86::R10B: case X86::R10W: case X86::R10D: case X86::R10:
811 return X86::R10;
812 case X86::R11B: case X86::R11W: case X86::R11D: case X86::R11:
813 return X86::R11;
814 case X86::R12B: case X86::R12W: case X86::R12D: case X86::R12:
815 return X86::R12;
816 case X86::R13B: case X86::R13W: case X86::R13D: case X86::R13:
817 return X86::R13;
818 case X86::R14B: case X86::R14W: case X86::R14D: case X86::R14:
819 return X86::R14;
820 case X86::R15B: case X86::R15W: case X86::R15D: case X86::R15:
821 return X86::R15;
822 }
823 }
824
825 return Reg;
826 }
827
828 // This is a copy of DemoteRegTo32 from X86NaClRewritePass.cpp.
829 // We cannot use the original because it uses part of libLLVMX86CodeGen,
830 // which cannot be a dependency of this module (libLLVMX86Desc).
831 // Note that this function calls getX86SubSuperRegister_, which is
832 // also a copied function for the same reason.
833
834 unsigned DemoteRegTo32_(unsigned RegIn) {
835 if (RegIn == 0)
836 return 0;
837 unsigned RegOut = getX86SubSuperRegister_(RegIn, MVT::i32, false);
838 assert(RegOut != 0);
839 return RegOut;
840 }
841 } //namespace
842 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
OLDNEW
« no previous file with comments | « lib/Target/X86/MCTargetDesc/X86MCNaCl.h ('k') | lib/Target/X86/X86.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698