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

Side by Side Diff: lib/Target/ARM/MCTargetDesc/ARMMCNaCl.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/MCTargetDesc/ARMMCNaCl.h ('k') | lib/Target/ARM/MCTargetDesc/CMakeLists.txt » ('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 //=== ARMMCNaCl.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 "arm-mc-nacl"
12
13 #include "MCTargetDesc/ARMBaseInfo.h"
14 #include "MCTargetDesc/ARMMCExpr.h"
15 #include "MCTargetDesc/ARMMCNaCl.h"
16 #include "MCTargetDesc/ARMMCTargetDesc.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCStreamer.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Support/Debug.h"
21
22 using namespace llvm;
23
24 /// Two helper functions for emitting the actual guard instructions
25
26 static void EmitBICMask(const MCSubtargetInfo &STI, MCStreamer &Out,
27 unsigned Addr, int64_t Pred, unsigned Mask) {
28 // bic\Pred \Addr, \Addr, #Mask
29 MCInst BICInst;
30 BICInst.setOpcode(ARM::BICri);
31 BICInst.addOperand(MCOperand::CreateReg(Addr)); // rD
32 BICInst.addOperand(MCOperand::CreateReg(Addr)); // rS
33 BICInst.addOperand(MCOperand::CreateImm(Mask)); // imm
34 BICInst.addOperand(MCOperand::CreateImm(Pred)); // predicate
35 BICInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); // CPSR
36 BICInst.addOperand(MCOperand::CreateReg(0)); // flag out
37 Out.EmitInstruction(BICInst, STI);
38 }
39
40 static void EmitTST(const MCSubtargetInfo &STI, MCStreamer &Out, unsigned Reg) {
41 // tst \reg, #\MASK typically 0xc0000000
42 const unsigned Mask = 0xC0000000;
43 MCInst TSTInst;
44 TSTInst.setOpcode(ARM::TSTri);
45 TSTInst.addOperand(MCOperand::CreateReg(Reg)); // rS
46 TSTInst.addOperand(MCOperand::CreateImm(Mask)); // imm
47 TSTInst.addOperand(MCOperand::CreateImm((int64_t)ARMCC::AL)); // Always
48 TSTInst.addOperand(MCOperand::CreateImm(0)); // flag out
49 Out.EmitInstruction(TSTInst, STI);
50 }
51
52
53 // This is ONLY used for sandboxing stack changes.
54 // The reason why SFI_NOP_IF_AT_BUNDLE_END gets handled here is that
55 // it must ensure that the two instructions are in the same bundle.
56 // It just so happens that the SFI_NOP_IF_AT_BUNDLE_END is always
57 // emitted in conjunction with a SFI_DATA_MASK
58 //
59 static void EmitDataMask(const MCSubtargetInfo &STI, int I, MCInst Saved[],
60 MCStreamer &Out) {
61 assert(I == 3 && (ARM::SFI_NOP_IF_AT_BUNDLE_END == Saved[0].getOpcode()) &&
62 (ARM::SFI_DATA_MASK == Saved[2].getOpcode()) &&
63 "Unexpected SFI Pseudo while lowering");
64
65 unsigned Addr = Saved[2].getOperand(0).getReg();
66 int64_t Pred = Saved[2].getOperand(2).getImm();
67 assert((ARM::SP == Addr) && "Unexpected register at stack guard");
68
69 Out.EmitBundleLock(false);
70 Out.EmitInstruction(Saved[1], STI);
71 EmitBICMask(STI, Out, Addr, Pred, 0xC0000000);
72 Out.EmitBundleUnlock();
73 }
74
75 static void EmitDirectGuardCall(const MCSubtargetInfo &STI, int I,
76 MCInst Saved[], MCStreamer &Out) {
77 // sfi_call_preamble cond=
78 // sfi_nops_to_force_slot3
79 assert(I == 2 && (ARM::SFI_GUARD_CALL == Saved[0].getOpcode()) &&
80 "Unexpected SFI Pseudo while lowering SFI_GUARD_CALL");
81 Out.EmitBundleLock(true);
82 Out.EmitInstruction(Saved[1], STI);
83 Out.EmitBundleUnlock();
84 }
85
86 static void EmitIndirectGuardCall(const MCSubtargetInfo &STI, int I,
87 MCInst Saved[], MCStreamer &Out) {
88 // sfi_indirect_call_preamble link cond=
89 // sfi_nops_to_force_slot2
90 // sfi_code_mask \link \cond
91 assert(I == 2 && (ARM::SFI_GUARD_INDIRECT_CALL == Saved[0].getOpcode()) &&
92 "Unexpected SFI Pseudo while lowering SFI_GUARD_CALL");
93 unsigned Reg = Saved[0].getOperand(0).getReg();
94 int64_t Pred = Saved[0].getOperand(2).getImm();
95 Out.EmitBundleLock(true);
96 EmitBICMask(STI, Out, Reg, Pred, 0xC000000F);
97 Out.EmitInstruction(Saved[1], STI);
98 Out.EmitBundleUnlock();
99 }
100
101 static void EmitIndirectGuardJmp(const MCSubtargetInfo &STI, int I,
102 MCInst Saved[], MCStreamer &Out) {
103 // sfi_indirect_jump_preamble link cond=
104 // sfi_nop_if_at_bundle_end
105 // sfi_code_mask \link \cond
106 assert(I == 2 && (ARM::SFI_GUARD_INDIRECT_JMP == Saved[0].getOpcode()) &&
107 "Unexpected SFI Pseudo while lowering SFI_GUARD_CALL");
108 unsigned Reg = Saved[0].getOperand(0).getReg();
109 int64_t Pred = Saved[0].getOperand(2).getImm();
110
111 Out.EmitBundleLock(false);
112 EmitBICMask(STI, Out, Reg, Pred, 0xC000000F);
113 Out.EmitInstruction(Saved[1], STI);
114 Out.EmitBundleUnlock();
115 }
116
117 static void EmitGuardReturn(const MCSubtargetInfo &STI, int I, MCInst Saved[],
118 MCStreamer &Out) {
119 // sfi_return_preamble reg cond=
120 // sfi_nop_if_at_bundle_end
121 // sfi_code_mask \reg \cond
122 assert(I == 2 && (ARM::SFI_GUARD_RETURN == Saved[0].getOpcode()) &&
123 "Unexpected SFI Pseudo while lowering SFI_GUARD_RETURN");
124 int64_t Pred = Saved[0].getOperand(0).getImm();
125
126 Out.EmitBundleLock(false);
127 EmitBICMask(STI, Out, ARM::LR, Pred, 0xC000000F);
128 Out.EmitInstruction(Saved[1], STI);
129 Out.EmitBundleUnlock();
130 }
131
132 static void EmitGuardLoadOrStore(const MCSubtargetInfo &STI, int I,
133 MCInst Saved[], MCStreamer &Out) {
134 // sfi_store_preamble reg cond ---->
135 // sfi_nop_if_at_bundle_end
136 // sfi_data_mask \reg, \cond
137 assert(I == 2 && (ARM::SFI_GUARD_LOADSTORE == Saved[0].getOpcode()) &&
138 "Unexpected SFI Pseudo while lowering SFI_GUARD_RETURN");
139 unsigned Reg = Saved[0].getOperand(0).getReg();
140 int64_t Pred = Saved[0].getOperand(2).getImm();
141
142 Out.EmitBundleLock(false);
143 EmitBICMask(STI, Out, Reg, Pred, 0xC0000000);
144 Out.EmitInstruction(Saved[1], STI);
145 Out.EmitBundleUnlock();
146 }
147
148 static void EmitGuardLoadOrStoreTst(const MCSubtargetInfo &STI, int I,
149 MCInst Saved[], MCStreamer &Out) {
150 // sfi_cstore_preamble reg -->
151 // sfi_nop_if_at_bundle_end
152 // sfi_data_tst \reg
153 assert(I == 2 && (ARM::SFI_GUARD_LOADSTORE_TST == Saved[0].getOpcode()) &&
154 "Unexpected SFI Pseudo while lowering");
155 unsigned Reg = Saved[0].getOperand(0).getReg();
156
157 Out.EmitBundleLock(false);
158 EmitTST(STI, Out, Reg);
159 Out.EmitInstruction(Saved[1], STI);
160 Out.EmitBundleUnlock();
161 }
162
163 // This is ONLY used for loads into the stack pointer.
164 static void EmitGuardSpLoad(const MCSubtargetInfo &STI, int I, MCInst Saved[],
165 MCStreamer &Out) {
166 assert(I == 4 &&
167 (ARM::SFI_GUARD_SP_LOAD == Saved[0].getOpcode()) &&
168 (ARM::SFI_NOP_IF_AT_BUNDLE_END == Saved[1].getOpcode()) &&
169 (ARM::SFI_DATA_MASK == Saved[3].getOpcode()) &&
170 "Unexpected SFI Pseudo while lowering");
171
172 unsigned AddrReg = Saved[0].getOperand(0).getReg();
173 unsigned SpReg = Saved[3].getOperand(0).getReg();
174 int64_t Pred = Saved[3].getOperand(2).getImm();
175 assert((ARM::SP == SpReg) && "Unexpected register at stack guard");
176
177 Out.EmitBundleLock(false);
178 EmitBICMask(STI, Out, AddrReg, Pred, 0xC0000000);
179 Out.EmitInstruction(Saved[2], STI);
180 EmitBICMask(STI, Out, SpReg, Pred, 0xC0000000);
181 Out.EmitBundleUnlock();
182 }
183
184 namespace llvm {
185
186 const int ARMMCNaClSFIState::MaxSaved;
187
188 // CustomExpandInstNaClARM -
189 // If Inst is a NaCl pseudo instruction, emits the substitute
190 // expansion to the MCStreamer and returns true.
191 // Otherwise, returns false.
192 //
193 // NOTE: Each time this function calls Out.EmitInstruction(), it will be
194 // called again recursively to rewrite the new instruction being emitted.
195 // Care must be taken to ensure that this does not result in an infinite
196 // loop. Also, global state must be managed carefully so that it is
197 // consistent during recursive calls.
198 bool CustomExpandInstNaClARM(const MCSubtargetInfo &STI, const MCInst &Inst,
199 MCStreamer &Out, ARMMCNaClSFIState &State) {
200 // Logic:
201 // This is somewhat convoluted, but in the current model, the SFI
202 // guard pseudo instructions occur PRIOR to the actual instruction.
203 // So, the bundling/alignment operation has to refer to the FOLLOWING
204 // instructions.
205 //
206 // When a SFI pseudo is detected, it is saved. Then, the saved SFI
207 // pseudo and the very next instructions (their amount depending on the kind
208 // of the SFI pseudo) are used as arguments to the Emit*() functions in
209 // this file.
210 //
211 // Some state data is used to preserve state accross calls:
212 //
213 // Saved: the saved instructions (starting with the SFI_ pseudo).
214 // SavedCount: the amount of saved instructions required for the SFI pseudo
215 // that's being expanded.
216 // I: the index of the currently saved instruction - used to track
217 // where in Saved to insert the instruction and how many more
218 // remain.
219 //
220
221 // If we are emitting to .s, just emit all pseudo-instructions directly.
222 if (Out.hasRawTextSupport()) {
223 return false;
224 }
225
226 // Protect against recursive execution. If State.RecurseiveCall == true, it
227 // means we're already in the process of expanding a custom instruction, and
228 // we don't need to run recursively on anything generated by such an
229 // expansion.
230 if (State.RecursiveCall)
231 return false;
232
233 DEBUG(dbgs() << "CustomExpandInstNaClARM("; Inst.dump(); dbgs() << ")\n");
234
235 if ((State.I == 0) && (State.SaveCount == 0)) {
236 // Base state: no SFI guard identified yet and no saving started.
237 switch (Inst.getOpcode()) {
238 default:
239 // We don't handle non-SFI guards here
240 return false;
241 case ARM::SFI_NOP_IF_AT_BUNDLE_END:
242 // Note: SFI_NOP_IF_AT_BUNDLE_END is only emitted directly as part of
243 // a stack guard in conjunction with a SFI_DATA_MASK.
244 State.SaveCount = 3;
245 break;
246 case ARM::SFI_DATA_MASK:
247 llvm_unreachable(
248 "SFI_DATA_MASK found without preceding SFI_NOP_IF_AT_BUNDLE_END");
249 return false;
250 case ARM::SFI_GUARD_CALL:
251 case ARM::SFI_GUARD_INDIRECT_CALL:
252 case ARM::SFI_GUARD_INDIRECT_JMP:
253 case ARM::SFI_GUARD_RETURN:
254 case ARM::SFI_GUARD_LOADSTORE:
255 case ARM::SFI_GUARD_LOADSTORE_TST:
256 State.SaveCount = 2;
257 break;
258 case ARM::SFI_GUARD_SP_LOAD:
259 State.SaveCount = 4;
260 break;
261 }
262 }
263
264 // We're in "saving instructions" state
265 if (State.I < State.SaveCount) {
266 // This instruction has to be saved
267 assert(State.I < State.MaxSaved && "Trying to save too many instructions");
268 State.Saved[State.I++] = Inst;
269 if (State.I < State.SaveCount)
270 return true;
271 }
272
273 // We're in "saved enough instructions, time to emit" state
274 assert(State.I == State.SaveCount && State.SaveCount > 0 && "Bookeeping Error" );
275
276 // When calling Emit* functions, do that with RecurseGuard set (the comment
277 // at the beginning of this function explains why)
278 State.RecursiveCall = true;
279 switch (State.Saved[0].getOpcode()) {
280 default:
281 break;
282 case ARM::SFI_NOP_IF_AT_BUNDLE_END:
283 EmitDataMask(STI, State.I, State.Saved, Out);
284 break;
285 case ARM::SFI_DATA_MASK:
286 llvm_unreachable("SFI_DATA_MASK can't start a SFI sequence");
287 break;
288 case ARM::SFI_GUARD_CALL:
289 EmitDirectGuardCall(STI, State.I, State.Saved, Out);
290 break;
291 case ARM::SFI_GUARD_INDIRECT_CALL:
292 EmitIndirectGuardCall(STI, State.I, State.Saved, Out);
293 break;
294 case ARM::SFI_GUARD_INDIRECT_JMP:
295 EmitIndirectGuardJmp(STI, State.I, State.Saved, Out);
296 break;
297 case ARM::SFI_GUARD_RETURN:
298 EmitGuardReturn(STI, State.I, State.Saved, Out);
299 break;
300 case ARM::SFI_GUARD_LOADSTORE:
301 EmitGuardLoadOrStore(STI, State.I, State.Saved, Out);
302 break;
303 case ARM::SFI_GUARD_LOADSTORE_TST:
304 EmitGuardLoadOrStoreTst(STI, State.I, State.Saved, Out);
305 break;
306 case ARM::SFI_GUARD_SP_LOAD:
307 EmitGuardSpLoad(STI, State.I, State.Saved, Out);
308 break;
309 }
310 assert(State.RecursiveCall && "Illegal Depth");
311 State.RecursiveCall = false;
312
313 // We're done expanding a SFI guard. Reset state vars.
314 State.SaveCount = 0;
315 State.I = 0;
316 return true;
317 }
318
319 } // namespace llvm
OLDNEW
« no previous file with comments | « lib/Target/ARM/MCTargetDesc/ARMMCNaCl.h ('k') | lib/Target/ARM/MCTargetDesc/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698