OLD | NEW |
1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
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 // This file implements the InstX8632 and OperandX8632 classes, | 10 // This file implements the InstX8632 and OperandX8632 classes, |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { | 482 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
483 (void)Mem; | 483 (void)Mem; |
484 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 484 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
485 llvm::report_fatal_error("Assembler can't jmp to memory operand"); | 485 llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
486 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { | 486 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
487 assert(CR->getOffset() == 0 && "We only support jumping to a function"); | 487 assert(CR->getOffset() == 0 && "We only support jumping to a function"); |
488 Asm->jmp(CR); | 488 Asm->jmp(CR); |
489 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { | 489 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
490 // NaCl trampoline calls refer to an address within the sandbox directly. | 490 // NaCl trampoline calls refer to an address within the sandbox directly. |
491 // This is usually only needed for non-IRT builds and otherwise not | 491 // This is usually only needed for non-IRT builds and otherwise not |
492 // very portable or stable. For this, we would use the 0xE8 opcode | 492 // very portable or stable. Usually this is only done for "calls" |
493 // (relative version of call) and there should be a PC32 reloc too. | 493 // and not jumps. |
494 // The PC32 reloc will have symbol index 0, and the absolute address | 494 // TODO(jvoung): Support this when there is a lowering that |
495 // would be encoded as an offset relative to the next instruction. | 495 // actually triggers this case. |
496 // TODO(jvoung): Do we need to support this? | |
497 (void)Imm; | 496 (void)Imm; |
498 llvm::report_fatal_error("Unexpected jmp to absolute address"); | 497 llvm::report_fatal_error("Unexpected jmp to absolute address"); |
499 } else { | 498 } else { |
500 llvm::report_fatal_error("Unexpected operand type"); | 499 llvm::report_fatal_error("Unexpected operand type"); |
501 } | 500 } |
502 } | 501 } |
503 | 502 |
504 void InstX8632Jmp::dump(const Cfg *Func) const { | 503 void InstX8632Jmp::dump(const Cfg *Func) const { |
505 if (!ALLOW_DUMP) | 504 if (!ALLOW_DUMP) |
506 return; | 505 return; |
507 Ostream &Str = Func->getContext()->getStrDump(); | 506 Ostream &Str = Func->getContext()->getStrDump(); |
508 Str << "jmp "; | 507 Str << "jmp "; |
509 getJmpTarget()->dump(Func); | 508 getJmpTarget()->dump(Func); |
510 } | 509 } |
511 | 510 |
512 void InstX8632Call::emit(const Cfg *Func) const { | 511 void InstX8632Call::emit(const Cfg *Func) const { |
513 if (!ALLOW_DUMP) | 512 if (!ALLOW_DUMP) |
514 return; | 513 return; |
515 Ostream &Str = Func->getContext()->getStrEmit(); | 514 Ostream &Str = Func->getContext()->getStrEmit(); |
516 assert(getSrcSize() == 1); | 515 assert(getSrcSize() == 1); |
517 Str << "\tcall\t"; | 516 Str << "\tcall\t"; |
518 if (const auto CallTarget = | 517 if (const auto CallTarget = llvm::dyn_cast<Constant>(getCallTarget())) { |
519 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { | |
520 // TODO(stichnot): All constant targets should suppress the '$', | |
521 // not just relocatables. | |
522 CallTarget->emitWithoutDollar(Func->getContext()); | 518 CallTarget->emitWithoutDollar(Func->getContext()); |
523 } else { | 519 } else { |
524 Str << "*"; | 520 Str << "*"; |
525 getCallTarget()->emit(Func); | 521 getCallTarget()->emit(Func); |
526 } | 522 } |
527 Func->getTarget()->resetStackAdjustment(); | 523 Func->getTarget()->resetStackAdjustment(); |
528 } | 524 } |
529 | 525 |
530 void InstX8632Call::emitIAS(const Cfg *Func) const { | 526 void InstX8632Call::emitIAS(const Cfg *Func) const { |
531 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 527 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
532 Operand *Target = getCallTarget(); | 528 Operand *Target = getCallTarget(); |
533 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { | 529 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
534 if (Var->hasReg()) { | 530 if (Var->hasReg()) { |
535 Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); | 531 Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); |
536 } else { | 532 } else { |
537 Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) | 533 Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) |
538 ->stackVarToAsmOperand(Var)); | 534 ->stackVarToAsmOperand(Var)); |
539 } | 535 } |
540 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { | 536 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
541 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 537 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
542 Asm->call(Mem->toAsmAddress(Asm)); | 538 Asm->call(Mem->toAsmAddress(Asm)); |
543 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { | 539 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
544 assert(CR->getOffset() == 0 && "We only support calling a function"); | 540 assert(CR->getOffset() == 0 && "We only support calling a function"); |
545 Asm->call(CR); | 541 Asm->call(CR); |
546 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { | 542 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
547 // NaCl trampoline calls refer to an address within the sandbox directly. | 543 Asm->call(x86::Immediate(Imm->getValue())); |
548 // This is usually only needed for non-IRT builds and otherwise not | |
549 // very portable or stable. For this, we would use the 0xE8 opcode | |
550 // (relative version of call) and there should be a PC32 reloc too. | |
551 // The PC32 reloc will have symbol index 0, and the absolute address | |
552 // would be encoded as an offset relative to the next instruction. | |
553 // TODO(jvoung): Do we need to support this? | |
554 (void)Imm; | |
555 llvm_unreachable("Unexpected call to absolute address"); | |
556 } else { | 544 } else { |
557 llvm_unreachable("Unexpected operand type"); | 545 llvm_unreachable("Unexpected operand type"); |
558 } | 546 } |
559 Func->getTarget()->resetStackAdjustment(); | 547 Func->getTarget()->resetStackAdjustment(); |
560 } | 548 } |
561 | 549 |
562 void InstX8632Call::dump(const Cfg *Func) const { | 550 void InstX8632Call::dump(const Cfg *Func) const { |
563 if (!ALLOW_DUMP) | 551 if (!ALLOW_DUMP) |
564 return; | 552 return; |
565 Ostream &Str = Func->getContext()->getStrDump(); | 553 Ostream &Str = Func->getContext()->getStrDump(); |
(...skipping 2370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2936 } | 2924 } |
2937 Str << "("; | 2925 Str << "("; |
2938 if (Func) | 2926 if (Func) |
2939 Var->dump(Func); | 2927 Var->dump(Func); |
2940 else | 2928 else |
2941 Var->dump(Str); | 2929 Var->dump(Str); |
2942 Str << ")"; | 2930 Str << ")"; |
2943 } | 2931 } |
2944 | 2932 |
2945 } // end of namespace Ice | 2933 } // end of namespace Ice |
OLD | NEW |