| 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 |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 | 236 |
| 237 // Generate the call instruction. Assign its result to a temporary | 237 // Generate the call instruction. Assign its result to a temporary |
| 238 // with high register allocation weight. | 238 // with high register allocation weight. |
| 239 Variable *Dest = Instr->getDest(); | 239 Variable *Dest = Instr->getDest(); |
| 240 // ReturnReg doubles as ReturnRegLo as necessary. | 240 // ReturnReg doubles as ReturnRegLo as necessary. |
| 241 Variable *ReturnReg = nullptr; | 241 Variable *ReturnReg = nullptr; |
| 242 Variable *ReturnRegHi = nullptr; | 242 Variable *ReturnRegHi = nullptr; |
| 243 if (Dest) { | 243 if (Dest) { |
| 244 switch (Dest->getType()) { | 244 switch (Dest->getType()) { |
| 245 case IceType_NUM: | 245 case IceType_NUM: |
| 246 llvm_unreachable("Invalid Call dest type"); | |
| 247 break; | |
| 248 case IceType_void: | 246 case IceType_void: |
| 247 llvm::report_fatal_error("Invalid Call dest type"); |
| 249 break; | 248 break; |
| 250 case IceType_i1: | 249 case IceType_i1: |
| 251 case IceType_i8: | 250 case IceType_i8: |
| 252 case IceType_i16: | 251 case IceType_i16: |
| 253 case IceType_i32: | 252 case IceType_i32: |
| 254 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); | 253 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); |
| 255 break; | 254 break; |
| 256 case IceType_i64: | 255 case IceType_i64: |
| 257 // TODO(jpp): return i64 in a GPR. | 256 // TODO(jpp): return i64 in a GPR. |
| 258 ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax); | 257 ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | 331 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || |
| 333 isVectorType(Dest->getType())); | 332 isVectorType(Dest->getType())); |
| 334 | 333 |
| 335 if (isScalarFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | 334 if (isScalarFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { |
| 336 _movp(Dest, ReturnReg); | 335 _movp(Dest, ReturnReg); |
| 337 } else { | 336 } else { |
| 338 _mov(Dest, ReturnReg); | 337 _mov(Dest, ReturnReg); |
| 339 } | 338 } |
| 340 } | 339 } |
| 341 | 340 |
| 342 void TargetDataX8664::lowerJumpTables() { | 341 void TargetX8664::lowerArguments() { |
| 343 switch (Ctx->getFlags().getOutFileType()) { | 342 VarList &Args = Func->getArgs(); |
| 344 case FT_Elf: { | 343 // The first eight vetcor typed arguments (as well as fp arguments) are passed |
| 345 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 344 // in %xmm0 through %xmm7 regardless of their position in the argument list. |
| 346 for (const JumpTableData &JumpTable : Ctx->getJumpTables()) | 345 unsigned NumXmmArgs = 0; |
| 347 // TODO(jpp): not 386. | 346 // The first six integer typed arguments are passed in %rdi, %rsi, %rdx, %rcx, |
| 348 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32); | 347 // %r8, and %r9 regardless of their position in the argument list. |
| 349 } break; | 348 unsigned NumGprArgs = 0; |
| 350 case FT_Asm: | 349 |
| 351 // Already emitted from Cfg | 350 Context.init(Func->getEntryNode()); |
| 352 break; | 351 Context.setInsertPoint(Context.getCur()); |
| 353 case FT_Iasm: { | 352 |
| 354 if (!BuildDefs::dump()) | 353 for (SizeT i = 0, End = Args.size(); |
| 355 return; | 354 i < End && (NumXmmArgs < Traits::X86_MAX_XMM_ARGS || |
| 356 Ostream &Str = Ctx->getStrEmit(); | 355 NumGprArgs < Traits::X86_MAX_XMM_ARGS); |
| 357 for (const JumpTableData &JT : Ctx->getJumpTables()) { | 356 ++i) { |
| 358 Str << "\t.section\t.rodata." << JT.getFunctionName() | 357 Variable *Arg = Args[i]; |
| 359 << "$jumptable,\"a\",@progbits\n"; | 358 Type Ty = Arg->getType(); |
| 360 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 359 if ((isVectorType(Ty) || isScalarFloatingType(Ty)) && |
| 361 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | 360 NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { |
| 362 | 361 // Replace Arg in the argument list with the home register. Then |
| 363 // On X8664 ILP32 pointers are 32-bit hence the use of .long | 362 // generate an instruction in the prolog to copy the home register |
| 364 for (intptr_t TargetOffset : JT.getTargetOffsets()) | 363 // to the assigned location of Arg. |
| 365 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | 364 int32_t RegNum = getRegisterForXmmArgNum(NumXmmArgs); |
| 366 Str << "\n"; | 365 ++NumXmmArgs; |
| 367 } | 366 Variable *RegisterArg = Func->makeVariable(Ty); |
| 368 } break; | 367 if (BuildDefs::dump()) |
| 369 } | 368 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 369 RegisterArg->setRegNum(RegNum); |
| 370 RegisterArg->setIsArg(); |
| 371 Arg->setIsArg(false); |
| 372 |
| 373 Args[i] = RegisterArg; |
| 374 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 375 } else if (isScalarIntegerType(Ty) && |
| 376 NumGprArgs < Traits::X86_MAX_GPR_ARGS) { |
| 377 int32_t RegNum = getRegisterForGprArgNum(NumGprArgs); |
| 378 ++NumGprArgs; |
| 379 Variable *RegisterArg = Func->makeVariable(Ty); |
| 380 if (BuildDefs::dump()) |
| 381 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 382 RegisterArg->setRegNum(RegNum); |
| 383 RegisterArg->setIsArg(); |
| 384 Arg->setIsArg(false); |
| 385 |
| 386 Args[i] = RegisterArg; |
| 387 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 388 } |
| 389 } |
| 390 } |
| 391 |
| 392 void TargetX8664::lowerRet(const InstRet *Inst) { |
| 393 Variable *Reg = nullptr; |
| 394 if (Inst->hasRetValue()) { |
| 395 Operand *Src0 = legalize(Inst->getRetValue()); |
| 396 // TODO(jpp): this is not needed. |
| 397 if (Src0->getType() == IceType_i64) { |
| 398 Variable *eax = |
| 399 legalizeToReg(loOperand(Src0), Traits::RegisterSet::Reg_eax); |
| 400 Variable *edx = |
| 401 legalizeToReg(hiOperand(Src0), Traits::RegisterSet::Reg_edx); |
| 402 Reg = eax; |
| 403 Context.insert(InstFakeUse::create(Func, edx)); |
| 404 } else if (isScalarFloatingType(Src0->getType())) { |
| 405 _fld(Src0); |
| 406 } else if (isVectorType(Src0->getType())) { |
| 407 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); |
| 408 } else { |
| 409 _mov(Reg, Src0, Traits::RegisterSet::Reg_eax); |
| 410 } |
| 411 } |
| 412 // Add a ret instruction even if sandboxing is enabled, because |
| 413 // addEpilog explicitly looks for a ret instruction as a marker for |
| 414 // where to insert the frame removal instructions. |
| 415 _ret(Reg); |
| 416 // Add a fake use of esp to make sure esp stays alive for the entire |
| 417 // function. Otherwise post-call esp adjustments get dead-code |
| 418 // eliminated. TODO: Are there more places where the fake use |
| 419 // should be inserted? E.g. "void f(int n){while(1) g(n);}" may not |
| 420 // have a ret instruction. |
| 421 Variable *esp = |
| 422 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 423 Context.insert(InstFakeUse::create(Func, esp)); |
| 424 } |
| 425 |
| 426 void TargetX8664::addProlog(CfgNode *Node) { |
| 427 // Stack frame layout: |
| 428 // |
| 429 // +------------------------+ |
| 430 // | 1. return address | |
| 431 // +------------------------+ |
| 432 // | 2. preserved registers | |
| 433 // +------------------------+ |
| 434 // | 3. padding | |
| 435 // +------------------------+ |
| 436 // | 4. global spill area | |
| 437 // +------------------------+ |
| 438 // | 5. padding | |
| 439 // +------------------------+ |
| 440 // | 6. local spill area | |
| 441 // +------------------------+ |
| 442 // | 7. padding | |
| 443 // +------------------------+ |
| 444 // | 8. allocas | |
| 445 // +------------------------+ |
| 446 // |
| 447 // The following variables record the size in bytes of the given areas: |
| 448 // * X86_RET_IP_SIZE_BYTES: area 1 |
| 449 // * PreservedRegsSizeBytes: area 2 |
| 450 // * SpillAreaPaddingBytes: area 3 |
| 451 // * GlobalsSize: area 4 |
| 452 // * GlobalsAndSubsequentPaddingSize: areas 4 - 5 |
| 453 // * LocalsSpillAreaSize: area 6 |
| 454 // * SpillAreaSizeBytes: areas 3 - 7 |
| 455 |
| 456 // Determine stack frame offsets for each Variable without a |
| 457 // register assignment. This can be done as one variable per stack |
| 458 // slot. Or, do coalescing by running the register allocator again |
| 459 // with an infinite set of registers (as a side effect, this gives |
| 460 // variables a second chance at physical register assignment). |
| 461 // |
| 462 // A middle ground approach is to leverage sparsity and allocate one |
| 463 // block of space on the frame for globals (variables with |
| 464 // multi-block lifetime), and one block to share for locals |
| 465 // (single-block lifetime). |
| 466 |
| 467 Context.init(Node); |
| 468 Context.setInsertPoint(Context.getCur()); |
| 469 |
| 470 llvm::SmallBitVector CalleeSaves = |
| 471 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 472 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); |
| 473 VarList SortedSpilledVariables, VariablesLinkedToSpillSlots; |
| 474 size_t GlobalsSize = 0; |
| 475 // If there is a separate locals area, this represents that area. |
| 476 // Otherwise it counts any variable not counted by GlobalsSize. |
| 477 SpillAreaSizeBytes = 0; |
| 478 // If there is a separate locals area, this specifies the alignment |
| 479 // for it. |
| 480 uint32_t LocalsSlotsAlignmentBytes = 0; |
| 481 // The entire spill locations area gets aligned to largest natural |
| 482 // alignment of the variables that have a spill slot. |
| 483 uint32_t SpillAreaAlignmentBytes = 0; |
| 484 // A spill slot linked to a variable with a stack slot should reuse |
| 485 // that stack slot. |
| 486 std::function<bool(Variable *)> TargetVarHook = |
| 487 [&VariablesLinkedToSpillSlots](Variable *Var) { |
| 488 if (auto *SpillVar = |
| 489 llvm::dyn_cast<typename Traits::SpillVariable>(Var)) { |
| 490 assert(Var->getWeight().isZero()); |
| 491 if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { |
| 492 VariablesLinkedToSpillSlots.push_back(Var); |
| 493 return true; |
| 494 } |
| 495 } |
| 496 return false; |
| 497 }; |
| 498 |
| 499 // Compute the list of spilled variables and bounds for GlobalsSize, etc. |
| 500 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, |
| 501 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, |
| 502 &LocalsSlotsAlignmentBytes, TargetVarHook); |
| 503 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; |
| 504 SpillAreaSizeBytes += GlobalsSize; |
| 505 |
| 506 // Add push instructions for preserved registers. |
| 507 uint32_t NumCallee = 0; |
| 508 size_t PreservedRegsSizeBytes = 0; |
| 509 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 510 if (CalleeSaves[i] && RegsUsed[i]) { |
| 511 ++NumCallee; |
| 512 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
| 513 _push(getPhysicalRegister(i)); |
| 514 } |
| 515 } |
| 516 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 517 |
| 518 // Generate "push ebp; mov ebp, esp" |
| 519 if (IsEbpBasedFrame) { |
| 520 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) |
| 521 .count() == 0); |
| 522 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
| 523 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
| 524 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 525 _push(ebp); |
| 526 _mov(ebp, esp); |
| 527 // Keep ebp live for late-stage liveness analysis |
| 528 // (e.g. asm-verbose mode). |
| 529 Context.insert(InstFakeUse::create(Func, ebp)); |
| 530 } |
| 531 |
| 532 // Align the variables area. SpillAreaPaddingBytes is the size of |
| 533 // the region after the preserved registers and before the spill areas. |
| 534 // LocalsSlotsPaddingBytes is the amount of padding between the globals |
| 535 // and locals area if they are separate. |
| 536 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); |
| 537 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
| 538 uint32_t SpillAreaPaddingBytes = 0; |
| 539 uint32_t LocalsSlotsPaddingBytes = 0; |
| 540 alignStackSpillAreas(Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes, |
| 541 SpillAreaAlignmentBytes, GlobalsSize, |
| 542 LocalsSlotsAlignmentBytes, &SpillAreaPaddingBytes, |
| 543 &LocalsSlotsPaddingBytes); |
| 544 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; |
| 545 uint32_t GlobalsAndSubsequentPaddingSize = |
| 546 GlobalsSize + LocalsSlotsPaddingBytes; |
| 547 |
| 548 // Align esp if necessary. |
| 549 if (NeedsStackAlignment) { |
| 550 uint32_t StackOffset = |
| 551 Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes; |
| 552 uint32_t StackSize = |
| 553 Traits::applyStackAlignment(StackOffset + SpillAreaSizeBytes); |
| 554 SpillAreaSizeBytes = StackSize - StackOffset; |
| 555 } |
| 556 |
| 557 // Generate "sub esp, SpillAreaSizeBytes" |
| 558 if (SpillAreaSizeBytes) |
| 559 _sub(getPhysicalRegister(Traits::RegisterSet::Reg_esp), |
| 560 Ctx->getConstantInt32(SpillAreaSizeBytes)); |
| 561 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
| 562 |
| 563 resetStackAdjustment(); |
| 564 |
| 565 // Fill in stack offsets for stack args, and copy args into registers |
| 566 // for those that were register-allocated. Args are pushed right to |
| 567 // left, so Arg[0] is closest to the stack/frame pointer. |
| 568 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 569 size_t BasicFrameOffset = |
| 570 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; |
| 571 if (!IsEbpBasedFrame) |
| 572 BasicFrameOffset += SpillAreaSizeBytes; |
| 573 |
| 574 const VarList &Args = Func->getArgs(); |
| 575 size_t InArgsSizeBytes = 0; |
| 576 unsigned NumXmmArgs = 0; |
| 577 unsigned NumGPRArgs = 0; |
| 578 for (Variable *Arg : Args) { |
| 579 // Skip arguments passed in registers. |
| 580 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { |
| 581 ++NumXmmArgs; |
| 582 continue; |
| 583 } |
| 584 if (isScalarFloatingType(Arg->getType()) && |
| 585 NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { |
| 586 ++NumXmmArgs; |
| 587 continue; |
| 588 } |
| 589 if (isScalarIntegerType(Arg->getType()) && |
| 590 NumGPRArgs < Traits::X86_MAX_GPR_ARGS) { |
| 591 ++NumGPRArgs; |
| 592 continue; |
| 593 } |
| 594 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 595 } |
| 596 |
| 597 // Fill in stack offsets for locals. |
| 598 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
| 599 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
| 600 IsEbpBasedFrame); |
| 601 // Assign stack offsets to variables that have been linked to spilled |
| 602 // variables. |
| 603 for (Variable *Var : VariablesLinkedToSpillSlots) { |
| 604 Variable *Linked = |
| 605 (llvm::cast<typename Traits::SpillVariable>(Var))->getLinkedTo(); |
| 606 Var->setStackOffset(Linked->getStackOffset()); |
| 607 } |
| 608 this->HasComputedFrame = true; |
| 609 |
| 610 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
| 611 OstreamLocker L(Func->getContext()); |
| 612 Ostream &Str = Func->getContext()->getStrDump(); |
| 613 |
| 614 Str << "Stack layout:\n"; |
| 615 uint32_t EspAdjustmentPaddingSize = |
| 616 SpillAreaSizeBytes - LocalsSpillAreaSize - |
| 617 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; |
| 618 Str << " in-args = " << InArgsSizeBytes << " bytes\n" |
| 619 << " return address = " << Traits::X86_RET_IP_SIZE_BYTES << " bytes\n" |
| 620 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" |
| 621 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" |
| 622 << " globals spill area = " << GlobalsSize << " bytes\n" |
| 623 << " globals-locals spill areas intermediate padding = " |
| 624 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n" |
| 625 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n" |
| 626 << " esp alignment padding = " << EspAdjustmentPaddingSize |
| 627 << " bytes\n"; |
| 628 |
| 629 Str << "Stack details:\n" |
| 630 << " esp adjustment = " << SpillAreaSizeBytes << " bytes\n" |
| 631 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n" |
| 632 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes |
| 633 << " bytes\n" |
| 634 << " is ebp based = " << IsEbpBasedFrame << "\n"; |
| 635 } |
| 636 } |
| 637 |
| 638 void TargetX8664::addEpilog(CfgNode *Node) { |
| 639 InstList &Insts = Node->getInsts(); |
| 640 InstList::reverse_iterator RI, E; |
| 641 for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) { |
| 642 if (llvm::isa<typename Traits::Insts::Ret>(*RI)) |
| 643 break; |
| 644 } |
| 645 if (RI == E) |
| 646 return; |
| 647 |
| 648 // Convert the reverse_iterator position into its corresponding |
| 649 // (forward) iterator position. |
| 650 InstList::iterator InsertPoint = RI.base(); |
| 651 --InsertPoint; |
| 652 Context.init(Node); |
| 653 Context.setInsertPoint(InsertPoint); |
| 654 |
| 655 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 656 if (IsEbpBasedFrame) { |
| 657 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
| 658 // For late-stage liveness analysis (e.g. asm-verbose mode), |
| 659 // adding a fake use of esp before the assignment of esp=ebp keeps |
| 660 // previous esp adjustments from being dead-code eliminated. |
| 661 Context.insert(InstFakeUse::create(Func, esp)); |
| 662 _mov(esp, ebp); |
| 663 _pop(ebp); |
| 664 } else { |
| 665 // add esp, SpillAreaSizeBytes |
| 666 if (SpillAreaSizeBytes) |
| 667 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); |
| 668 } |
| 669 |
| 670 // Add pop instructions for preserved registers. |
| 671 llvm::SmallBitVector CalleeSaves = |
| 672 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 673 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 674 SizeT j = CalleeSaves.size() - i - 1; |
| 675 if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame) |
| 676 continue; |
| 677 if (CalleeSaves[j] && RegsUsed[j]) { |
| 678 _pop(getPhysicalRegister(j)); |
| 679 } |
| 680 } |
| 681 |
| 682 if (!Ctx->getFlags().getUseSandboxing()) |
| 683 return; |
| 684 // Change the original ret instruction into a sandboxed return sequence. |
| 685 // t:ecx = pop |
| 686 // bundle_lock |
| 687 // and t, ~31 |
| 688 // jmp *t |
| 689 // bundle_unlock |
| 690 // FakeUse <original_ret_operand> |
| 691 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
| 692 _pop(T_ecx); |
| 693 lowerIndirectJump(T_ecx); |
| 694 if (RI->getSrcSize()) { |
| 695 Variable *RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 696 Context.insert(InstFakeUse::create(Func, RetValue)); |
| 697 } |
| 698 RI->setDeleted(); |
| 699 } |
| 700 |
| 701 void TargetX8664::emitJumpTable(const Cfg *Func, |
| 702 const InstJumpTable *JumpTable) const { |
| 703 if (!BuildDefs::dump()) |
| 704 return; |
| 705 Ostream &Str = Ctx->getStrEmit(); |
| 706 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| 707 Str << "\t.section\t.rodata." << MangledName |
| 708 << "$jumptable,\"a\",@progbits\n"; |
| 709 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
| 710 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; |
| 711 |
| 712 // On X8664 ILP32 pointers are 32-bit hence the use of .long |
| 713 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) |
| 714 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); |
| 715 Str << "\n"; |
| 370 } | 716 } |
| 371 | 717 |
| 372 namespace { | 718 namespace { |
| 373 template <typename T> struct PoolTypeConverter {}; | 719 template <typename T> struct PoolTypeConverter {}; |
| 374 | 720 |
| 375 template <> struct PoolTypeConverter<float> { | 721 template <> struct PoolTypeConverter<float> { |
| 376 typedef uint32_t PrimitiveIntType; | 722 typedef uint32_t PrimitiveIntType; |
| 377 typedef ConstantFloat IceType; | 723 typedef ConstantFloat IceType; |
| 378 static const Type Ty = IceType_f32; | 724 static const Type Ty = IceType_f32; |
| 379 static const char *TypeName; | 725 static const char *TypeName; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); | 846 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); |
| 501 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | 847 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); |
| 502 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | 848 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); |
| 503 | 849 |
| 504 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 850 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 505 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 851 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 506 } break; | 852 } break; |
| 507 } | 853 } |
| 508 } | 854 } |
| 509 | 855 |
| 510 void TargetX8664::emitJumpTable(const Cfg *Func, | 856 void TargetDataX8664::lowerJumpTables() { |
| 511 const InstJumpTable *JumpTable) const { | 857 switch (Ctx->getFlags().getOutFileType()) { |
| 512 if (!BuildDefs::dump()) | 858 case FT_Elf: { |
| 513 return; | 859 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 514 Ostream &Str = Ctx->getStrEmit(); | 860 for (const JumpTableData &JumpTable : Ctx->getJumpTables()) |
| 515 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 861 // TODO(jpp): not 386. |
| 516 Str << "\t.section\t.rodata." << MangledName | 862 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32); |
| 517 << "$jumptable,\"a\",@progbits\n"; | 863 } break; |
| 518 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 864 case FT_Asm: |
| 519 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; | 865 // Already emitted from Cfg |
| 866 break; |
| 867 case FT_Iasm: { |
| 868 if (!BuildDefs::dump()) |
| 869 return; |
| 870 Ostream &Str = Ctx->getStrEmit(); |
| 871 for (const JumpTableData &JT : Ctx->getJumpTables()) { |
| 872 Str << "\t.section\t.rodata." << JT.getFunctionName() |
| 873 << "$jumptable,\"a\",@progbits\n"; |
| 874 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
| 875 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; |
| 520 | 876 |
| 521 // On X8664 ILP32 pointers are 32-bit hence the use of .long | 877 // On X8664 ILP32 pointers are 32-bit hence the use of .long |
| 522 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | 878 for (intptr_t TargetOffset : JT.getTargetOffsets()) |
| 523 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | 879 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; |
| 524 Str << "\n"; | 880 Str << "\n"; |
| 881 } |
| 882 } break; |
| 883 } |
| 525 } | 884 } |
| 526 | 885 |
| 527 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, | 886 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, |
| 528 const IceString &SectionSuffix) { | 887 const IceString &SectionSuffix) { |
| 529 switch (Ctx->getFlags().getOutFileType()) { | 888 switch (Ctx->getFlags().getOutFileType()) { |
| 530 case FT_Elf: { | 889 case FT_Elf: { |
| 531 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 890 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 532 // TODO(jpp): not 386. | 891 // TODO(jpp): not 386. |
| 533 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix); | 892 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix); |
| 534 } break; | 893 } break; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 // entries in case the high-level table has extra entries. | 1006 // entries in case the high-level table has extra entries. |
| 648 #define X(tag, sizeLog2, align, elts, elty, str) \ | 1007 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 649 static_assert(_table1_##tag == _table2_##tag, \ | 1008 static_assert(_table1_##tag == _table2_##tag, \ |
| 650 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 1009 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 651 ICETYPE_TABLE | 1010 ICETYPE_TABLE |
| 652 #undef X | 1011 #undef X |
| 653 } // end of namespace dummy3 | 1012 } // end of namespace dummy3 |
| 654 } // end of anonymous namespace | 1013 } // end of anonymous namespace |
| 655 | 1014 |
| 656 } // end of namespace Ice | 1015 } // end of namespace Ice |
| OLD | NEW |