| 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 TargetX8664::Traits::RegisterSet::Reg_r8d, | 116 TargetX8664::Traits::RegisterSet::Reg_r8d, |
| 117 TargetX8664::Traits::RegisterSet::Reg_r9d, | 117 TargetX8664::Traits::RegisterSet::Reg_r9d, |
| 118 }; | 118 }; |
| 119 static_assert(llvm::array_lengthof(GprForArgNum) == | 119 static_assert(llvm::array_lengthof(GprForArgNum) == |
| 120 TargetX8664::TargetX8664::Traits::X86_MAX_GPR_ARGS, | 120 TargetX8664::TargetX8664::Traits::X86_MAX_GPR_ARGS, |
| 121 "Mismatch between MAX_GPR_ARGS and GprForArgNum."); | 121 "Mismatch between MAX_GPR_ARGS and GprForArgNum."); |
| 122 return GprForArgNum[ArgNum]; | 122 return GprForArgNum[ArgNum]; |
| 123 } | 123 } |
| 124 | 124 |
| 125 // constexprMax returns a (constexpr) max(S0, S1), and it is used for defining | 125 // constexprMax returns a (constexpr) max(S0, S1), and it is used for defining |
| 126 // OperandList in lowerCall. std::max() was supposed to work, but it doesn't. | 126 // OperandList in lowerCall. std::max() is supposed to work, but it doesn't. |
| 127 constexpr SizeT constexprMax(SizeT S0, SizeT S1) { return S0 < S1 ? S1 : S0; } | 127 constexpr SizeT constexprMax(SizeT S0, SizeT S1) { return S0 < S1 ? S1 : S0; } |
| 128 | 128 |
| 129 } // end of anonymous namespace | 129 } // end of anonymous namespace |
| 130 | 130 |
| 131 void TargetX8664::lowerCall(const InstCall *Instr) { | 131 void TargetX8664::lowerCall(const InstCall *Instr) { |
| 132 // x86-64 calling convention: | 132 // x86-64 calling convention: |
| 133 // | 133 // |
| 134 // * At the point before the call, the stack must be aligned to 16 | 134 // * At the point before the call, the stack must be aligned to 16 |
| 135 // bytes. | 135 // bytes. |
| 136 // | 136 // |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { | 232 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { |
| 233 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i)); | 233 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i)); |
| 234 Context.insert(InstFakeUse::create(Func, Reg)); | 234 Context.insert(InstFakeUse::create(Func, Reg)); |
| 235 } | 235 } |
| 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; | |
| 243 if (Dest) { | 242 if (Dest) { |
| 244 switch (Dest->getType()) { | 243 switch (Dest->getType()) { |
| 245 case IceType_NUM: | 244 case IceType_NUM: |
| 246 case IceType_void: | 245 case IceType_void: |
| 247 llvm::report_fatal_error("Invalid Call dest type"); | 246 llvm::report_fatal_error("Invalid Call dest type"); |
| 248 break; | 247 break; |
| 249 case IceType_i1: | 248 case IceType_i1: |
| 250 case IceType_i8: | 249 case IceType_i8: |
| 251 case IceType_i16: | 250 case IceType_i16: |
| 252 case IceType_i32: | 251 case IceType_i32: |
| 252 case IceType_i64: |
| 253 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); | 253 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); |
| 254 break; | 254 break; |
| 255 case IceType_i64: | |
| 256 // TODO(jpp): return i64 in a GPR. | |
| 257 ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax); | |
| 258 ReturnRegHi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx); | |
| 259 break; | |
| 260 case IceType_f32: | 255 case IceType_f32: |
| 261 case IceType_f64: | 256 case IceType_f64: |
| 262 case IceType_v4i1: | 257 case IceType_v4i1: |
| 263 case IceType_v8i1: | 258 case IceType_v8i1: |
| 264 case IceType_v16i1: | 259 case IceType_v16i1: |
| 265 case IceType_v16i8: | 260 case IceType_v16i8: |
| 266 case IceType_v8i16: | 261 case IceType_v8i16: |
| 267 case IceType_v4i32: | 262 case IceType_v4i32: |
| 268 case IceType_v4f32: | 263 case IceType_v4f32: |
| 269 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); | 264 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); |
| 270 break; | 265 break; |
| 271 } | 266 } |
| 272 } | 267 } |
| 273 | 268 |
| 274 Operand *CallTarget = legalize(Instr->getCallTarget()); | 269 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); |
| 275 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 270 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
| 276 if (NeedSandboxing) { | 271 if (NeedSandboxing) { |
| 277 if (llvm::isa<Constant>(CallTarget)) { | 272 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 278 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | |
| 279 } else { | |
| 280 Variable *CallTargetVar = nullptr; | |
| 281 _mov(CallTargetVar, CallTarget); | |
| 282 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | |
| 283 const SizeT BundleSize = | |
| 284 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | |
| 285 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); | |
| 286 CallTarget = CallTargetVar; | |
| 287 } | |
| 288 } | 273 } |
| 289 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); | 274 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); |
| 290 Context.insert(NewCall); | 275 Context.insert(NewCall); |
| 291 if (NeedSandboxing) | 276 if (NeedSandboxing) { |
| 292 _bundle_unlock(); | 277 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 293 if (ReturnRegHi) | 278 } |
| 294 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | |
| 295 | 279 |
| 296 // Add the appropriate offset to esp. The call instruction takes care | 280 // Add the appropriate offset to esp. The call instruction takes care |
| 297 // of resetting the stack offset during emission. | 281 // of resetting the stack offset during emission. |
| 298 if (ParameterAreaSizeBytes) { | 282 if (ParameterAreaSizeBytes) { |
| 299 Variable *Esp = | 283 Variable *Esp = |
| 300 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 284 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 301 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); | 285 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); |
| 302 } | 286 } |
| 303 | 287 |
| 304 // Insert a register-kill pseudo instruction. | 288 // Insert a register-kill pseudo instruction. |
| 305 Context.insert(InstFakeKill::create(Func, NewCall)); | 289 Context.insert(InstFakeKill::create(Func, NewCall)); |
| 306 | 290 |
| 307 // Generate a FakeUse to keep the call live if necessary. | 291 // Generate a FakeUse to keep the call live if necessary. |
| 308 if (Instr->hasSideEffects() && ReturnReg) { | 292 if (Instr->hasSideEffects() && ReturnReg) { |
| 309 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 293 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
| 310 Context.insert(FakeUse); | 294 Context.insert(FakeUse); |
| 311 } | 295 } |
| 312 | 296 |
| 313 if (!Dest) | 297 if (!Dest) |
| 314 return; | 298 return; |
| 315 | 299 |
| 316 assert(ReturnReg && "x86-64 always returns value on registers."); | 300 assert(ReturnReg && "x86-64 always returns value on registers."); |
| 317 | 301 |
| 318 // Assign the result of the call to Dest. | 302 if (isVectorType(Dest->getType())) { |
| 319 if (ReturnRegHi) { | |
| 320 assert(Dest->getType() == IceType_i64); | |
| 321 split64(Dest); | |
| 322 Variable *DestLo = Dest->getLo(); | |
| 323 Variable *DestHi = Dest->getHi(); | |
| 324 _mov(DestLo, ReturnReg); | |
| 325 _mov(DestHi, ReturnRegHi); | |
| 326 return; | |
| 327 } | |
| 328 | |
| 329 assert(Dest->getType() == IceType_f32 || Dest->getType() == IceType_f64 || | |
| 330 Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || | |
| 331 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | |
| 332 isVectorType(Dest->getType())); | |
| 333 | |
| 334 if (isScalarFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | |
| 335 _movp(Dest, ReturnReg); | 303 _movp(Dest, ReturnReg); |
| 336 } else { | 304 } else { |
| 305 assert(isScalarFloatingType(Dest->getType()) || |
| 306 isScalarIntegerType(Dest->getType())); |
| 337 _mov(Dest, ReturnReg); | 307 _mov(Dest, ReturnReg); |
| 338 } | 308 } |
| 339 } | 309 } |
| 340 | 310 |
| 341 void TargetX8664::lowerArguments() { | 311 void TargetX8664::lowerArguments() { |
| 342 VarList &Args = Func->getArgs(); | 312 VarList &Args = Func->getArgs(); |
| 343 // The first eight vetcor typed arguments (as well as fp arguments) are passed | 313 // The first eight vetcor typed arguments (as well as fp arguments) are passed |
| 344 // in %xmm0 through %xmm7 regardless of their position in the argument list. | 314 // in %xmm0 through %xmm7 regardless of their position in the argument list. |
| 345 unsigned NumXmmArgs = 0; | 315 unsigned NumXmmArgs = 0; |
| 346 // The first six integer typed arguments are passed in %rdi, %rsi, %rdx, %rcx, | 316 // The first six integer typed arguments are passed in %rdi, %rsi, %rdx, %rcx, |
| 347 // %r8, and %r9 regardless of their position in the argument list. | 317 // %r8, and %r9 regardless of their position in the argument list. |
| 348 unsigned NumGprArgs = 0; | 318 unsigned NumGprArgs = 0; |
| 349 | 319 |
| 350 Context.init(Func->getEntryNode()); | 320 Context.init(Func->getEntryNode()); |
| 351 Context.setInsertPoint(Context.getCur()); | 321 Context.setInsertPoint(Context.getCur()); |
| 352 | 322 |
| 353 for (SizeT i = 0, End = Args.size(); | 323 for (SizeT i = 0, End = Args.size(); |
| 354 i < End && (NumXmmArgs < Traits::X86_MAX_XMM_ARGS || | 324 i < End && (NumXmmArgs < Traits::X86_MAX_XMM_ARGS || |
| 355 NumGprArgs < Traits::X86_MAX_XMM_ARGS); | 325 NumGprArgs < Traits::X86_MAX_XMM_ARGS); |
| 356 ++i) { | 326 ++i) { |
| 357 Variable *Arg = Args[i]; | 327 Variable *Arg = Args[i]; |
| 358 Type Ty = Arg->getType(); | 328 Type Ty = Arg->getType(); |
| 359 if ((isVectorType(Ty) || isScalarFloatingType(Ty)) && | 329 Variable *RegisterArg = nullptr; |
| 360 NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | 330 int32_t RegNum = Variable::NoRegister; |
| 361 // Replace Arg in the argument list with the home register. Then | 331 if ((isVectorType(Ty) || isScalarFloatingType(Ty))) { |
| 362 // generate an instruction in the prolog to copy the home register | 332 if (NumXmmArgs >= Traits::X86_MAX_XMM_ARGS) { |
| 363 // to the assigned location of Arg. | 333 continue; |
| 364 int32_t RegNum = getRegisterForXmmArgNum(NumXmmArgs); | 334 } |
| 335 RegNum = getRegisterForXmmArgNum(NumXmmArgs); |
| 365 ++NumXmmArgs; | 336 ++NumXmmArgs; |
| 366 Variable *RegisterArg = Func->makeVariable(Ty); | 337 RegisterArg = Func->makeVariable(Ty); |
| 367 if (BuildDefs::dump()) | 338 } else if (isScalarIntegerType(Ty)) { |
| 368 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 339 if (NumGprArgs >= Traits::X86_MAX_GPR_ARGS) { |
| 369 RegisterArg->setRegNum(RegNum); | 340 continue; |
| 370 RegisterArg->setIsArg(); | 341 } |
| 371 Arg->setIsArg(false); | 342 RegNum = getRegisterForGprArgNum(NumGprArgs); |
| 343 ++NumGprArgs; |
| 344 RegisterArg = Func->makeVariable(Ty); |
| 345 } |
| 346 assert(RegNum != Variable::NoRegister); |
| 347 assert(RegisterArg != nullptr); |
| 348 // Replace Arg in the argument list with the home register. Then |
| 349 // generate an instruction in the prolog to copy the home register |
| 350 // to the assigned location of Arg. |
| 351 if (BuildDefs::dump()) |
| 352 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 353 RegisterArg->setRegNum(RegNum); |
| 354 RegisterArg->setIsArg(); |
| 355 Arg->setIsArg(false); |
| 372 | 356 |
| 373 Args[i] = RegisterArg; | 357 Args[i] = RegisterArg; |
| 374 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 358 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 } | 359 } |
| 390 } | 360 } |
| 391 | 361 |
| 392 void TargetX8664::lowerRet(const InstRet *Inst) { | 362 void TargetX8664::lowerRet(const InstRet *Inst) { |
| 393 Variable *Reg = nullptr; | 363 Variable *Reg = nullptr; |
| 394 if (Inst->hasRetValue()) { | 364 if (Inst->hasRetValue()) { |
| 395 Operand *Src0 = legalize(Inst->getRetValue()); | 365 Operand *Src0 = legalize(Inst->getRetValue()); |
| 396 // TODO(jpp): this is not needed. | 366 if (isVectorType(Src0->getType()) || |
| 397 if (Src0->getType() == IceType_i64) { | 367 isScalarFloatingType(Src0->getType())) { |
| 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); | 368 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); |
| 408 } else { | 369 } else { |
| 370 assert(isScalarIntegerType(Src0->getType())); |
| 409 _mov(Reg, Src0, Traits::RegisterSet::Reg_eax); | 371 _mov(Reg, Src0, Traits::RegisterSet::Reg_eax); |
| 410 } | 372 } |
| 411 } | 373 } |
| 412 // Add a ret instruction even if sandboxing is enabled, because | 374 // Add a ret instruction even if sandboxing is enabled, because |
| 413 // addEpilog explicitly looks for a ret instruction as a marker for | 375 // addEpilog explicitly looks for a ret instruction as a marker for |
| 414 // where to insert the frame removal instructions. | 376 // where to insert the frame removal instructions. |
| 415 _ret(Reg); | 377 _ret(Reg); |
| 416 // Add a fake use of esp to make sure esp stays alive for the entire | 378 // 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 | 379 // function. Otherwise post-call esp adjustments get dead-code |
| 418 // eliminated. TODO: Are there more places where the fake use | 380 // eliminated. TODO: Are there more places where the fake use |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; | 532 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; |
| 571 if (!IsEbpBasedFrame) | 533 if (!IsEbpBasedFrame) |
| 572 BasicFrameOffset += SpillAreaSizeBytes; | 534 BasicFrameOffset += SpillAreaSizeBytes; |
| 573 | 535 |
| 574 const VarList &Args = Func->getArgs(); | 536 const VarList &Args = Func->getArgs(); |
| 575 size_t InArgsSizeBytes = 0; | 537 size_t InArgsSizeBytes = 0; |
| 576 unsigned NumXmmArgs = 0; | 538 unsigned NumXmmArgs = 0; |
| 577 unsigned NumGPRArgs = 0; | 539 unsigned NumGPRArgs = 0; |
| 578 for (Variable *Arg : Args) { | 540 for (Variable *Arg : Args) { |
| 579 // Skip arguments passed in registers. | 541 // Skip arguments passed in registers. |
| 580 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | 542 if (isVectorType(Arg->getType()) || isScalarFloatingType(Arg->getType())) { |
| 581 ++NumXmmArgs; | 543 if (NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { |
| 582 continue; | 544 ++NumXmmArgs; |
| 583 } | 545 continue; |
| 584 if (isScalarFloatingType(Arg->getType()) && | 546 } |
| 585 NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | 547 } else { |
| 586 ++NumXmmArgs; | 548 assert(isScalarIntegerType(Arg->getType())); |
| 587 continue; | 549 if (NumGPRArgs < Traits::X86_MAX_GPR_ARGS) { |
| 588 } | 550 ++NumGPRArgs; |
| 589 if (isScalarIntegerType(Arg->getType()) && | 551 continue; |
| 590 NumGPRArgs < Traits::X86_MAX_GPR_ARGS) { | 552 } |
| 591 ++NumGPRArgs; | |
| 592 continue; | |
| 593 } | 553 } |
| 594 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 554 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 595 } | 555 } |
| 596 | 556 |
| 597 // Fill in stack offsets for locals. | 557 // Fill in stack offsets for locals. |
| 598 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | 558 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
| 599 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | 559 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
| 600 IsEbpBasedFrame); | 560 IsEbpBasedFrame); |
| 601 // Assign stack offsets to variables that have been linked to spilled | 561 // Assign stack offsets to variables that have been linked to spilled |
| 602 // variables. | 562 // variables. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 632 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 673 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 633 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 674 SizeT j = CalleeSaves.size() - i - 1; | 634 SizeT j = CalleeSaves.size() - i - 1; |
| 675 if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame) | 635 if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame) |
| 676 continue; | 636 continue; |
| 677 if (CalleeSaves[j] && RegsUsed[j]) { | 637 if (CalleeSaves[j] && RegsUsed[j]) { |
| 678 _pop(getPhysicalRegister(j)); | 638 _pop(getPhysicalRegister(j)); |
| 679 } | 639 } |
| 680 } | 640 } |
| 681 | 641 |
| 682 if (!Ctx->getFlags().getUseSandboxing()) | 642 if (Ctx->getFlags().getUseSandboxing()) { |
| 683 return; | 643 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 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 } | 644 } |
| 698 RI->setDeleted(); | |
| 699 } | 645 } |
| 700 | 646 |
| 701 void TargetX8664::emitJumpTable(const Cfg *Func, | 647 void TargetX8664::emitJumpTable(const Cfg *Func, |
| 702 const InstJumpTable *JumpTable) const { | 648 const InstJumpTable *JumpTable) const { |
| 703 if (!BuildDefs::dump()) | 649 if (!BuildDefs::dump()) |
| 704 return; | 650 return; |
| 705 Ostream &Str = Ctx->getStrEmit(); | 651 Ostream &Str = Ctx->getStrEmit(); |
| 706 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 652 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| 707 Str << "\t.section\t.rodata." << MangledName | 653 Str << "\t.section\t.rodata." << MangledName |
| 708 << "$jumptable,\"a\",@progbits\n"; | 654 << "$jumptable,\"a\",@progbits\n"; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 797 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 852 } break; | 798 } break; |
| 853 } | 799 } |
| 854 } | 800 } |
| 855 | 801 |
| 856 void TargetDataX8664::lowerJumpTables() { | 802 void TargetDataX8664::lowerJumpTables() { |
| 857 switch (Ctx->getFlags().getOutFileType()) { | 803 switch (Ctx->getFlags().getOutFileType()) { |
| 858 case FT_Elf: { | 804 case FT_Elf: { |
| 859 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 805 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 860 for (const JumpTableData &JumpTable : Ctx->getJumpTables()) | 806 for (const JumpTableData &JumpTable : Ctx->getJumpTables()) |
| 861 // TODO(jpp): not 386. | 807 Writer->writeJumpTable(JumpTable, TargetX8664::Traits::RelFixup); |
| 862 Writer->writeJumpTable(JumpTable, llvm::ELF::R_386_32); | |
| 863 } break; | 808 } break; |
| 864 case FT_Asm: | 809 case FT_Asm: |
| 865 // Already emitted from Cfg | 810 // Already emitted from Cfg |
| 866 break; | 811 break; |
| 867 case FT_Iasm: { | 812 case FT_Iasm: { |
| 868 if (!BuildDefs::dump()) | 813 if (!BuildDefs::dump()) |
| 869 return; | 814 return; |
| 870 Ostream &Str = Ctx->getStrEmit(); | 815 Ostream &Str = Ctx->getStrEmit(); |
| 871 for (const JumpTableData &JT : Ctx->getJumpTables()) { | 816 for (const JumpTableData &JT : Ctx->getJumpTables()) { |
| 872 Str << "\t.section\t.rodata." << JT.getFunctionName() | 817 Str << "\t.section\t.rodata." << JT.getFunctionName() |
| 873 << "$jumptable,\"a\",@progbits\n"; | 818 << "$jumptable,\"a\",@progbits\n"; |
| 874 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 819 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
| 875 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | 820 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; |
| 876 | 821 |
| 877 // On X8664 ILP32 pointers are 32-bit hence the use of .long | 822 // On X8664 ILP32 pointers are 32-bit hence the use of .long |
| 878 for (intptr_t TargetOffset : JT.getTargetOffsets()) | 823 for (intptr_t TargetOffset : JT.getTargetOffsets()) |
| 879 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | 824 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; |
| 880 Str << "\n"; | 825 Str << "\n"; |
| 881 } | 826 } |
| 882 } break; | 827 } break; |
| 883 } | 828 } |
| 884 } | 829 } |
| 885 | 830 |
| 886 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, | 831 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars, |
| 887 const IceString &SectionSuffix) { | 832 const IceString &SectionSuffix) { |
| 888 switch (Ctx->getFlags().getOutFileType()) { | 833 switch (Ctx->getFlags().getOutFileType()) { |
| 889 case FT_Elf: { | 834 case FT_Elf: { |
| 890 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 835 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 891 // TODO(jpp): not 386. | 836 Writer->writeDataSection(Vars, TargetX8664::Traits::RelFixup, |
| 892 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix); | 837 SectionSuffix); |
| 893 } break; | 838 } break; |
| 894 case FT_Asm: | 839 case FT_Asm: |
| 895 case FT_Iasm: { | 840 case FT_Iasm: { |
| 896 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 841 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); |
| 897 OstreamLocker L(Ctx); | 842 OstreamLocker L(Ctx); |
| 898 for (const VariableDeclaration *Var : Vars) { | 843 for (const VariableDeclaration *Var : Vars) { |
| 899 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 844 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
| 900 emitGlobal(*Var, SectionSuffix); | 845 emitGlobal(*Var, SectionSuffix); |
| 901 } | 846 } |
| 902 } | 847 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1006 // entries in case the high-level table has extra entries. | 951 // entries in case the high-level table has extra entries. |
| 1007 #define X(tag, sizeLog2, align, elts, elty, str) \ | 952 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 1008 static_assert(_table1_##tag == _table2_##tag, \ | 953 static_assert(_table1_##tag == _table2_##tag, \ |
| 1009 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 954 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 1010 ICETYPE_TABLE | 955 ICETYPE_TABLE |
| 1011 #undef X | 956 #undef X |
| 1012 } // end of namespace dummy3 | 957 } // end of namespace dummy3 |
| 1013 } // end of anonymous namespace | 958 } // end of anonymous namespace |
| 1014 | 959 |
| 1015 } // end of namespace Ice | 960 } // end of namespace Ice |
| OLD | NEW |