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

Side by Side Diff: lib/Target/ARM/ARMNaClRewritePass.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/ARM/ARMNaClRewritePass.h ('k') | lib/Target/ARM/ARMSelectionDAGInfo.cpp » ('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 //===-- ARMNaClRewritePass.cpp - Native Client Rewrite Pass ------*- 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 // Native Client Rewrite Pass
11 // This final pass inserts the sandboxing instructions needed to run inside
12 // the Native Client sandbox. Native Client requires certain software fault
13 // isolation (SFI) constructions to be put in place, to prevent escape from
14 // the sandbox. Native Client refuses to execute binaries without the correct
15 // SFI sequences.
16 //
17 // Potentially dangerous operations which are protected include:
18 // * Stores
19 // * Branches
20 // * Changes to SP
21 //
22 //===----------------------------------------------------------------------===//
23
24 #define DEBUG_TYPE "arm-sfi"
25 #include "ARM.h"
26 #include "ARMBaseInstrInfo.h"
27 #include "ARMNaClRewritePass.h"
28 #include "llvm/CodeGen/MachineFunctionPass.h"
29 #include "llvm/CodeGen/MachineInstrBuilder.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include "llvm/Target/TargetSubtargetInfo.h"
34 #include <set>
35 #include <stdio.h>
36
37 using namespace llvm;
38
39 namespace {
40 class ARMNaClRewritePass : public MachineFunctionPass {
41 public:
42 static char ID;
43 ARMNaClRewritePass() : MachineFunctionPass(ID) {}
44
45 const ARMBaseInstrInfo *TII;
46 const TargetRegisterInfo *TRI;
47 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
48 virtual bool runOnMachineFunction(MachineFunction &Fn);
49
50 virtual const char *getPassName() const {
51 return "ARM Native Client Rewrite Pass";
52 }
53
54 private:
55
56 bool SandboxMemoryReferencesInBlock(MachineBasicBlock &MBB);
57 void SandboxMemory(MachineBasicBlock &MBB,
58 MachineBasicBlock::iterator MBBI,
59 MachineInstr &MI,
60 int AddrIdx,
61 bool IsLoad);
62
63 bool SandboxBranchesInBlock(MachineBasicBlock &MBB);
64 bool SandboxStackChangesInBlock(MachineBasicBlock &MBB);
65
66 void SandboxStackChange(MachineBasicBlock &MBB,
67 MachineBasicBlock::iterator MBBI);
68 void LightweightVerify(MachineFunction &MF);
69 };
70 char ARMNaClRewritePass::ID = 0;
71 }
72
73 static bool IsReturn(const MachineInstr &MI) {
74 return (MI.getOpcode() == ARM::BX_RET);
75 }
76
77 static bool IsIndirectJump(const MachineInstr &MI) {
78 switch (MI.getOpcode()) {
79 default: return false;
80 case ARM::BX:
81 case ARM::TAILJMPr:
82 return true;
83 }
84 }
85
86 static bool IsIndirectCall(const MachineInstr &MI) {
87 return MI.getOpcode() == ARM::BLX;
88 }
89
90 static bool IsDirectCall(const MachineInstr &MI) {
91 switch (MI.getOpcode()) {
92 default: return false;
93 case ARM::BL:
94 case ARM::BL_pred:
95 case ARM::TPsoft:
96 return true;
97 }
98 }
99
100 static void DumpInstructionVerbose(const MachineInstr &MI) {
101 DEBUG({
102 dbgs() << MI;
103 dbgs() << MI.getNumOperands() << " operands:" << "\n";
104 for (unsigned i = 0; i < MI.getNumOperands(); ++i) {
105 const MachineOperand& op = MI.getOperand(i);
106 dbgs() << " " << i << "(" << (unsigned)op.getType() << "):" << op
107 << "\n";
108 }
109 dbgs() << "\n";
110 });
111 }
112
113 static void DumpBasicBlockVerbose(const MachineBasicBlock &MBB) {
114 DEBUG({
115 dbgs() << "\n<<<<< DUMP BASIC BLOCK START\n";
116 for (MachineBasicBlock::const_iterator
117 MBBI = MBB.begin(), MBBE = MBB.end();
118 MBBI != MBBE;
119 ++MBBI) {
120 DumpInstructionVerbose(*MBBI);
121 }
122 dbgs() << "<<<<< DUMP BASIC BLOCK END\n\n";
123 });
124 }
125
126 /**********************************************************************/
127 /* Exported functions */
128
129 namespace ARM_SFI {
130
131 bool IsStackChange(const MachineInstr &MI, const TargetRegisterInfo *TRI) {
132 return MI.modifiesRegister(ARM::SP, TRI);
133 }
134
135 bool NextInstrMasksSP(const MachineInstr &MI) {
136 MachineBasicBlock::const_iterator It = &MI;
137 const MachineBasicBlock *MBB = MI.getParent();
138
139 MachineBasicBlock::const_iterator next = ++It;
140 if (next == MBB->end()) {
141 return false;
142 }
143
144 const MachineInstr &next_instr = *next;
145 unsigned opcode = next_instr.getOpcode();
146 return (opcode == ARM::SFI_DATA_MASK) &&
147 (next_instr.getOperand(0).getReg() == ARM::SP);
148 }
149
150 bool IsSandboxedStackChange(const MachineInstr &MI) {
151 // Calls do not change the stack on ARM but they have implicit-defs, so
152 // make sure they do not get sandboxed.
153 if (MI.getDesc().isCall())
154 return true;
155
156 unsigned opcode = MI.getOpcode();
157 switch (opcode) {
158 default: break;
159
160 // Our mask instructions correctly update the stack pointer.
161 case ARM::SFI_DATA_MASK:
162 return true;
163
164 // These just bump SP by a little (and access the stack),
165 // so that is okay due to guard pages.
166 case ARM::STMIA_UPD:
167 case ARM::STMDA_UPD:
168 case ARM::STMDB_UPD:
169 case ARM::STMIB_UPD:
170
171 case ARM::VSTMDIA_UPD:
172 case ARM::VSTMDDB_UPD:
173 case ARM::VSTMSIA_UPD:
174 case ARM::VSTMSDB_UPD:
175 return true;
176
177 // Similar, unless it is a load into SP...
178 case ARM::LDMIA_UPD:
179 case ARM::LDMDA_UPD:
180 case ARM::LDMDB_UPD:
181 case ARM::LDMIB_UPD:
182
183 case ARM::VLDMDIA_UPD:
184 case ARM::VLDMDDB_UPD:
185 case ARM::VLDMSIA_UPD:
186 case ARM::VLDMSDB_UPD: {
187 bool dest_SP = false;
188 // Dest regs start at operand index 4.
189 for (unsigned i = 4; i < MI.getNumOperands(); ++i) {
190 const MachineOperand &DestReg = MI.getOperand(i);
191 dest_SP = dest_SP || (DestReg.getReg() == ARM::SP);
192 }
193 if (dest_SP) {
194 break;
195 }
196 return true;
197 }
198
199 // Some localmods *should* prevent selecting a reg offset
200 // (see SelectAddrMode2 in ARMISelDAGToDAG.cpp).
201 // Otherwise, the store is already a potential violation.
202 case ARM::STR_PRE_REG:
203 case ARM::STR_PRE_IMM:
204
205 case ARM::STRH_PRE:
206
207 case ARM::STRB_PRE_REG:
208 case ARM::STRB_PRE_IMM:
209 return true;
210
211 // Similar, unless it is a load into SP...
212 case ARM::LDRi12:
213 case ARM::LDR_PRE_REG:
214 case ARM::LDR_PRE_IMM:
215 case ARM::LDRH_PRE:
216 case ARM::LDRB_PRE_REG:
217 case ARM::LDRB_PRE_IMM:
218 case ARM::LDRSH_PRE:
219 case ARM::LDRSB_PRE: {
220 const MachineOperand &DestReg = MI.getOperand(0);
221 if (DestReg.getReg() == ARM::SP) {
222 break;
223 }
224 return true;
225 }
226
227 // Here, if SP is the base / write-back reg, we need to check if
228 // a reg is used as offset (otherwise it is not a small nudge).
229 case ARM::STR_POST_REG:
230 case ARM::STR_POST_IMM:
231 case ARM::STRH_POST:
232 case ARM::STRB_POST_REG:
233 case ARM::STRB_POST_IMM: {
234 const MachineOperand &WBReg = MI.getOperand(0);
235 const MachineOperand &OffReg = MI.getOperand(3);
236 if (WBReg.getReg() == ARM::SP && OffReg.getReg() != 0) {
237 break;
238 }
239 return true;
240 }
241
242 // Similar, but also check that DestReg is not SP.
243 case ARM::LDR_POST_REG:
244 case ARM::LDR_POST_IMM:
245 case ARM::LDRB_POST_REG:
246 case ARM::LDRB_POST_IMM:
247 case ARM::LDRH_POST:
248 case ARM::LDRSH_POST:
249 case ARM::LDRSB_POST: {
250 const MachineOperand &DestReg = MI.getOperand(0);
251 if (DestReg.getReg() == ARM::SP) {
252 break;
253 }
254 const MachineOperand &WBReg = MI.getOperand(1);
255 const MachineOperand &OffReg = MI.getOperand(3);
256 if (WBReg.getReg() == ARM::SP && OffReg.getReg() != 0) {
257 break;
258 }
259 return true;
260 }
261 }
262
263 return (NextInstrMasksSP(MI));
264 }
265
266 bool NeedSandboxStackChange(const MachineInstr &MI,
267 const TargetRegisterInfo *TRI) {
268 return (IsStackChange(MI, TRI) && !IsSandboxedStackChange(MI));
269 }
270
271 } // namespace ARM_SFI
272
273 /**********************************************************************/
274
275 void ARMNaClRewritePass::getAnalysisUsage(AnalysisUsage &AU) const {
276 // Slight (possibly unnecessary) efficiency tweak:
277 // Promise not to modify the CFG.
278 AU.setPreservesCFG();
279 MachineFunctionPass::getAnalysisUsage(AU);
280 }
281
282 /*
283 * A primitive validator to catch problems at compile time.
284 * E.g., it could be used along with bugpoint to reduce a bitcode file.
285 */
286 void ARMNaClRewritePass::LightweightVerify(MachineFunction &MF) {
287 DEBUG({
288 for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end();
289 MFI != MFE;
290 ++MFI) {
291 MachineBasicBlock &MBB = *MFI;
292 for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end();
293 MBBI != MBBE;
294 ++MBBI) {
295 MachineInstr &MI = *MBBI;
296 if (ARM_SFI::NeedSandboxStackChange(MI, TRI)) {
297 dbgs() << "LightWeightVerify for function: "
298 << MF.getFunction()->getName() << " (BAD STACK CHANGE)\n";
299 DumpInstructionVerbose(MI);
300 DumpBasicBlockVerbose(MBB);
301 }
302 }
303 }
304 });
305 }
306
307 void ARMNaClRewritePass::SandboxStackChange(MachineBasicBlock &MBB,
308 MachineBasicBlock::iterator MBBI) {
309 // (1) Ensure there is room in the bundle for a data mask instruction
310 // (nop'ing to the next bundle if needed).
311 // (2) Do a data mask on SP after the instruction that updated SP.
312 MachineInstr &MI = *MBBI;
313
314 // Use same predicate as current instruction.
315 unsigned PredReg = 0;
316 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
317
318 BuildMI(MBB, MBBI, MI.getDebugLoc(),
319 TII->get(ARM::SFI_NOP_IF_AT_BUNDLE_END));
320
321 // Get to next instr.
322 MachineBasicBlock::iterator MBBINext = (++MBBI);
323
324 BuildMI(MBB, MBBINext, MI.getDebugLoc(),
325 TII->get(ARM::SFI_DATA_MASK))
326 .addReg(ARM::SP, RegState::Define) // modify SP (as dst)
327 .addReg(ARM::SP, RegState::Kill) // start with SP (as src)
328 .addImm((int64_t) Pred) // predicate condition
329 .addReg(PredReg); // predicate source register (CPSR)
330 }
331
332 bool ARMNaClRewritePass::SandboxStackChangesInBlock(MachineBasicBlock &MBB) {
333 bool Modified = false;
334 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
335 MBBI != E;
336 ++MBBI) {
337 MachineInstr &MI = *MBBI;
338 if (ARM_SFI::NeedSandboxStackChange(MI, TRI)) {
339 SandboxStackChange(MBB, MBBI);
340 Modified |= true;
341 }
342 }
343 return Modified;
344 }
345
346 bool ARMNaClRewritePass::SandboxBranchesInBlock(MachineBasicBlock &MBB) {
347 bool Modified = false;
348
349 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
350 MBBI != E;
351 ++MBBI) {
352 MachineInstr &MI = *MBBI;
353 // Use same predicate as current instruction.
354 unsigned PredReg = 0;
355 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
356
357 if (IsReturn(MI)) {
358 BuildMI(MBB, MBBI, MI.getDebugLoc(),
359 TII->get(ARM::SFI_GUARD_RETURN))
360 .addImm((int64_t) Pred) // predicate condition
361 .addReg(PredReg); // predicate source register (CPSR)
362 Modified = true;
363 }
364
365 if (IsIndirectJump(MI)) {
366 unsigned Addr = MI.getOperand(0).getReg();
367 BuildMI(MBB, MBBI, MI.getDebugLoc(),
368 TII->get(ARM::SFI_GUARD_INDIRECT_JMP))
369 .addReg(Addr, RegState::Define) // Destination definition (as dst)
370 .addReg(Addr, RegState::Kill) // Destination read (as src)
371 .addImm((int64_t) Pred) // predicate condition
372 .addReg(PredReg); // predicate source register (CPSR)
373 Modified = true;
374 }
375
376 if (IsDirectCall(MI)) {
377 BuildMI(MBB, MBBI, MI.getDebugLoc(),
378 TII->get(ARM::SFI_GUARD_CALL))
379 .addImm((int64_t) Pred) // predicate condition
380 .addReg(PredReg); // predicate source register (CPSR)
381 Modified = true;
382 }
383
384 if (IsIndirectCall(MI)) {
385 unsigned Addr = MI.getOperand(0).getReg();
386 BuildMI(MBB, MBBI, MI.getDebugLoc(),
387 TII->get(ARM::SFI_GUARD_INDIRECT_CALL))
388 .addReg(Addr, RegState::Define) // Destination definition (as dst)
389 .addReg(Addr, RegState::Kill) // Destination read (as src)
390 .addImm((int64_t) Pred) // predicate condition
391 .addReg(PredReg); // predicate source register (CPSR)
392 Modified = true;
393 }
394 }
395
396 return Modified;
397 }
398
399 static bool IsDangerousLoad(const MachineInstr &MI, int *AddrIdx) {
400 unsigned Opcode = MI.getOpcode();
401 switch (Opcode) {
402 default: return false;
403
404 // Instructions with base address register in position 0...
405 case ARM::LDMIA:
406 case ARM::LDMDA:
407 case ARM::LDMDB:
408 case ARM::LDMIB:
409
410 case ARM::VLDMDIA:
411 case ARM::VLDMSIA:
412
413 case ARM::PLDi12:
414 case ARM::PLDWi12:
415 case ARM::PLIi12:
416 *AddrIdx = 0;
417 break;
418 // Instructions with base address register in position 1...
419 case ARM::LDMIA_UPD: // same reg at position 0 and position 1
420 case ARM::LDMDA_UPD:
421 case ARM::LDMDB_UPD:
422 case ARM::LDMIB_UPD:
423
424 case ARM::LDRSB:
425 case ARM::LDRH:
426 case ARM::LDRSH:
427
428 case ARM::LDRi12:
429 case ARM::LDRrs:
430 case ARM::LDRBi12:
431 case ARM::LDRBrs:
432 case ARM::VLDMDIA_UPD:
433 case ARM::VLDMDDB_UPD:
434 case ARM::VLDMSIA_UPD:
435 case ARM::VLDMSDB_UPD:
436 case ARM::VLDRS:
437 case ARM::VLDRD:
438
439 case ARM::LDREX:
440 case ARM::LDREXB:
441 case ARM::LDREXH:
442 case ARM::LDREXD:
443 *AddrIdx = 1;
444 break;
445
446 // Instructions with base address register in position 2...
447 case ARM::LDR_PRE_REG:
448 case ARM::LDR_PRE_IMM:
449 case ARM::LDR_POST_REG:
450 case ARM::LDR_POST_IMM:
451
452 case ARM::LDRB_PRE_REG:
453 case ARM::LDRB_PRE_IMM:
454 case ARM::LDRB_POST_REG:
455 case ARM::LDRB_POST_IMM:
456 case ARM::LDRSB_PRE:
457 case ARM::LDRSB_POST:
458
459 case ARM::LDRH_PRE:
460 case ARM::LDRH_POST:
461 case ARM::LDRSH_PRE:
462 case ARM::LDRSH_POST:
463
464 case ARM::LDRD:
465 *AddrIdx = 2;
466 break;
467
468 //
469 // NEON loads
470 //
471
472 // VLD1
473 case ARM::VLD1d8:
474 case ARM::VLD1d16:
475 case ARM::VLD1d32:
476 case ARM::VLD1d64:
477 case ARM::VLD1q8:
478 case ARM::VLD1q16:
479 case ARM::VLD1q32:
480 case ARM::VLD1q64:
481 *AddrIdx = 1;
482 break;
483
484 case ARM::VLD1d8wb_fixed:
485 case ARM::VLD1d16wb_fixed:
486 case ARM::VLD1d32wb_fixed:
487 case ARM::VLD1d64wb_fixed:
488 case ARM::VLD1q8wb_fixed:
489 case ARM::VLD1q16wb_fixed:
490 case ARM::VLD1q32wb_fixed:
491 case ARM::VLD1q64wb_fixed:
492 case ARM::VLD1d8wb_register:
493 case ARM::VLD1d16wb_register:
494 case ARM::VLD1d32wb_register:
495 case ARM::VLD1d64wb_register:
496 case ARM::VLD1q8wb_register:
497 case ARM::VLD1q16wb_register:
498 case ARM::VLD1q32wb_register:
499 case ARM::VLD1q64wb_register:
500 *AddrIdx = 2;
501 break;
502
503 // VLD1T
504 case ARM::VLD1d8T:
505 case ARM::VLD1d16T:
506 case ARM::VLD1d32T:
507 case ARM::VLD1d64T:
508 *AddrIdx = 1;
509 break;
510
511 case ARM::VLD1d8Twb_fixed:
512 case ARM::VLD1d16Twb_fixed:
513 case ARM::VLD1d32Twb_fixed:
514 case ARM::VLD1d64Twb_fixed:
515 case ARM::VLD1d8Twb_register:
516 case ARM::VLD1d16Twb_register:
517 case ARM::VLD1d32Twb_register:
518 case ARM::VLD1d64Twb_register:
519 *AddrIdx = 2;
520 break;
521
522 // VLD1Q
523 case ARM::VLD1d8Q:
524 case ARM::VLD1d16Q:
525 case ARM::VLD1d32Q:
526 case ARM::VLD1d64Q:
527 *AddrIdx = 1;
528 break;
529
530 case ARM::VLD1d8Qwb_fixed:
531 case ARM::VLD1d16Qwb_fixed:
532 case ARM::VLD1d32Qwb_fixed:
533 case ARM::VLD1d64Qwb_fixed:
534 case ARM::VLD1d8Qwb_register:
535 case ARM::VLD1d16Qwb_register:
536 case ARM::VLD1d32Qwb_register:
537 case ARM::VLD1d64Qwb_register:
538 *AddrIdx = 2;
539 break;
540
541 // VLD1LN
542 case ARM::VLD1LNd8:
543 case ARM::VLD1LNd16:
544 case ARM::VLD1LNd32:
545 case ARM::VLD1LNd8_UPD:
546 case ARM::VLD1LNd16_UPD:
547 case ARM::VLD1LNd32_UPD:
548
549 // VLD1DUP
550 case ARM::VLD1DUPd8:
551 case ARM::VLD1DUPd16:
552 case ARM::VLD1DUPd32:
553 case ARM::VLD1DUPq8:
554 case ARM::VLD1DUPq16:
555 case ARM::VLD1DUPq32:
556 case ARM::VLD1DUPd8wb_fixed:
557 case ARM::VLD1DUPd16wb_fixed:
558 case ARM::VLD1DUPd32wb_fixed:
559 case ARM::VLD1DUPq8wb_fixed:
560 case ARM::VLD1DUPq16wb_fixed:
561 case ARM::VLD1DUPq32wb_fixed:
562 case ARM::VLD1DUPd8wb_register:
563 case ARM::VLD1DUPd16wb_register:
564 case ARM::VLD1DUPd32wb_register:
565 case ARM::VLD1DUPq8wb_register:
566 case ARM::VLD1DUPq16wb_register:
567 case ARM::VLD1DUPq32wb_register:
568
569 // VLD2
570 case ARM::VLD2d8:
571 case ARM::VLD2d16:
572 case ARM::VLD2d32:
573 case ARM::VLD2b8:
574 case ARM::VLD2b16:
575 case ARM::VLD2b32:
576 case ARM::VLD2q8:
577 case ARM::VLD2q16:
578 case ARM::VLD2q32:
579 *AddrIdx = 1;
580 break;
581
582 case ARM::VLD2d8wb_fixed:
583 case ARM::VLD2d16wb_fixed:
584 case ARM::VLD2d32wb_fixed:
585 case ARM::VLD2b8wb_fixed:
586 case ARM::VLD2b16wb_fixed:
587 case ARM::VLD2b32wb_fixed:
588 case ARM::VLD2q8wb_fixed:
589 case ARM::VLD2q16wb_fixed:
590 case ARM::VLD2q32wb_fixed:
591 case ARM::VLD2d8wb_register:
592 case ARM::VLD2d16wb_register:
593 case ARM::VLD2d32wb_register:
594 case ARM::VLD2b8wb_register:
595 case ARM::VLD2b16wb_register:
596 case ARM::VLD2b32wb_register:
597 case ARM::VLD2q8wb_register:
598 case ARM::VLD2q16wb_register:
599 case ARM::VLD2q32wb_register:
600 *AddrIdx = 2;
601 break;
602
603 // VLD2LN
604 case ARM::VLD2LNd8:
605 case ARM::VLD2LNd16:
606 case ARM::VLD2LNd32:
607 case ARM::VLD2LNq16:
608 case ARM::VLD2LNq32:
609 *AddrIdx = 2;
610 break;
611
612 case ARM::VLD2LNd8_UPD:
613 case ARM::VLD2LNd16_UPD:
614 case ARM::VLD2LNd32_UPD:
615 case ARM::VLD2LNq16_UPD:
616 case ARM::VLD2LNq32_UPD:
617 *AddrIdx = 3;
618 break;
619
620 // VLD2DUP
621 case ARM::VLD2DUPd8:
622 case ARM::VLD2DUPd16:
623 case ARM::VLD2DUPd32:
624 case ARM::VLD2DUPd8x2:
625 case ARM::VLD2DUPd16x2:
626 case ARM::VLD2DUPd32x2:
627 *AddrIdx = 1;
628 break;
629
630 case ARM::VLD2DUPd8wb_fixed:
631 case ARM::VLD2DUPd16wb_fixed:
632 case ARM::VLD2DUPd32wb_fixed:
633 case ARM::VLD2DUPd8wb_register:
634 case ARM::VLD2DUPd16wb_register:
635 case ARM::VLD2DUPd32wb_register:
636 case ARM::VLD2DUPd8x2wb_fixed:
637 case ARM::VLD2DUPd16x2wb_fixed:
638 case ARM::VLD2DUPd32x2wb_fixed:
639 case ARM::VLD2DUPd8x2wb_register:
640 case ARM::VLD2DUPd16x2wb_register:
641 case ARM::VLD2DUPd32x2wb_register:
642 *AddrIdx = 2;
643 break;
644
645 // VLD3
646 case ARM::VLD3d8:
647 case ARM::VLD3d16:
648 case ARM::VLD3d32:
649 case ARM::VLD3q8:
650 case ARM::VLD3q16:
651 case ARM::VLD3q32:
652 case ARM::VLD3d8_UPD:
653 case ARM::VLD3d16_UPD:
654 case ARM::VLD3d32_UPD:
655 case ARM::VLD3q8_UPD:
656 case ARM::VLD3q16_UPD:
657 case ARM::VLD3q32_UPD:
658
659 // VLD3LN
660 case ARM::VLD3LNd8:
661 case ARM::VLD3LNd16:
662 case ARM::VLD3LNd32:
663 case ARM::VLD3LNq16:
664 case ARM::VLD3LNq32:
665 *AddrIdx = 3;
666 break;
667
668 case ARM::VLD3LNd8_UPD:
669 case ARM::VLD3LNd16_UPD:
670 case ARM::VLD3LNd32_UPD:
671 case ARM::VLD3LNq16_UPD:
672 case ARM::VLD3LNq32_UPD:
673 *AddrIdx = 4;
674 break;
675
676 // VLD3DUP
677 case ARM::VLD3DUPd8:
678 case ARM::VLD3DUPd16:
679 case ARM::VLD3DUPd32:
680 case ARM::VLD3DUPq8:
681 case ARM::VLD3DUPq16:
682 case ARM::VLD3DUPq32:
683 *AddrIdx = 3;
684 break;
685
686 case ARM::VLD3DUPd8_UPD:
687 case ARM::VLD3DUPd16_UPD:
688 case ARM::VLD3DUPd32_UPD:
689 case ARM::VLD3DUPq8_UPD:
690 case ARM::VLD3DUPq16_UPD:
691 case ARM::VLD3DUPq32_UPD:
692 *AddrIdx = 4;
693 break;
694
695 // VLD4
696 case ARM::VLD4d8:
697 case ARM::VLD4d16:
698 case ARM::VLD4d32:
699 case ARM::VLD4q8:
700 case ARM::VLD4q16:
701 case ARM::VLD4q32:
702 *AddrIdx = 4;
703 break;
704
705 case ARM::VLD4d8_UPD:
706 case ARM::VLD4d16_UPD:
707 case ARM::VLD4d32_UPD:
708 case ARM::VLD4q8_UPD:
709 case ARM::VLD4q16_UPD:
710 case ARM::VLD4q32_UPD:
711 *AddrIdx = 5;
712 break;
713
714 // VLD4LN
715 case ARM::VLD4LNd8:
716 case ARM::VLD4LNd16:
717 case ARM::VLD4LNd32:
718 case ARM::VLD4LNq16:
719 case ARM::VLD4LNq32:
720 *AddrIdx = 4;
721 break;
722
723 case ARM::VLD4LNd8_UPD:
724 case ARM::VLD4LNd16_UPD:
725 case ARM::VLD4LNd32_UPD:
726 case ARM::VLD4LNq16_UPD:
727 case ARM::VLD4LNq32_UPD:
728 *AddrIdx = 5;
729 break;
730
731 case ARM::VLD4DUPd8:
732 case ARM::VLD4DUPd16:
733 case ARM::VLD4DUPd32:
734 case ARM::VLD4DUPq16:
735 case ARM::VLD4DUPq32:
736 *AddrIdx = 4;
737 break;
738
739 case ARM::VLD4DUPd8_UPD:
740 case ARM::VLD4DUPd16_UPD:
741 case ARM::VLD4DUPd32_UPD:
742 case ARM::VLD4DUPq16_UPD:
743 case ARM::VLD4DUPq32_UPD:
744 *AddrIdx = 5;
745 break;
746 }
747
748 if (MI.getOperand(*AddrIdx).getReg() == ARM::SP) {
749 // The contents of SP do not require masking.
750 return false;
751 }
752
753 return true;
754 }
755
756 /*
757 * Sandboxes a memory reference instruction by inserting an appropriate mask
758 * or check operation before it.
759 */
760 void ARMNaClRewritePass::SandboxMemory(MachineBasicBlock &MBB,
761 MachineBasicBlock::iterator MBBI,
762 MachineInstr &MI,
763 int AddrIdx,
764 bool IsLoad) {
765 unsigned Addr = MI.getOperand(AddrIdx).getReg();
766
767 if (Addr == ARM::R9) {
768 // R9-relative loads are no longer sandboxed.
769 assert(IsLoad && "There should be no r9-relative stores");
770 } else {
771 unsigned Opcode;
772 if (IsLoad && (MI.getOperand(0).getReg() == ARM::SP)) {
773 Opcode = ARM::SFI_GUARD_SP_LOAD;
774 } else {
775 Opcode = ARM::SFI_GUARD_LOADSTORE;
776 }
777 // Use same predicate as current instruction.
778 unsigned PredReg = 0;
779 ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg);
780 // Use the older BIC sandbox, which is universal, but incurs a stall.
781 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode))
782 .addReg(Addr, RegState::Define) // Address definition (as dst).
783 .addReg(Addr, RegState::Kill) // Address read (as src).
784 .addImm((int64_t) Pred) // predicate condition
785 .addReg(PredReg); // predicate source register (CPSR)
786
787 /*
788 * This pseudo-instruction is intended to generate something resembling the
789 * following, but with alignment enforced.
790 * TODO(cbiffle): move alignment into this function, use the code below.
791 *
792 * // bic<cc> Addr, Addr, #0xC0000000
793 * BuildMI(MBB, MBBI, MI.getDebugLoc(),
794 * TII->get(ARM::BICri))
795 * .addReg(Addr) // rD
796 * .addReg(Addr) // rN
797 * .addImm(0xC0000000) // imm
798 * .addImm((int64_t) Pred) // predicate condition
799 * .addReg(PredReg) // predicate source register (CPSR)
800 * .addReg(0); // flag output register (0 == no flags)
801 */
802 }
803 }
804
805 static bool IsDangerousStore(const MachineInstr &MI, int *AddrIdx) {
806 unsigned Opcode = MI.getOpcode();
807 switch (Opcode) {
808 default: return false;
809
810 // Instructions with base address register in position 0...
811 case ARM::STMIA:
812 case ARM::STMDA:
813 case ARM::STMDB:
814 case ARM::STMIB:
815
816 case ARM::VSTMDIA:
817 case ARM::VSTMSIA:
818 *AddrIdx = 0;
819 break;
820
821 // Instructions with base address register in position 1...
822 case ARM::STMIA_UPD: // same reg at position 0 and position 1
823 case ARM::STMDA_UPD:
824 case ARM::STMDB_UPD:
825 case ARM::STMIB_UPD:
826
827 case ARM::STRH:
828 case ARM::STRi12:
829 case ARM::STRrs:
830 case ARM::STRBi12:
831 case ARM::STRBrs:
832 case ARM::VSTMDIA_UPD:
833 case ARM::VSTMDDB_UPD:
834 case ARM::VSTMSIA_UPD:
835 case ARM::VSTMSDB_UPD:
836 case ARM::VSTRS:
837 case ARM::VSTRD:
838 *AddrIdx = 1;
839 break;
840
841 //
842 // NEON stores
843 //
844
845 // VST1
846 case ARM::VST1d8:
847 case ARM::VST1d16:
848 case ARM::VST1d32:
849 case ARM::VST1d64:
850 case ARM::VST1q8:
851 case ARM::VST1q16:
852 case ARM::VST1q32:
853 case ARM::VST1q64:
854 *AddrIdx = 0;
855 break;
856
857 case ARM::VST1d8wb_fixed:
858 case ARM::VST1d16wb_fixed:
859 case ARM::VST1d32wb_fixed:
860 case ARM::VST1d64wb_fixed:
861 case ARM::VST1q8wb_fixed:
862 case ARM::VST1q16wb_fixed:
863 case ARM::VST1q32wb_fixed:
864 case ARM::VST1q64wb_fixed:
865 case ARM::VST1d8wb_register:
866 case ARM::VST1d16wb_register:
867 case ARM::VST1d32wb_register:
868 case ARM::VST1d64wb_register:
869 case ARM::VST1q8wb_register:
870 case ARM::VST1q16wb_register:
871 case ARM::VST1q32wb_register:
872 case ARM::VST1q64wb_register:
873 *AddrIdx = 1;
874 break;
875
876 // VST1LN
877 case ARM::VST1LNd8:
878 case ARM::VST1LNd16:
879 case ARM::VST1LNd32:
880 *AddrIdx = 0;
881 break;
882
883 case ARM::VST1LNd8_UPD:
884 case ARM::VST1LNd16_UPD:
885 case ARM::VST1LNd32_UPD:
886 *AddrIdx = 1;
887 break;
888
889 // VST2
890 case ARM::VST2d8:
891 case ARM::VST2d16:
892 case ARM::VST2d32:
893 case ARM::VST2q8:
894 case ARM::VST2q16:
895 case ARM::VST2q32:
896 *AddrIdx = 0;
897 break;
898
899 case ARM::VST2d8wb_fixed:
900 case ARM::VST2d16wb_fixed:
901 case ARM::VST2d32wb_fixed:
902 case ARM::VST2q8wb_fixed:
903 case ARM::VST2q16wb_fixed:
904 case ARM::VST2q32wb_fixed:
905 case ARM::VST2d8wb_register:
906 case ARM::VST2d16wb_register:
907 case ARM::VST2d32wb_register:
908 case ARM::VST2q8wb_register:
909 case ARM::VST2q16wb_register:
910 case ARM::VST2q32wb_register:
911 *AddrIdx = 1;
912 break;
913
914 // VST2LN
915 case ARM::VST2LNd8:
916 case ARM::VST2LNd16:
917 case ARM::VST2LNq16:
918 case ARM::VST2LNd32:
919 case ARM::VST2LNq32:
920 *AddrIdx = 0;
921 break;
922
923 case ARM::VST2LNd8_UPD:
924 case ARM::VST2LNd16_UPD:
925 case ARM::VST2LNq16_UPD:
926 case ARM::VST2LNd32_UPD:
927 case ARM::VST2LNq32_UPD:
928 *AddrIdx = 1;
929 break;
930
931 // VST3
932 case ARM::VST3d8:
933 case ARM::VST3d16:
934 case ARM::VST3d32:
935 case ARM::VST3q8:
936 case ARM::VST3q16:
937 case ARM::VST3q32:
938 *AddrIdx = 0;
939 break;
940
941 case ARM::VST3d8_UPD:
942 case ARM::VST3d16_UPD:
943 case ARM::VST3d32_UPD:
944 case ARM::VST3q8_UPD:
945 case ARM::VST3q16_UPD:
946 case ARM::VST3q32_UPD:
947 *AddrIdx = 1;
948 break;
949
950 // VST3LN
951 case ARM::VST3LNd8:
952 case ARM::VST3LNd16:
953 case ARM::VST3LNq16:
954 case ARM::VST3LNd32:
955 case ARM::VST3LNq32:
956 *AddrIdx = 0;
957 break;
958
959 case ARM::VST3LNd8_UPD:
960 case ARM::VST3LNd16_UPD:
961 case ARM::VST3LNq16_UPD:
962 case ARM::VST3LNd32_UPD:
963 case ARM::VST3LNq32_UPD:
964 *AddrIdx = 1;
965 break;
966
967 // VST4
968 case ARM::VST4d8:
969 case ARM::VST4d16:
970 case ARM::VST4d32:
971 case ARM::VST4q8:
972 case ARM::VST4q16:
973 case ARM::VST4q32:
974 *AddrIdx = 0;
975 break;
976
977 case ARM::VST4d8_UPD:
978 case ARM::VST4d16_UPD:
979 case ARM::VST4d32_UPD:
980 case ARM::VST4q8_UPD:
981 case ARM::VST4q16_UPD:
982 case ARM::VST4q32_UPD:
983 *AddrIdx = 1;
984 break;
985
986 // VST4LN
987 case ARM::VST4LNd8:
988 case ARM::VST4LNd16:
989 case ARM::VST4LNq16:
990 case ARM::VST4LNd32:
991 case ARM::VST4LNq32:
992 *AddrIdx = 0;
993 break;
994
995 case ARM::VST4LNd8_UPD:
996 case ARM::VST4LNd16_UPD:
997 case ARM::VST4LNq16_UPD:
998 case ARM::VST4LNd32_UPD:
999 case ARM::VST4LNq32_UPD:
1000 *AddrIdx = 1;
1001 break;
1002
1003 // Instructions with base address register in position 2...
1004 case ARM::STR_PRE_REG:
1005 case ARM::STR_PRE_IMM:
1006 case ARM::STR_POST_REG:
1007 case ARM::STR_POST_IMM:
1008
1009 case ARM::STRB_PRE_REG:
1010 case ARM::STRB_PRE_IMM:
1011 case ARM::STRB_POST_REG:
1012 case ARM::STRB_POST_IMM:
1013
1014 case ARM::STRH_PRE:
1015 case ARM::STRH_POST:
1016
1017
1018 case ARM::STRD:
1019 case ARM::STREX:
1020 case ARM::STREXB:
1021 case ARM::STREXH:
1022 case ARM::STREXD:
1023 *AddrIdx = 2;
1024 break;
1025 }
1026
1027 if (MI.getOperand(*AddrIdx).getReg() == ARM::SP) {
1028 // The contents of SP do not require masking.
1029 return false;
1030 }
1031
1032 return true;
1033 }
1034
1035 bool ARMNaClRewritePass::SandboxMemoryReferencesInBlock(
1036 MachineBasicBlock &MBB) {
1037 bool Modified = false;
1038 for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1039 MBBI != E;
1040 ++MBBI) {
1041 MachineInstr &MI = *MBBI;
1042 int AddrIdx;
1043
1044 if (IsDangerousLoad(MI, &AddrIdx)) {
1045 SandboxMemory(MBB, MBBI, MI, AddrIdx, true);
1046 Modified = true;
1047 }
1048 if (IsDangerousStore(MI, &AddrIdx)) {
1049 SandboxMemory(MBB, MBBI, MI, AddrIdx, false);
1050 Modified = true;
1051 }
1052 }
1053 return Modified;
1054 }
1055
1056 /**********************************************************************/
1057
1058 bool ARMNaClRewritePass::runOnMachineFunction(MachineFunction &MF) {
1059 TII = static_cast<const ARMBaseInstrInfo*>(MF.getSubtarget().getInstrInfo());
1060 TRI = MF.getSubtarget().getRegisterInfo();
1061
1062 bool Modified = false;
1063 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end();
1064 MFI != E;
1065 ++MFI) {
1066 MachineBasicBlock &MBB = *MFI;
1067
1068 if (MBB.hasAddressTaken()) {
1069 //FIXME: use symbolic constant or get this value from some configuration
1070 MBB.setAlignment(4);
1071 Modified = true;
1072 }
1073
1074 Modified |= SandboxMemoryReferencesInBlock(MBB);
1075 Modified |= SandboxBranchesInBlock(MBB);
1076 Modified |= SandboxStackChangesInBlock(MBB);
1077 }
1078 DEBUG(LightweightVerify(MF));
1079 return Modified;
1080 }
1081
1082 /// createARMNaClRewritePass - returns an instance of the NaClRewritePass.
1083 FunctionPass *llvm::createARMNaClRewritePass() {
1084 return new ARMNaClRewritePass();
1085 }
OLDNEW
« no previous file with comments | « lib/Target/ARM/ARMNaClRewritePass.h ('k') | lib/Target/ARM/ARMSelectionDAGInfo.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698