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

Side by Side Diff: src/IceTargetLoweringX8664.cpp

Issue 1559243002: Suzero. X8664. NaCl Sandboxing. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fixes filetype=asm; addresses comments. Created 4 years, 11 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 | « src/IceTargetLoweringX8664.h ('k') | src/IceTargetLoweringX8664Traits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
11 /// \brief Implements the TargetLoweringX8664 class, which consists almost 11 /// \brief Implements the TargetLoweringX8664 class, which consists almost
12 /// entirely of the lowering sequence for each high-level instruction. 12 /// entirely of the lowering sequence for each high-level instruction.
13 /// 13 ///
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15
16 #include "IceTargetLoweringX8664.h" 15 #include "IceTargetLoweringX8664.h"
17 16
17 #include "IceDefs.h"
18 #include "IceTargetLoweringX8664Traits.h" 18 #include "IceTargetLoweringX8664Traits.h"
19 19
20 namespace X8664 { 20 namespace X8664 {
21 std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) { 21 std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) {
22 return ::Ice::X8664::TargetX8664::create(Func); 22 return ::Ice::X8664::TargetX8664::create(Func);
23 } 23 }
24 24
25 std::unique_ptr<::Ice::TargetDataLowering> 25 std::unique_ptr<::Ice::TargetDataLowering>
26 createTargetDataLowering(::Ice::GlobalContext *Ctx) { 26 createTargetDataLowering(::Ice::GlobalContext *Ctx) {
27 return ::Ice::X8664::TargetDataX8664::create(Ctx); 27 return ::Ice::X8664::TargetDataX8664::create(Ctx);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 TargetX86Base<X8664::Traits>::Traits::FK_Abs; 123 TargetX86Base<X8664::Traits>::Traits::FK_Abs;
124 124
125 //------------------------------------------------------------------------------ 125 //------------------------------------------------------------------------------
126 // __ ______ __ __ ______ ______ __ __ __ ______ 126 // __ ______ __ __ ______ ______ __ __ __ ______
127 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ 127 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\
128 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ 128 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \
129 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ 129 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
130 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ 130 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
131 // 131 //
132 //------------------------------------------------------------------------------ 132 //------------------------------------------------------------------------------
133 void TargetX8664::_add_sp(Operand *Adjustment) {
134 Variable *rsp =
135 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
136 if (!NeedSandboxing) {
137 _add(rsp, Adjustment);
138 return;
139 }
140
141 Variable *esp =
142 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32);
143 Variable *r15 =
144 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
145
146 // When incrementing rsp, NaCl sandboxing requires the following sequence
147 //
148 // .bundle_start
149 // add Adjustment, %esp
150 // add %r15, %rsp
151 // .bundle_end
152 //
153 // In Subzero, even though rsp and esp alias each other, defining one does not
154 // define the other. Therefore, we must emit
155 //
156 // .bundle_start
157 // %esp = fake-def %rsp
158 // add Adjustment, %esp
159 // %rsp = fake-def %esp
160 // add %r15, %rsp
161 // .bundle_end
162 //
163 // The fake-defs ensure that the
164 //
165 // add Adjustment, %esp
166 //
167 // instruction is not DCE'd.
168 _bundle_lock();
169 _redefined(Context.insert<InstFakeDef>(esp, rsp));
170 _add(esp, Adjustment);
171 _redefined(Context.insert<InstFakeDef>(rsp, esp));
172 _add(rsp, r15);
173 _bundle_unlock();
174 }
175
176 void TargetX8664::_mov_sp(Operand *NewValue) {
177 assert(NewValue->getType() == IceType_i32);
178
179 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
180 Variable *rsp =
181 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
182
183 if (NeedSandboxing) {
184 _bundle_lock();
185 }
186
187 _redefined(Context.insert<InstFakeDef>(esp, rsp));
188 _redefined(_mov(esp, NewValue));
189 _redefined(Context.insert<InstFakeDef>(rsp, esp));
190
191 if (!NeedSandboxing) {
192 return;
193 }
194
195 Variable *r15 =
196 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
197 _add(rsp, r15);
198 _bundle_unlock();
199 }
200
201 void TargetX8664::_push_rbp() {
202 assert(NeedSandboxing);
203
204 Constant *_0 = Ctx->getConstantZero(IceType_i32);
205 Variable *ebp =
206 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32);
207 Variable *rsp =
208 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
209 auto *TopOfStack = llvm::cast<X86OperandMem>(
210 legalize(X86OperandMem::create(Func, IceType_i32, rsp, _0),
211 Legal_Reg | Legal_Mem));
212
213 // Emits a sequence:
214 //
215 // .bundle_start
216 // push 0
217 // mov %ebp, %(rsp)
218 // .bundle_end
219 //
220 // to avoid leaking the upper 32-bits (i.e., the sandbox address.)
221 _bundle_lock();
222 _push(_0);
223 Context.insert<typename Traits::Insts::Store>(ebp, TopOfStack);
224 _bundle_unlock();
225 }
226
227 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
228 // In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.)
229 // NaCl sandboxing also requires that any registers that are not %rsp and
230 // %rbp to be 'truncated' to 32-bit before memory access.
231 assert(NeedSandboxing);
232 Variable *Base = Mem->getBase();
233 Variable *Index = Mem->getIndex();
234 uint16_t Shift = 0;
235 Variable *r15 =
236 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
237 Constant *Offset = Mem->getOffset();
238 Variable *T = nullptr;
239
240 if (Mem->getIsRebased()) {
241 // If Mem.IsRebased, then we don't need to update Mem to contain a reference
242 // to %r15, but we still need to truncate Mem.Index (if any) to 32-bit.
243 assert(r15 == Base);
244 T = Index;
245 Shift = Mem->getShift();
246 } else if (Base != nullptr && Index != nullptr) {
247 // Another approach could be to emit an
248 //
249 // lea Mem, %T
250 //
251 // And then update Mem.Base = r15, Mem.Index = T, Mem.Shift = 0
252 llvm::report_fatal_error("memory reference contains base and index.");
253 } else if (Base != nullptr) {
254 T = Base;
255 } else if (Index != nullptr) {
256 T = Index;
257 Shift = Mem->getShift();
258 }
259
260 // NeedsLea is a flags indicating whether Mem needs to be materialized to a
261 // GPR prior to being used. A LEA is needed if Mem.Offset is a constant
262 // relocatable, or if Mem.Offset is negative. In both these cases, the LEA is
263 // needed to ensure the sandboxed memory operand will only use the lower
264 // 32-bits of T+Offset.
265 bool NeedsLea = false;
266 if (const auto *Offset = Mem->getOffset()) {
267 if (llvm::isa<ConstantRelocatable>(Offset)) {
268 NeedsLea = true;
269 } else if (const auto *Imm = llvm::cast<ConstantInteger32>(Offset)) {
270 NeedsLea = Imm->getValue() < 0;
271 }
272 }
273
274 int32_t RegNum = Variable::NoRegister;
275 int32_t RegNum32 = Variable::NoRegister;
276 if (T != nullptr) {
277 if (T->hasReg()) {
278 RegNum = Traits::getGprForType(IceType_i64, T->getRegNum());
279 RegNum32 = Traits::getGprForType(IceType_i32, RegNum);
280 switch (RegNum) {
281 case Traits::RegisterSet::Reg_rsp:
282 case Traits::RegisterSet::Reg_rbp:
283 // Memory operands referencing rsp/rbp do not need to be sandboxed.
284 return Mem;
285 }
286 }
287
288 switch (T->getType()) {
289 default:
290 case IceType_i64:
291 // Even though "default:" would also catch T.Type == IceType_i64, an
292 // explicit 'case IceType_i64' shows that memory operands are always
293 // supposed to be 32-bits.
294 llvm::report_fatal_error("Mem pointer should be 32-bit.");
295 case IceType_i32: {
296 Variable *T64 = makeReg(IceType_i64, RegNum);
297 auto *Movzx = _movzx(T64, T);
298 if (!NeedsLea) {
299 // This movzx is only needed when Mem does not need to be lea'd into a
300 // temporary. If an lea is going to be emitted, then eliding this movzx
301 // is safe because the emitted lea will write a 32-bit result --
302 // implicitly zero-extended to 64-bit.
303 Movzx->setMustKeep();
304 }
305 T = T64;
306 } break;
307 }
308 }
309
310 if (NeedsLea) {
311 Variable *NewT = makeReg(IceType_i32, RegNum32);
312 Variable *Base = T;
313 Variable *Index = T;
314 static constexpr bool NotRebased = false;
315 if (Shift == 0) {
316 Index = nullptr;
317 } else {
318 Base = nullptr;
319 }
320 _lea(NewT, Traits::X86OperandMem::create(
321 Func, Mem->getType(), Base, Offset, Index, Shift,
322 Traits::X86OperandMem::DefaultSegment, NotRebased));
323
324 T = makeReg(IceType_i64, RegNum);
325 _movzx(T, NewT);
326 Shift = 0;
327 Offset = nullptr;
328 }
329
330 static constexpr bool IsRebased = true;
331 return Traits::X86OperandMem::create(
332 Func, Mem->getType(), r15, Offset, T, Shift,
333 Traits::X86OperandMem::DefaultSegment, IsRebased);
334 }
335
336 void TargetX8664::_sub_sp(Operand *Adjustment) {
337 Variable *rsp =
338 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
339 if (!NeedSandboxing) {
340 _sub(rsp, Adjustment);
341 return;
342 }
343
344 Variable *esp =
345 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32);
346 Variable *r15 =
347 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
348
349 // .bundle_start
350 // sub Adjustment, %esp
351 // add %r15, %rsp
352 // .bundle_end
353 _bundle_lock();
354 _redefined(Context.insert<InstFakeDef>(esp, rsp));
355 _sub(esp, Adjustment);
356 _redefined(Context.insert<InstFakeDef>(rsp, esp));
357 _add(rsp, r15);
358 _bundle_unlock();
359 }
360
361 void TargetX8664::initSandbox() {
362 assert(NeedSandboxing);
363 Context.init(Func->getEntryNode());
364 Context.setInsertPoint(Context.getCur());
365 Variable *r15 =
366 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
367 Context.insert<InstFakeDef>(r15);
368 Context.insert<InstFakeUse>(r15);
369 }
370
371 void TargetX8664::lowerIndirectJump(Variable *JumpTarget) {
372 if (!NeedSandboxing) {
373 Variable *T = makeReg(IceType_i64);
374 _movzx(T, JumpTarget);
375 JumpTarget = T;
376 } else {
377 Variable *T = makeReg(IceType_i32);
378 Variable *T64 = makeReg(IceType_i64);
379 Variable *r15 =
380 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
381
382 _mov(T, JumpTarget);
383 _bundle_lock();
384 const SizeT BundleSize =
385 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
386 _and(T, Ctx->getConstantInt32(~(BundleSize - 1)));
387 _movzx(T64, T);
388 _add(T64, r15);
389 JumpTarget = T64;
390 }
391
392 _jmp(JumpTarget);
393 if (NeedSandboxing)
394 _bundle_unlock();
395 }
396
133 namespace { 397 namespace {
134 static inline TargetX8664::Traits::RegisterSet::AllRegisters 398 static inline TargetX8664::Traits::RegisterSet::AllRegisters
135 getRegisterForXmmArgNum(uint32_t ArgNum) { 399 getRegisterForXmmArgNum(uint32_t ArgNum) {
136 assert(ArgNum < TargetX8664::Traits::X86_MAX_XMM_ARGS); 400 assert(ArgNum < TargetX8664::Traits::X86_MAX_XMM_ARGS);
137 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>( 401 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>(
138 TargetX8664::Traits::RegisterSet::Reg_xmm0 + ArgNum); 402 TargetX8664::Traits::RegisterSet::Reg_xmm0 + ArgNum);
139 } 403 }
140 404
141 static inline TargetX8664::Traits::RegisterSet::AllRegisters 405 static inline TargetX8664::Traits::RegisterSet::AllRegisters
142 getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 406 getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 case IceType_v16i1: 574 case IceType_v16i1:
311 case IceType_v16i8: 575 case IceType_v16i8:
312 case IceType_v8i16: 576 case IceType_v8i16:
313 case IceType_v4i32: 577 case IceType_v4i32:
314 case IceType_v4f32: 578 case IceType_v4f32:
315 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); 579 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0);
316 break; 580 break;
317 } 581 }
318 } 582 }
319 583
320 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); 584 InstX86Label *ReturnAddress = nullptr;
321 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { 585 Operand *CallTarget =
322 // x86-64 in Subzero is ILP32. Therefore, CallTarget is i32, but the emitted 586 legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm | Legal_AddrAbs);
323 // call needs a i64 register (for textual asm.) 587 auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget);
324 Variable *T = makeReg(IceType_i64); 588 Inst *NewCall = nullptr;
325 _movzx(T, CallTargetR); 589 if (!NeedSandboxing) {
326 CallTarget = T; 590 if (CallTargetR != nullptr) {
327 } 591 // x86-64 in Subzero is ILP32. Therefore, CallTarget is i32, but the
328 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); 592 // emitted call needs a i64 register (for textual asm.)
329 if (NeedSandboxing) { 593 Variable *T = makeReg(IceType_i64);
330 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); 594 _movzx(T, CallTargetR);
331 } 595 CallTarget = T;
332 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); 596 }
333 if (NeedSandboxing) { 597 NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget);
334 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); 598 } else {
599 ReturnAddress = InstX86Label::create(Func, this);
600 ReturnAddress->setIsReturnLocation(true);
601 constexpr bool SuppressMangling = true;
602 if (CallTargetR == nullptr) {
603 _bundle_lock(InstBundleLock::Opt_PadToEnd);
604 _push(Ctx->getConstantSym(0, ReturnAddress->getName(Func),
605 SuppressMangling));
606 } else {
607 Variable *T = makeReg(IceType_i32);
608 Variable *T64 = makeReg(IceType_i64);
609 Variable *r15 =
610 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
611
612 _mov(T, CallTargetR);
613 _bundle_lock(InstBundleLock::Opt_PadToEnd);
614 _push(Ctx->getConstantSym(0, ReturnAddress->getName(Func),
615 SuppressMangling));
616 const SizeT BundleSize =
617 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
618 _and(T, Ctx->getConstantInt32(~(BundleSize - 1)));
619 _movzx(T64, T);
620 _add(T64, r15);
621 CallTarget = T64;
622 }
623
624 NewCall = Context.insert<Traits::Insts::Jmp>(CallTarget);
625 _bundle_unlock();
626 if (ReturnReg != nullptr) {
627 Context.insert<InstFakeDef>(ReturnReg);
628 }
629
630 Context.insert(ReturnAddress);
335 } 631 }
336 632
337 // Insert a register-kill pseudo instruction. 633 // Insert a register-kill pseudo instruction.
338 Context.insert<InstFakeKill>(NewCall); 634 Context.insert<InstFakeKill>(NewCall);
339 635
340 // Generate a FakeUse to keep the call live if necessary. 636 // Generate a FakeUse to keep the call live if necessary.
341 if (Instr->hasSideEffects() && ReturnReg) { 637 if (Instr->hasSideEffects() && ReturnReg) {
342 Context.insert<InstFakeUse>(ReturnReg); 638 Context.insert<InstFakeUse>(ReturnReg);
343 } 639 }
344 640
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 // Add push instructions for preserved registers. 812 // Add push instructions for preserved registers.
517 uint32_t NumCallee = 0; 813 uint32_t NumCallee = 0;
518 size_t PreservedRegsSizeBytes = 0; 814 size_t PreservedRegsSizeBytes = 0;
519 llvm::SmallBitVector Pushed(CalleeSaves.size()); 815 llvm::SmallBitVector Pushed(CalleeSaves.size());
520 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { 816 for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
521 const int32_t Canonical = Traits::getBaseReg(i); 817 const int32_t Canonical = Traits::getBaseReg(i);
522 assert(Canonical == Traits::getBaseReg(Canonical)); 818 assert(Canonical == Traits::getBaseReg(Canonical));
523 if (CalleeSaves[i] && RegsUsed[i]) 819 if (CalleeSaves[i] && RegsUsed[i])
524 Pushed[Canonical] = true; 820 Pushed[Canonical] = true;
525 } 821 }
822
823 Variable *rbp =
824 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64);
825 Variable *ebp =
826 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32);
827 Variable *rsp =
828 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
829
526 for (SizeT i = 0; i < Pushed.size(); ++i) { 830 for (SizeT i = 0; i < Pushed.size(); ++i) {
527 if (!Pushed[i]) 831 if (!Pushed[i])
528 continue; 832 continue;
529 assert(static_cast<int32_t>(i) == Traits::getBaseReg(i)); 833 assert(static_cast<int32_t>(i) == Traits::getBaseReg(i));
530 ++NumCallee; 834 ++NumCallee;
531 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); 835 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64);
532 _push(getPhysicalRegister(i, IceType_i64)); 836 Variable *Src = getPhysicalRegister(i, IceType_i64);
837 if (Src != rbp || !NeedSandboxing) {
838 _push(getPhysicalRegister(i, IceType_i64));
839 } else {
840 _push_rbp();
841 }
533 } 842 }
534 Ctx->statsUpdateRegistersSaved(NumCallee); 843 Ctx->statsUpdateRegistersSaved(NumCallee);
535 844
536 // Generate "push ebp; mov ebp, esp" 845 // Generate "push ebp; mov ebp, esp"
537 if (IsEbpBasedFrame) { 846 if (IsEbpBasedFrame) {
538 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) 847 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None))
539 .count() == 0); 848 .count() == 0);
540 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); 849 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64);
541 Variable *ebp =
542 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64);
543 Variable *esp = 850 Variable *esp =
544 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); 851 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32);
545 _push(ebp); 852 Variable *r15 =
546 _mov(ebp, esp); 853 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
854
855 if (!NeedSandboxing) {
856 _push(rbp);
857 _mov(rbp, rsp);
858 } else {
859 _push_rbp();
860
861 _bundle_lock();
862 _redefined(Context.insert<InstFakeDef>(ebp, rbp));
863 _redefined(Context.insert<InstFakeDef>(esp, rsp));
864 _mov(ebp, esp);
865 _redefined(Context.insert<InstFakeDef>(rsp, esp));
866 _add(rbp, r15);
867 _bundle_unlock();
868 }
547 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). 869 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode).
548 Context.insert<InstFakeUse>(ebp); 870 Context.insert<InstFakeUse>(rbp);
549 } 871 }
550 872
551 // Align the variables area. SpillAreaPaddingBytes is the size of the region 873 // Align the variables area. SpillAreaPaddingBytes is the size of the region
552 // after the preserved registers and before the spill areas. 874 // after the preserved registers and before the spill areas.
553 // LocalsSlotsPaddingBytes is the amount of padding between the globals and 875 // LocalsSlotsPaddingBytes is the amount of padding between the globals and
554 // locals area if they are separate. 876 // locals area if they are separate.
555 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); 877 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES);
556 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); 878 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes);
557 uint32_t SpillAreaPaddingBytes = 0; 879 uint32_t SpillAreaPaddingBytes = 0;
558 uint32_t LocalsSlotsPaddingBytes = 0; 880 uint32_t LocalsSlotsPaddingBytes = 0;
(...skipping 16 matching lines...) Expand all
575 } else { 897 } else {
576 SpillAreaSizeBytes += maxOutArgsSizeBytes(); 898 SpillAreaSizeBytes += maxOutArgsSizeBytes();
577 } 899 }
578 900
579 // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the 901 // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the
580 // fixed allocations in the prolog. 902 // fixed allocations in the prolog.
581 if (PrologEmitsFixedAllocas) 903 if (PrologEmitsFixedAllocas)
582 SpillAreaSizeBytes += FixedAllocaSizeBytes; 904 SpillAreaSizeBytes += FixedAllocaSizeBytes;
583 // Generate "sub esp, SpillAreaSizeBytes" 905 // Generate "sub esp, SpillAreaSizeBytes"
584 if (SpillAreaSizeBytes) { 906 if (SpillAreaSizeBytes) {
585 _sub(getPhysicalRegister(getStackReg(), IceType_i64), 907 if (NeedSandboxing) {
586 Ctx->getConstantInt32(SpillAreaSizeBytes)); 908 _sub_sp(Ctx->getConstantInt32(SpillAreaSizeBytes));
909 } else {
910 _sub(getPhysicalRegister(getStackReg(), IceType_i64),
911 Ctx->getConstantInt32(SpillAreaSizeBytes));
912 }
587 // If the fixed allocas are aligned more than the stack frame, align the 913 // If the fixed allocas are aligned more than the stack frame, align the
588 // stack pointer accordingly. 914 // stack pointer accordingly.
589 if (PrologEmitsFixedAllocas && 915 if (PrologEmitsFixedAllocas &&
590 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { 916 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) {
591 assert(IsEbpBasedFrame); 917 assert(IsEbpBasedFrame);
592 _and(getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64), 918 _and(getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64),
593 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); 919 Ctx->getConstantInt32(-FixedAllocaAlignBytes));
594 } 920 }
595 } 921 }
596 922
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 if (RI == E) 1018 if (RI == E)
693 return; 1019 return;
694 1020
695 // Convert the reverse_iterator position into its corresponding (forward) 1021 // Convert the reverse_iterator position into its corresponding (forward)
696 // iterator position. 1022 // iterator position.
697 InstList::iterator InsertPoint = RI.base(); 1023 InstList::iterator InsertPoint = RI.base();
698 --InsertPoint; 1024 --InsertPoint;
699 Context.init(Node); 1025 Context.init(Node);
700 Context.setInsertPoint(InsertPoint); 1026 Context.setInsertPoint(InsertPoint);
701 1027
702 Variable *esp = 1028 Variable *rsp =
703 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); 1029 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
704 if (IsEbpBasedFrame) { 1030
1031 if (!IsEbpBasedFrame) {
1032 // add rsp, SpillAreaSizeBytes
1033 if (SpillAreaSizeBytes != 0) {
1034 _add_sp(Ctx->getConstantInt32(SpillAreaSizeBytes));
1035 }
1036 } else {
1037 Variable *rbp =
1038 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64);
705 Variable *ebp = 1039 Variable *ebp =
706 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64); 1040 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32);
707 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake 1041 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake
708 // use of esp before the assignment of esp=ebp keeps previous esp 1042 // use of rsp before the assignment of rsp=rbp keeps previous rsp
709 // adjustments from being dead-code eliminated. 1043 // adjustments from being dead-code eliminated.
710 Context.insert<InstFakeUse>(esp); 1044 Context.insert<InstFakeUse>(rsp);
711 _mov(esp, ebp); 1045 if (!NeedSandboxing) {
712 _pop(ebp); 1046 _mov(rsp, rbp);
713 } else { 1047 _pop(rbp);
714 // add esp, SpillAreaSizeBytes 1048 } else {
715 if (SpillAreaSizeBytes) 1049 _mov_sp(ebp);
716 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); 1050
1051 Variable *r15 =
1052 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
1053 Variable *rcx =
1054 getPhysicalRegister(Traits::RegisterSet::Reg_rcx, IceType_i64);
1055 Variable *ecx =
1056 getPhysicalRegister(Traits::RegisterSet::Reg_ecx, IceType_i32);
1057
1058 _pop(rcx);
1059 Context.insert<InstFakeDef>(ecx, rcx);
1060 _bundle_lock();
1061 _mov(ebp, ecx);
1062
1063 _redefined(Context.insert<InstFakeDef>(rbp, ebp));
1064 _add(rbp, r15);
1065 _bundle_unlock();
1066 }
717 } 1067 }
718 1068
719 // Add pop instructions for preserved registers. 1069 // Add pop instructions for preserved registers.
720 llvm::SmallBitVector CalleeSaves = 1070 llvm::SmallBitVector CalleeSaves =
721 getRegisterSet(RegSet_CalleeSave, RegSet_None); 1071 getRegisterSet(RegSet_CalleeSave, RegSet_None);
722 llvm::SmallBitVector Popped(CalleeSaves.size()); 1072 llvm::SmallBitVector Popped(CalleeSaves.size());
723 for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) { 1073 for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) {
724 if (i == Traits::RegisterSet::Reg_rbp && IsEbpBasedFrame) 1074 if (i == Traits::RegisterSet::Reg_rbp && IsEbpBasedFrame)
725 continue; 1075 continue;
726 const SizeT Canonical = Traits::getBaseReg(i); 1076 const SizeT Canonical = Traits::getBaseReg(i);
727 if (CalleeSaves[i] && RegsUsed[i]) 1077 if (CalleeSaves[i] && RegsUsed[i])
728 Popped[Canonical] = true; 1078 Popped[Canonical] = true;
729 } 1079 }
730 for (int32_t i = Popped.size() - 1; i >= 0; --i) { 1080 for (int32_t i = Popped.size() - 1; i >= 0; --i) {
731 if (!Popped[i]) 1081 if (!Popped[i])
732 continue; 1082 continue;
733 assert(i == Traits::getBaseReg(i)); 1083 assert(i == Traits::getBaseReg(i));
734 _pop(getPhysicalRegister(i, IceType_i64)); 1084 _pop(getPhysicalRegister(i, IceType_i64));
735 } 1085 }
736 1086
737 if (Ctx->getFlags().getUseSandboxing()) { 1087 if (!NeedSandboxing) {
738 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); 1088 return;
739 } 1089 }
1090
1091 Variable *T_rcx = makeReg(IceType_i64, Traits::RegisterSet::Reg_rcx);
1092 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
1093 _pop(T_rcx);
1094 _mov(T_ecx, T_rcx);
1095
1096 // lowerIndirectJump(T_ecx);
1097 Variable *r15 =
1098 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
1099
1100 _bundle_lock();
1101 const SizeT BundleSize = 1
1102 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
1103 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1)));
1104 Context.insert<InstFakeDef>(T_rcx, T_ecx);
1105 _add(T_rcx, r15);
1106
1107 _jmp(T_rcx);
1108 _bundle_unlock();
1109
1110 if (RI->getSrcSize()) {
1111 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0));
1112 Context.insert<InstFakeUse>(RetValue);
1113 }
1114 RI->setDeleted();
740 } 1115 }
741 1116
742 void TargetX8664::emitJumpTable(const Cfg *Func, 1117 void TargetX8664::emitJumpTable(const Cfg *Func,
743 const InstJumpTable *JumpTable) const { 1118 const InstJumpTable *JumpTable) const {
744 if (!BuildDefs::dump()) 1119 if (!BuildDefs::dump())
745 return; 1120 return;
746 Ostream &Str = Ctx->getStrEmit(); 1121 Ostream &Str = Ctx->getStrEmit();
747 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); 1122 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
748 Str << "\t.section\t.rodata." << MangledName 1123 Str << "\t.section\t.rodata." << MangledName
749 << "$jumptable,\"a\",@progbits\n"; 1124 << "$jumptable,\"a\",@progbits\n";
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 #define X(tag, sizeLog2, align, elts, elty, str) \ 1425 #define X(tag, sizeLog2, align, elts, elty, str) \
1051 static_assert(_table1_##tag == _table2_##tag, \ 1426 static_assert(_table1_##tag == _table2_##tag, \
1052 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); 1427 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE");
1053 ICETYPE_TABLE 1428 ICETYPE_TABLE
1054 #undef X 1429 #undef X
1055 } // end of namespace dummy3 1430 } // end of namespace dummy3
1056 } // end of anonymous namespace 1431 } // end of anonymous namespace
1057 1432
1058 } // end of namespace X8664 1433 } // end of namespace X8664
1059 } // end of namespace Ice 1434 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceTargetLoweringX8664.h ('k') | src/IceTargetLoweringX8664Traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698