OLD | NEW |
---|---|
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 Loading... | |
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 'truncted' to 32-bit before memory access. | |
Jim Stichnoth
2016/01/14 00:09:52
truncated
John
2016/01/14 23:18:25
(I meant to write trunc'ed.)
Done.
| |
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 goign to be emitted, then eliding this movzx | |
Jim Stichnoth
2016/01/14 00:09:52
going
John
2016/01/14 23:18:25
Done.
| |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |