| 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 //------------------------------------------------------------------------------ | 111 //------------------------------------------------------------------------------ |
| 112 namespace { | 112 namespace { |
| 113 static inline TargetX8664::Traits::RegisterSet::AllRegisters | 113 static inline TargetX8664::Traits::RegisterSet::AllRegisters |
| 114 getRegisterForXmmArgNum(uint32_t ArgNum) { | 114 getRegisterForXmmArgNum(uint32_t ArgNum) { |
| 115 assert(ArgNum < TargetX8664::Traits::X86_MAX_XMM_ARGS); | 115 assert(ArgNum < TargetX8664::Traits::X86_MAX_XMM_ARGS); |
| 116 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>( | 116 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>( |
| 117 TargetX8664::Traits::RegisterSet::Reg_xmm0 + ArgNum); | 117 TargetX8664::Traits::RegisterSet::Reg_xmm0 + ArgNum); |
| 118 } | 118 } |
| 119 | 119 |
| 120 static inline TargetX8664::Traits::RegisterSet::AllRegisters | 120 static inline TargetX8664::Traits::RegisterSet::AllRegisters |
| 121 getRegisterForGprArgNum(uint32_t ArgNum) { | 121 getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { |
| 122 assert(ArgNum < TargetX8664::Traits::X86_MAX_GPR_ARGS); | 122 assert(ArgNum < TargetX8664::Traits::X86_MAX_GPR_ARGS); |
| 123 static const TargetX8664::Traits::RegisterSet::AllRegisters GprForArgNum[] = { | 123 static const TargetX8664::Traits::RegisterSet::AllRegisters GprForArgNum[] = { |
| 124 TargetX8664::Traits::RegisterSet::Reg_edi, | 124 TargetX8664::Traits::RegisterSet::Reg_rdi, |
| 125 TargetX8664::Traits::RegisterSet::Reg_esi, | 125 TargetX8664::Traits::RegisterSet::Reg_rsi, |
| 126 TargetX8664::Traits::RegisterSet::Reg_edx, | 126 TargetX8664::Traits::RegisterSet::Reg_rdx, |
| 127 TargetX8664::Traits::RegisterSet::Reg_ecx, | 127 TargetX8664::Traits::RegisterSet::Reg_rcx, |
| 128 TargetX8664::Traits::RegisterSet::Reg_r8d, | 128 TargetX8664::Traits::RegisterSet::Reg_r8, |
| 129 TargetX8664::Traits::RegisterSet::Reg_r9d, | 129 TargetX8664::Traits::RegisterSet::Reg_r9, |
| 130 }; | 130 }; |
| 131 static_assert(llvm::array_lengthof(GprForArgNum) == | 131 static_assert(llvm::array_lengthof(GprForArgNum) == |
| 132 TargetX8664::TargetX8664::Traits::X86_MAX_GPR_ARGS, | 132 TargetX8664::TargetX8664::Traits::X86_MAX_GPR_ARGS, |
| 133 "Mismatch between MAX_GPR_ARGS and GprForArgNum."); | 133 "Mismatch between MAX_GPR_ARGS and GprForArgNum."); |
| 134 return GprForArgNum[ArgNum]; | 134 assert(Ty == IceType_i64 || Ty == IceType_i32); |
| 135 return static_cast<TargetX8664::Traits::RegisterSet::AllRegisters>( |
| 136 TargetX8664::Traits::getGprForType(Ty, GprForArgNum[ArgNum])); |
| 135 } | 137 } |
| 136 | 138 |
| 137 // constexprMax returns a (constexpr) max(S0, S1), and it is used for defining | 139 // constexprMax returns a (constexpr) max(S0, S1), and it is used for defining |
| 138 // OperandList in lowerCall. std::max() is supposed to work, but it doesn't. | 140 // OperandList in lowerCall. std::max() is supposed to work, but it doesn't. |
| 139 constexpr SizeT constexprMax(SizeT S0, SizeT S1) { return S0 < S1 ? S1 : S0; } | 141 constexpr SizeT constexprMax(SizeT S0, SizeT S1) { return S0 < S1 ? S1 : S0; } |
| 140 | 142 |
| 141 } // end of anonymous namespace | 143 } // end of anonymous namespace |
| 142 | 144 |
| 143 void TargetX8664::lowerCall(const InstCall *Instr) { | 145 void TargetX8664::lowerCall(const InstCall *Instr) { |
| 144 // x86-64 calling convention: | 146 // x86-64 calling convention: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 161 // multiple of 16 bytes. Other stack arguments are aligned to 8 bytes. | 163 // multiple of 16 bytes. Other stack arguments are aligned to 8 bytes. |
| 162 // | 164 // |
| 163 // This intends to match the section "Function Calling Sequence" of the | 165 // This intends to match the section "Function Calling Sequence" of the |
| 164 // document "System V Application Binary Interface." | 166 // document "System V Application Binary Interface." |
| 165 NeedsStackAlignment = true; | 167 NeedsStackAlignment = true; |
| 166 | 168 |
| 167 using OperandList = | 169 using OperandList = |
| 168 llvm::SmallVector<Operand *, constexprMax(Traits::X86_MAX_XMM_ARGS, | 170 llvm::SmallVector<Operand *, constexprMax(Traits::X86_MAX_XMM_ARGS, |
| 169 Traits::X86_MAX_GPR_ARGS)>; | 171 Traits::X86_MAX_GPR_ARGS)>; |
| 170 OperandList XmmArgs; | 172 OperandList XmmArgs; |
| 171 OperandList GprArgs; | 173 CfgVector<std::pair<const Type, Operand *>> GprArgs; |
| 172 OperandList StackArgs, StackArgLocations; | 174 OperandList StackArgs, StackArgLocations; |
| 173 int32_t ParameterAreaSizeBytes = 0; | 175 int32_t ParameterAreaSizeBytes = 0; |
| 174 | 176 |
| 175 // Classify each argument operand according to the location where the | 177 // Classify each argument operand according to the location where the |
| 176 // argument is passed. | 178 // argument is passed. |
| 177 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 179 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
| 178 Operand *Arg = Instr->getArg(i); | 180 Operand *Arg = Instr->getArg(i); |
| 179 Type Ty = Arg->getType(); | 181 Type Ty = Arg->getType(); |
| 180 // The PNaCl ABI requires the width of arguments to be at least 32 bits. | 182 // The PNaCl ABI requires the width of arguments to be at least 32 bits. |
| 181 assert(typeWidthInBytes(Ty) >= 4); | 183 assert(typeWidthInBytes(Ty) >= 4); |
| 182 if (isVectorType(Ty) && XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) { | 184 if (isVectorType(Ty) && XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) { |
| 183 XmmArgs.push_back(Arg); | 185 XmmArgs.push_back(Arg); |
| 184 } else if (isScalarFloatingType(Ty) && | 186 } else if (isScalarFloatingType(Ty) && |
| 185 XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) { | 187 XmmArgs.size() < Traits::X86_MAX_XMM_ARGS) { |
| 186 XmmArgs.push_back(Arg); | 188 XmmArgs.push_back(Arg); |
| 187 } else if (isScalarIntegerType(Ty) && | 189 } else if (isScalarIntegerType(Ty) && |
| 188 GprArgs.size() < Traits::X86_MAX_GPR_ARGS) { | 190 GprArgs.size() < Traits::X86_MAX_GPR_ARGS) { |
| 189 GprArgs.push_back(Arg); | 191 GprArgs.emplace_back(Ty, Arg); |
| 190 } else { | 192 } else { |
| 191 StackArgs.push_back(Arg); | 193 StackArgs.push_back(Arg); |
| 192 if (isVectorType(Arg->getType())) { | 194 if (isVectorType(Arg->getType())) { |
| 193 ParameterAreaSizeBytes = | 195 ParameterAreaSizeBytes = |
| 194 Traits::applyStackAlignment(ParameterAreaSizeBytes); | 196 Traits::applyStackAlignment(ParameterAreaSizeBytes); |
| 195 } | 197 } |
| 196 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_rsp); | 198 Variable *esp = |
| 199 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); |
| 197 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); | 200 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); |
| 198 StackArgLocations.push_back( | 201 StackArgLocations.push_back( |
| 199 Traits::X86OperandMem::create(Func, Ty, esp, Loc)); | 202 Traits::X86OperandMem::create(Func, Ty, esp, Loc)); |
| 200 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); | 203 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); |
| 201 } | 204 } |
| 202 } | 205 } |
| 203 | 206 |
| 204 // Adjust the parameter area so that the stack is aligned. It is assumed that | 207 // Adjust the parameter area so that the stack is aligned. It is assumed that |
| 205 // the stack is already aligned at the start of the calling sequence. | 208 // the stack is already aligned at the start of the calling sequence. |
| 206 ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes); | 209 ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 223 // done. | 226 // done. |
| 224 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { | 227 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { |
| 225 Variable *Reg = legalizeToReg(XmmArgs[i], getRegisterForXmmArgNum(i)); | 228 Variable *Reg = legalizeToReg(XmmArgs[i], getRegisterForXmmArgNum(i)); |
| 226 // Generate a FakeUse of register arguments so that they do not get dead | 229 // Generate a FakeUse of register arguments so that they do not get dead |
| 227 // code eliminated as a result of the FakeKill of scratch registers after | 230 // code eliminated as a result of the FakeKill of scratch registers after |
| 228 // the call. | 231 // the call. |
| 229 Context.insert<InstFakeUse>(Reg); | 232 Context.insert<InstFakeUse>(Reg); |
| 230 } | 233 } |
| 231 | 234 |
| 232 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { | 235 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { |
| 233 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i)); | 236 const Type SignatureTy = GprArgs[i].first; |
| 237 Operand *Arg = GprArgs[i].second; |
| 238 Variable *Reg = |
| 239 legalizeToReg(Arg, getRegisterForGprArgNum(Arg->getType(), i)); |
| 240 assert(SignatureTy == IceType_i64 || SignatureTy == IceType_i32); |
| 241 if (SignatureTy != Arg->getType()) { |
| 242 if (SignatureTy == IceType_i32) { |
| 243 assert(Arg->getType() == IceType_i64); |
| 244 Variable *T = makeReg( |
| 245 IceType_i32, Traits::getGprForType(IceType_i32, Reg->getRegNum())); |
| 246 _mov(T, Reg); |
| 247 Reg = T; |
| 248 } else { |
| 249 // This branch has never been reached, so we leave the assert(false) |
| 250 // here until we figure out how to exercise it. |
| 251 assert(false); |
| 252 assert(Arg->getType() == IceType_i32); |
| 253 Variable *T = makeReg( |
| 254 IceType_i64, Traits::getGprForType(IceType_i64, Reg->getRegNum())); |
| 255 _movzx(T, Reg); |
| 256 Reg = T; |
| 257 } |
| 258 } |
| 234 Context.insert<InstFakeUse>(Reg); | 259 Context.insert<InstFakeUse>(Reg); |
| 235 } | 260 } |
| 236 | 261 |
| 237 // Generate the call instruction. Assign its result to a temporary with high | 262 // Generate the call instruction. Assign its result to a temporary with high |
| 238 // register allocation weight. | 263 // register allocation weight. |
| 239 Variable *Dest = Instr->getDest(); | 264 Variable *Dest = Instr->getDest(); |
| 240 // ReturnReg doubles as ReturnRegLo as necessary. | 265 // ReturnReg doubles as ReturnRegLo as necessary. |
| 241 Variable *ReturnReg = nullptr; | 266 Variable *ReturnReg = nullptr; |
| 242 if (Dest) { | 267 if (Dest) { |
| 243 switch (Dest->getType()) { | 268 switch (Dest->getType()) { |
| 244 case IceType_NUM: | 269 case IceType_NUM: |
| 245 case IceType_void: | 270 case IceType_void: |
| 246 llvm::report_fatal_error("Invalid Call dest type"); | 271 llvm::report_fatal_error("Invalid Call dest type"); |
| 247 break; | 272 break; |
| 248 case IceType_i1: | 273 case IceType_i1: |
| 249 case IceType_i8: | 274 case IceType_i8: |
| 250 case IceType_i16: | 275 case IceType_i16: |
| 276 // The bitcode should never return an i1, i8, or i16. |
| 277 assert(false); |
| 278 // Fallthrough intended. |
| 251 case IceType_i32: | 279 case IceType_i32: |
| 280 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); |
| 281 break; |
| 252 case IceType_i64: | 282 case IceType_i64: |
| 253 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax); | 283 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_rax); |
| 254 break; | 284 break; |
| 255 case IceType_f32: | 285 case IceType_f32: |
| 256 case IceType_f64: | 286 case IceType_f64: |
| 257 case IceType_v4i1: | 287 case IceType_v4i1: |
| 258 case IceType_v8i1: | 288 case IceType_v8i1: |
| 259 case IceType_v16i1: | 289 case IceType_v16i1: |
| 260 case IceType_v16i8: | 290 case IceType_v16i8: |
| 261 case IceType_v8i16: | 291 case IceType_v8i16: |
| 262 case IceType_v4i32: | 292 case IceType_v4i32: |
| 263 case IceType_v4f32: | 293 case IceType_v4f32: |
| 264 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); | 294 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); |
| 265 break; | 295 break; |
| 266 } | 296 } |
| 267 } | 297 } |
| 268 | 298 |
| 269 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); | 299 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); |
| 300 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { |
| 301 // x86-64 in Subzero is ILP32. Therefore, CallTarget is i32, but the emitted |
| 302 // call needs a i64 register (for textual asm.) |
| 303 Variable *T = makeReg(IceType_i64); |
| 304 _movzx(T, CallTargetR); |
| 305 CallTarget = T; |
| 306 } |
| 270 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 307 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
| 271 if (NeedSandboxing) { | 308 if (NeedSandboxing) { |
| 272 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 309 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 273 } | 310 } |
| 274 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); | 311 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); |
| 275 if (NeedSandboxing) { | 312 if (NeedSandboxing) { |
| 276 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 313 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 277 } | 314 } |
| 278 | 315 |
| 279 // Insert a register-kill pseudo instruction. | 316 // Insert a register-kill pseudo instruction. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 if (NumXmmArgs >= Traits::X86_MAX_XMM_ARGS) { | 360 if (NumXmmArgs >= Traits::X86_MAX_XMM_ARGS) { |
| 324 continue; | 361 continue; |
| 325 } | 362 } |
| 326 RegNum = getRegisterForXmmArgNum(NumXmmArgs); | 363 RegNum = getRegisterForXmmArgNum(NumXmmArgs); |
| 327 ++NumXmmArgs; | 364 ++NumXmmArgs; |
| 328 RegisterArg = Func->makeVariable(Ty); | 365 RegisterArg = Func->makeVariable(Ty); |
| 329 } else if (isScalarIntegerType(Ty)) { | 366 } else if (isScalarIntegerType(Ty)) { |
| 330 if (NumGprArgs >= Traits::X86_MAX_GPR_ARGS) { | 367 if (NumGprArgs >= Traits::X86_MAX_GPR_ARGS) { |
| 331 continue; | 368 continue; |
| 332 } | 369 } |
| 333 RegNum = getRegisterForGprArgNum(NumGprArgs); | 370 RegNum = getRegisterForGprArgNum(Ty, NumGprArgs); |
| 334 ++NumGprArgs; | 371 ++NumGprArgs; |
| 335 RegisterArg = Func->makeVariable(Ty); | 372 RegisterArg = Func->makeVariable(Ty); |
| 336 } | 373 } |
| 337 assert(RegNum != Variable::NoRegister); | 374 assert(RegNum != Variable::NoRegister); |
| 338 assert(RegisterArg != nullptr); | 375 assert(RegisterArg != nullptr); |
| 339 // Replace Arg in the argument list with the home register. Then generate | 376 // Replace Arg in the argument list with the home register. Then generate |
| 340 // an instruction in the prolog to copy the home register to the assigned | 377 // an instruction in the prolog to copy the home register to the assigned |
| 341 // location of Arg. | 378 // location of Arg. |
| 342 if (BuildDefs::dump()) | 379 if (BuildDefs::dump()) |
| 343 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 380 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 344 RegisterArg->setRegNum(RegNum); | 381 RegisterArg->setRegNum(RegNum); |
| 345 RegisterArg->setIsArg(); | 382 RegisterArg->setIsArg(); |
| 346 Arg->setIsArg(false); | 383 Arg->setIsArg(false); |
| 347 | 384 |
| 348 Args[i] = RegisterArg; | 385 Args[i] = RegisterArg; |
| 349 Context.insert<InstAssign>(Arg, RegisterArg); | 386 Context.insert<InstAssign>(Arg, RegisterArg); |
| 350 } | 387 } |
| 351 } | 388 } |
| 352 | 389 |
| 353 void TargetX8664::lowerRet(const InstRet *Inst) { | 390 void TargetX8664::lowerRet(const InstRet *Inst) { |
| 354 Variable *Reg = nullptr; | 391 Variable *Reg = nullptr; |
| 355 if (Inst->hasRetValue()) { | 392 if (Inst->hasRetValue()) { |
| 356 Operand *Src0 = legalize(Inst->getRetValue()); | 393 Operand *Src0 = legalize(Inst->getRetValue()); |
| 357 if (isVectorType(Src0->getType()) || | 394 if (isVectorType(Src0->getType()) || |
| 358 isScalarFloatingType(Src0->getType())) { | 395 isScalarFloatingType(Src0->getType())) { |
| 359 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); | 396 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); |
| 360 } else { | 397 } else { |
| 361 assert(isScalarIntegerType(Src0->getType())); | 398 assert(isScalarIntegerType(Src0->getType())); |
| 362 _mov(Reg, Src0, Traits::RegisterSet::Reg_eax); | 399 _mov(Reg, Src0, Traits::getGprForType(Src0->getType(), |
| 400 Traits::RegisterSet::Reg_rax)); |
| 363 } | 401 } |
| 364 } | 402 } |
| 365 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 403 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
| 366 // explicitly looks for a ret instruction as a marker for where to insert the | 404 // explicitly looks for a ret instruction as a marker for where to insert the |
| 367 // frame removal instructions. | 405 // frame removal instructions. |
| 368 _ret(Reg); | 406 _ret(Reg); |
| 369 // Add a fake use of esp to make sure esp stays alive for the entire | 407 // Add a fake use of esp to make sure esp stays alive for the entire |
| 370 // function. Otherwise post-call esp adjustments get dead-code eliminated. | 408 // function. Otherwise post-call esp adjustments get dead-code eliminated. |
| 371 keepEspLiveAtExit(); | 409 keepEspLiveAtExit(); |
| 372 } | 410 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | 510 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
| 473 _push(getPhysicalRegister(i, IceType_i64)); | 511 _push(getPhysicalRegister(i, IceType_i64)); |
| 474 } | 512 } |
| 475 Ctx->statsUpdateRegistersSaved(NumCallee); | 513 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 476 | 514 |
| 477 // Generate "push ebp; mov ebp, esp" | 515 // Generate "push ebp; mov ebp, esp" |
| 478 if (IsEbpBasedFrame) { | 516 if (IsEbpBasedFrame) { |
| 479 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | 517 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) |
| 480 .count() == 0); | 518 .count() == 0); |
| 481 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | 519 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
| 482 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_rbp); | 520 Variable *ebp = |
| 483 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_rsp); | 521 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64); |
| 522 Variable *esp = |
| 523 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); |
| 484 _push(ebp); | 524 _push(ebp); |
| 485 _mov(ebp, esp); | 525 _mov(ebp, esp); |
| 486 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | 526 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). |
| 487 Context.insert<InstFakeUse>(ebp); | 527 Context.insert<InstFakeUse>(ebp); |
| 488 } | 528 } |
| 489 | 529 |
| 490 // Align the variables area. SpillAreaPaddingBytes is the size of the region | 530 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
| 491 // after the preserved registers and before the spill areas. | 531 // after the preserved registers and before the spill areas. |
| 492 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | 532 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
| 493 // locals area if they are separate. | 533 // locals area if they are separate. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 521 SpillAreaSizeBytes += FixedAllocaSizeBytes; | 561 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
| 522 // Generate "sub esp, SpillAreaSizeBytes" | 562 // Generate "sub esp, SpillAreaSizeBytes" |
| 523 if (SpillAreaSizeBytes) { | 563 if (SpillAreaSizeBytes) { |
| 524 _sub(getPhysicalRegister(getStackReg(), IceType_i64), | 564 _sub(getPhysicalRegister(getStackReg(), IceType_i64), |
| 525 Ctx->getConstantInt32(SpillAreaSizeBytes)); | 565 Ctx->getConstantInt32(SpillAreaSizeBytes)); |
| 526 // If the fixed allocas are aligned more than the stack frame, align the | 566 // If the fixed allocas are aligned more than the stack frame, align the |
| 527 // stack pointer accordingly. | 567 // stack pointer accordingly. |
| 528 if (PrologEmitsFixedAllocas && | 568 if (PrologEmitsFixedAllocas && |
| 529 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { | 569 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { |
| 530 assert(IsEbpBasedFrame); | 570 assert(IsEbpBasedFrame); |
| 531 _and(getPhysicalRegister(Traits::RegisterSet::Reg_rsp), | 571 _and(getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64), |
| 532 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); | 572 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); |
| 533 } | 573 } |
| 534 } | 574 } |
| 535 | 575 |
| 536 // Account for alloca instructions with known frame offsets. | 576 // Account for alloca instructions with known frame offsets. |
| 537 if (!PrologEmitsFixedAllocas) | 577 if (!PrologEmitsFixedAllocas) |
| 538 SpillAreaSizeBytes += FixedAllocaSizeBytes; | 578 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
| 539 | 579 |
| 540 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | 580 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
| 541 | 581 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 if (RI == E) | 670 if (RI == E) |
| 631 return; | 671 return; |
| 632 | 672 |
| 633 // Convert the reverse_iterator position into its corresponding (forward) | 673 // Convert the reverse_iterator position into its corresponding (forward) |
| 634 // iterator position. | 674 // iterator position. |
| 635 InstList::iterator InsertPoint = RI.base(); | 675 InstList::iterator InsertPoint = RI.base(); |
| 636 --InsertPoint; | 676 --InsertPoint; |
| 637 Context.init(Node); | 677 Context.init(Node); |
| 638 Context.setInsertPoint(InsertPoint); | 678 Context.setInsertPoint(InsertPoint); |
| 639 | 679 |
| 640 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_rsp); | 680 Variable *esp = |
| 681 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); |
| 641 if (IsEbpBasedFrame) { | 682 if (IsEbpBasedFrame) { |
| 642 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_rbp); | 683 Variable *ebp = |
| 684 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64); |
| 643 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 685 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
| 644 // use of esp before the assignment of esp=ebp keeps previous esp | 686 // use of esp before the assignment of esp=ebp keeps previous esp |
| 645 // adjustments from being dead-code eliminated. | 687 // adjustments from being dead-code eliminated. |
| 646 Context.insert<InstFakeUse>(esp); | 688 Context.insert<InstFakeUse>(esp); |
| 647 _mov(esp, ebp); | 689 _mov(esp, ebp); |
| 648 _pop(ebp); | 690 _pop(ebp); |
| 649 } else { | 691 } else { |
| 650 // add esp, SpillAreaSizeBytes | 692 // add esp, SpillAreaSizeBytes |
| 651 if (SpillAreaSizeBytes) | 693 if (SpillAreaSizeBytes) |
| 652 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); | 694 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 // case the high-level table has extra entries. | 1025 // case the high-level table has extra entries. |
| 984 #define X(tag, sizeLog2, align, elts, elty, str) \ | 1026 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 985 static_assert(_table1_##tag == _table2_##tag, \ | 1027 static_assert(_table1_##tag == _table2_##tag, \ |
| 986 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 1028 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 987 ICETYPE_TABLE | 1029 ICETYPE_TABLE |
| 988 #undef X | 1030 #undef X |
| 989 } // end of namespace dummy3 | 1031 } // end of namespace dummy3 |
| 990 } // end of anonymous namespace | 1032 } // end of anonymous namespace |
| 991 | 1033 |
| 992 } // end of namespace Ice | 1034 } // end of namespace Ice |
| OLD | NEW |