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. |
| 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 |
| 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 |