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