Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1187513006: ARM: Assign "actuals" at call site to the appropriate GPR/stack slot. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: review Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 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 // This file implements the TargetLoweringARM32 class, which consists almost 10 // This file implements the TargetLoweringARM32 class, which consists almost
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 // Repeat the static asserts with respect to the high-level table 113 // Repeat the static asserts with respect to the high-level table
114 // entries in case the high-level table has extra entries. 114 // entries in case the high-level table has extra entries.
115 #define X(tag, str) \ 115 #define X(tag, str) \
116 static_assert( \ 116 static_assert( \
117 _table1_##tag == _table2_##tag, \ 117 _table1_##tag == _table2_##tag, \
118 "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE"); 118 "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE");
119 ICEINSTICMP_TABLE 119 ICEINSTICMP_TABLE
120 #undef X 120 #undef X
121 } // end of namespace dummy1 121 } // end of namespace dummy1
122 122
123 // The maximum number of arguments to pass in GPR registers.
124 const uint32_t ARM32_MAX_GPR_ARG = 4;
125
126 // Stack alignment 123 // Stack alignment
127 const uint32_t ARM32_STACK_ALIGNMENT_BYTES = 16; 124 const uint32_t ARM32_STACK_ALIGNMENT_BYTES = 16;
128 125
129 // Value is in bytes. Return Value adjusted to the next highest multiple 126 // Value is in bytes. Return Value adjusted to the next highest multiple
130 // of the stack alignment. 127 // of the stack alignment.
131 uint32_t applyStackAlignment(uint32_t Value) { 128 uint32_t applyStackAlignment(uint32_t Value) {
132 return Utils::applyAlignment(Value, ARM32_STACK_ALIGNMENT_BYTES); 129 return Utils::applyAlignment(Value, ARM32_STACK_ALIGNMENT_BYTES);
133 } 130 }
134 131
132 // Value is in bytes. Return Value adjusted to the next highest multiple
133 // of the stack alignment required for the given type.
134 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) {
135 // Use natural alignment, except that normally (non-NaCl) ARM only
136 // aligns vectors to 8 bytes.
137 // TODO(jvoung): Check this ...
138 size_t typeAlignInBytes = typeWidthInBytes(Ty);
139 if (isVectorType(Ty))
140 typeAlignInBytes = 8;
141 return Utils::applyAlignment(Value, typeAlignInBytes);
142 }
143
135 } // end of anonymous namespace 144 } // end of anonymous namespace
136 145
137 TargetARM32::TargetARM32(Cfg *Func) 146 TargetARM32::TargetARM32(Cfg *Func)
138 : TargetLowering(Func), InstructionSet(ARM32InstructionSet::Begin), 147 : TargetLowering(Func), InstructionSet(ARM32InstructionSet::Begin),
139 UsesFramePointer(false), NeedsStackAlignment(false), MaybeLeafFunc(true), 148 UsesFramePointer(false), NeedsStackAlignment(false), MaybeLeafFunc(true),
140 SpillAreaSizeBytes(0) { 149 SpillAreaSizeBytes(0) {
141 static_assert( 150 static_assert(
142 (ARM32InstructionSet::End - ARM32InstructionSet::Begin) == 151 (ARM32InstructionSet::End - ARM32InstructionSet::Begin) ==
143 (TargetInstructionSet::ARM32InstructionSet_End - 152 (TargetInstructionSet::ARM32InstructionSet_End -
144 TargetInstructionSet::ARM32InstructionSet_Begin), 153 TargetInstructionSet::ARM32InstructionSet_Begin),
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 } 379 }
371 if (Var->getWeight().isInf()) { 380 if (Var->getWeight().isInf()) {
372 llvm::report_fatal_error( 381 llvm::report_fatal_error(
373 "Infinite-weight Variable has no register assigned"); 382 "Infinite-weight Variable has no register assigned");
374 } 383 }
375 int32_t Offset = Var->getStackOffset(); 384 int32_t Offset = Var->getStackOffset();
376 if (!hasFramePointer()) 385 if (!hasFramePointer())
377 Offset += getStackAdjustment(); 386 Offset += getStackAdjustment();
378 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register 387 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register
379 // to materialize a larger offset. 388 // to materialize a larger offset.
380 const bool SignExt = false; 389 constexpr bool SignExt = false;
381 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { 390 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) {
382 llvm::report_fatal_error("Illegal stack offset"); 391 llvm::report_fatal_error("Illegal stack offset");
383 } 392 }
384 const Type FrameSPTy = IceType_i32; 393 const Type FrameSPTy = IceType_i32;
385 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy); 394 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy);
386 if (Offset != 0) { 395 if (Offset != 0) {
387 Str << ", " << getConstantPrefix() << Offset; 396 Str << ", " << getConstantPrefix() << Offset;
388 } 397 }
389 Str << "]"; 398 Str << "]";
390 } 399 }
391 400
401 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) {
402 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG)
403 return false;
404 int32_t RegLo, RegHi;
405 // Always start i64 registers at an even register, so this may end
406 // up padding away a register.
407 if (NumGPRRegsUsed % 2 != 0) {
408 ++NumGPRRegsUsed;
409 }
410 RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed;
411 ++NumGPRRegsUsed;
412 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed;
413 ++NumGPRRegsUsed;
414 // If this bumps us past the boundary, don't allocate to a register
415 // and leave any previously speculatively consumed registers as consumed.
416 if (NumGPRRegsUsed > ARM32_MAX_GPR_ARG)
417 return false;
418 Regs->first = RegLo;
419 Regs->second = RegHi;
420 return true;
421 }
422
423 bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) {
424 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG)
425 return false;
426 *Reg = RegARM32::Reg_r0 + NumGPRRegsUsed;
427 ++NumGPRRegsUsed;
428 return true;
429 }
430
392 void TargetARM32::lowerArguments() { 431 void TargetARM32::lowerArguments() {
393 VarList &Args = Func->getArgs(); 432 VarList &Args = Func->getArgs();
394 // The first few integer type parameters can use r0-r3, regardless of their 433 TargetARM32::CallingConv CC;
395 // position relative to the floating-point/vector arguments in the argument
396 // list. Floating-point and vector arguments can use q0-q3 (aka d0-d7,
397 // s0-s15).
398 unsigned NumGPRRegsUsed = 0;
399 434
400 // For each register argument, replace Arg in the argument list with the 435 // For each register argument, replace Arg in the argument list with the
401 // home register. Then generate an instruction in the prolog to copy the 436 // home register. Then generate an instruction in the prolog to copy the
402 // home register to the assigned location of Arg. 437 // home register to the assigned location of Arg.
403 Context.init(Func->getEntryNode()); 438 Context.init(Func->getEntryNode());
404 Context.setInsertPoint(Context.getCur()); 439 Context.setInsertPoint(Context.getCur());
405 440
406 for (SizeT I = 0, E = Args.size(); I < E; ++I) { 441 for (SizeT I = 0, E = Args.size(); I < E; ++I) {
407 Variable *Arg = Args[I]; 442 Variable *Arg = Args[I];
408 Type Ty = Arg->getType(); 443 Type Ty = Arg->getType();
409 // TODO(jvoung): handle float/vector types. 444 // TODO(jvoung): handle float/vector types.
410 if (isVectorType(Ty)) { 445 if (isVectorType(Ty)) {
411 UnimplementedError(Func->getContext()->getFlags()); 446 UnimplementedError(Func->getContext()->getFlags());
412 continue; 447 continue;
413 } else if (isFloatingType(Ty)) { 448 } else if (isFloatingType(Ty)) {
414 UnimplementedError(Func->getContext()->getFlags()); 449 UnimplementedError(Func->getContext()->getFlags());
415 continue; 450 continue;
416 } else if (Ty == IceType_i64) { 451 } else if (Ty == IceType_i64) {
417 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) 452 std::pair<int32_t, int32_t> RegPair;
418 continue; 453 if (!CC.I64InRegs(&RegPair))
419 int32_t RegLo;
420 int32_t RegHi;
421 // Always start i64 registers at an even register, so this may end
422 // up padding away a register.
423 if (NumGPRRegsUsed % 2 != 0) {
424 ++NumGPRRegsUsed;
425 }
426 RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed;
427 ++NumGPRRegsUsed;
428 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed;
429 ++NumGPRRegsUsed;
430 // If this bumps us past the boundary, don't allocate to a register
431 // and leave any previously speculatively consumed registers as consumed.
432 if (NumGPRRegsUsed > ARM32_MAX_GPR_ARG)
433 continue; 454 continue;
434 Variable *RegisterArg = Func->makeVariable(Ty); 455 Variable *RegisterArg = Func->makeVariable(Ty);
435 Variable *RegisterLo = Func->makeVariable(IceType_i32); 456 Variable *RegisterLo = Func->makeVariable(IceType_i32);
436 Variable *RegisterHi = Func->makeVariable(IceType_i32); 457 Variable *RegisterHi = Func->makeVariable(IceType_i32);
437 if (ALLOW_DUMP) { 458 if (ALLOW_DUMP) {
438 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); 459 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func));
439 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); 460 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func));
440 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); 461 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func));
441 } 462 }
442 RegisterLo->setRegNum(RegLo); 463 RegisterLo->setRegNum(RegPair.first);
443 RegisterLo->setIsArg(); 464 RegisterLo->setIsArg();
444 RegisterHi->setRegNum(RegHi); 465 RegisterHi->setRegNum(RegPair.second);
445 RegisterHi->setIsArg(); 466 RegisterHi->setIsArg();
446 RegisterArg->setLoHi(RegisterLo, RegisterHi); 467 RegisterArg->setLoHi(RegisterLo, RegisterHi);
447 RegisterArg->setIsArg(); 468 RegisterArg->setIsArg();
448 Arg->setIsArg(false); 469 Arg->setIsArg(false);
449 470
450 Args[I] = RegisterArg; 471 Args[I] = RegisterArg;
451 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); 472 Context.insert(InstAssign::create(Func, Arg, RegisterArg));
452 continue; 473 continue;
453 } else { 474 } else {
454 assert(Ty == IceType_i32); 475 assert(Ty == IceType_i32);
455 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) 476 int32_t RegNum;
477 if (!CC.I32InReg(&RegNum))
456 continue; 478 continue;
457 int32_t RegNum = RegARM32::Reg_r0 + NumGPRRegsUsed;
458 ++NumGPRRegsUsed;
459 Variable *RegisterArg = Func->makeVariable(Ty); 479 Variable *RegisterArg = Func->makeVariable(Ty);
460 if (ALLOW_DUMP) { 480 if (ALLOW_DUMP) {
461 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); 481 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func));
462 } 482 }
463 RegisterArg->setRegNum(RegNum); 483 RegisterArg->setRegNum(RegNum);
464 RegisterArg->setIsArg(); 484 RegisterArg->setIsArg();
465 Arg->setIsArg(false); 485 Arg->setIsArg(false);
466 486
467 Args[I] = RegisterArg; 487 Args[I] = RegisterArg;
468 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); 488 Context.insert(InstAssign::create(Func, Arg, RegisterArg));
(...skipping 16 matching lines...) Expand all
485 Variable *Lo = Arg->getLo(); 505 Variable *Lo = Arg->getLo();
486 Variable *Hi = Arg->getHi(); 506 Variable *Hi = Arg->getHi();
487 Type Ty = Arg->getType(); 507 Type Ty = Arg->getType();
488 if (Lo && Hi && Ty == IceType_i64) { 508 if (Lo && Hi && Ty == IceType_i64) {
489 assert(Lo->getType() != IceType_i64); // don't want infinite recursion 509 assert(Lo->getType() != IceType_i64); // don't want infinite recursion
490 assert(Hi->getType() != IceType_i64); // don't want infinite recursion 510 assert(Hi->getType() != IceType_i64); // don't want infinite recursion
491 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); 511 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes);
492 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); 512 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes);
493 return; 513 return;
494 } 514 }
495 if (isVectorType(Ty)) { 515 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty);
496 InArgsSizeBytes = applyStackAlignment(InArgsSizeBytes);
497 }
498 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); 516 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes);
499 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); 517 InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
500 // If the argument variable has been assigned a register, we need to load 518 // If the argument variable has been assigned a register, we need to load
501 // the value from the stack slot. 519 // the value from the stack slot.
502 if (Arg->hasReg()) { 520 if (Arg->hasReg()) {
503 assert(Ty != IceType_i64); 521 assert(Ty != IceType_i64);
504 OperandARM32Mem *Mem = OperandARM32Mem::create( 522 OperandARM32Mem *Mem = OperandARM32Mem::create(
505 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( 523 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>(
506 Ctx->getConstantInt32(Arg->getStackOffset()))); 524 Ctx->getConstantInt32(Arg->getStackOffset())));
507 if (isVectorType(Arg->getType())) { 525 if (isVectorType(Arg->getType())) {
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 // Fill in stack offsets for stack args, and copy args into registers 683 // Fill in stack offsets for stack args, and copy args into registers
666 // for those that were register-allocated. Args are pushed right to 684 // for those that were register-allocated. Args are pushed right to
667 // left, so Arg[0] is closest to the stack/frame pointer. 685 // left, so Arg[0] is closest to the stack/frame pointer.
668 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); 686 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg());
669 size_t BasicFrameOffset = PreservedRegsSizeBytes; 687 size_t BasicFrameOffset = PreservedRegsSizeBytes;
670 if (!UsesFramePointer) 688 if (!UsesFramePointer)
671 BasicFrameOffset += SpillAreaSizeBytes; 689 BasicFrameOffset += SpillAreaSizeBytes;
672 690
673 const VarList &Args = Func->getArgs(); 691 const VarList &Args = Func->getArgs();
674 size_t InArgsSizeBytes = 0; 692 size_t InArgsSizeBytes = 0;
675 unsigned NumGPRArgs = 0; 693 TargetARM32::CallingConv CC;
676 for (Variable *Arg : Args) { 694 for (Variable *Arg : Args) {
677 Type Ty = Arg->getType(); 695 Type Ty = Arg->getType();
696 bool InRegs = false;
678 // Skip arguments passed in registers. 697 // Skip arguments passed in registers.
679 if (isVectorType(Ty)) { 698 if (isVectorType(Ty)) {
680 UnimplementedError(Func->getContext()->getFlags()); 699 UnimplementedError(Func->getContext()->getFlags());
681 continue; 700 continue;
682 } else if (isFloatingType(Ty)) { 701 } else if (isFloatingType(Ty)) {
683 UnimplementedError(Func->getContext()->getFlags()); 702 UnimplementedError(Func->getContext()->getFlags());
684 continue; 703 continue;
685 } else if (Ty == IceType_i64 && NumGPRArgs < ARM32_MAX_GPR_ARG) { 704 } else if (Ty == IceType_i64) {
686 // Start at an even register. 705 std::pair<int32_t, int32_t> DummyRegs;
687 if (NumGPRArgs % 2 == 1) { 706 InRegs = CC.I64InRegs(&DummyRegs);
688 ++NumGPRArgs; 707 } else {
689 } 708 assert(Ty == IceType_i32);
690 NumGPRArgs += 2; 709 int32_t DummyReg;
691 if (NumGPRArgs <= ARM32_MAX_GPR_ARG) 710 InRegs = CC.I32InReg(&DummyReg);
692 continue;
693 } else if (NumGPRArgs < ARM32_MAX_GPR_ARG) {
694 ++NumGPRArgs;
695 continue;
696 } 711 }
697 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); 712 if (!InRegs)
713 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes);
698 } 714 }
699 715
700 // Fill in stack offsets for locals. 716 // Fill in stack offsets for locals.
701 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, 717 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes,
702 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, 718 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize,
703 UsesFramePointer); 719 UsesFramePointer);
704 this->HasComputedFrame = true; 720 this->HasComputedFrame = true;
705 721
706 if (ALLOW_DUMP && Func->isVerbose(IceV_Frame)) { 722 if (ALLOW_DUMP && Func->isVerbose(IceV_Frame)) {
707 OstreamLocker L(Func->getContext()); 723 OstreamLocker L(Func->getContext());
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 // TODO(jvoung): Handle folding opportunities. 1323 // TODO(jvoung): Handle folding opportunities.
1308 1324
1309 Variable *Src0R = legalizeToVar(Cond); 1325 Variable *Src0R = legalizeToVar(Cond);
1310 Constant *Zero = Ctx->getConstantZero(IceType_i32); 1326 Constant *Zero = Ctx->getConstantZero(IceType_i32);
1311 _cmp(Src0R, Zero); 1327 _cmp(Src0R, Zero);
1312 _br(CondARM32::NE, Inst->getTargetTrue(), Inst->getTargetFalse()); 1328 _br(CondARM32::NE, Inst->getTargetTrue(), Inst->getTargetFalse());
1313 } 1329 }
1314 1330
1315 void TargetARM32::lowerCall(const InstCall *Instr) { 1331 void TargetARM32::lowerCall(const InstCall *Instr) {
1316 MaybeLeafFunc = false; 1332 MaybeLeafFunc = false;
1333 NeedsStackAlignment = true;
1317 1334
1318 // TODO(jvoung): assign arguments to registers and stack. Also reserve stack. 1335 // Assign arguments to registers and stack. Also reserve stack.
1319 if (Instr->getNumArgs()) { 1336 TargetARM32::CallingConv CC;
1320 UnimplementedError(Func->getContext()->getFlags()); 1337 // Pair of Arg Operand -> GPR number assignments.
1338 llvm::SmallVector<std::pair<Operand *, int32_t>,
1339 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs;
1340 // Pair of Arg Operand -> stack offset.
1341 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs;
1342 int32_t ParameterAreaSizeBytes = 0;
1343
1344 // Classify each argument operand according to the location where the
1345 // argument is passed.
1346 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) {
1347 Operand *Arg = Instr->getArg(i);
1348 Type Ty = Arg->getType();
1349 bool InRegs = false;
1350 if (isVectorType(Ty)) {
1351 UnimplementedError(Func->getContext()->getFlags());
1352 } else if (isFloatingType(Ty)) {
1353 UnimplementedError(Func->getContext()->getFlags());
1354 } else if (Ty == IceType_i64) {
1355 std::pair<int32_t, int32_t> Regs;
1356 if (CC.I64InRegs(&Regs)) {
1357 InRegs = true;
1358 Operand *Lo = loOperand(Arg);
1359 Operand *Hi = hiOperand(Arg);
1360 GPRArgs.push_back(std::make_pair(Lo, Regs.first));
1361 GPRArgs.push_back(std::make_pair(Hi, Regs.second));
1362 }
1363 } else {
1364 assert(Ty == IceType_i32);
1365 int32_t Reg;
1366 if (CC.I32InReg(&Reg)) {
1367 InRegs = true;
1368 GPRArgs.push_back(std::make_pair(Arg, Reg));
1369 }
1370 }
1371
1372 if (!InRegs) {
1373 ParameterAreaSizeBytes =
1374 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty);
1375 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes));
1376 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
1377 }
1378 }
1379
1380 // Adjust the parameter area so that the stack is aligned. It is
1381 // assumed that the stack is already aligned at the start of the
1382 // calling sequence.
1383 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
1384
1385 // Subtract the appropriate amount for the argument area. This also
1386 // takes care of setting the stack adjustment during emission.
1387 //
1388 // TODO: If for some reason the call instruction gets dead-code
1389 // eliminated after lowering, we would need to ensure that the
1390 // pre-call and the post-call esp adjustment get eliminated as well.
1391 if (ParameterAreaSizeBytes) {
1392 Operand *SubAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes),
1393 Legal_Reg | Legal_Flex);
1394 _adjust_stack(ParameterAreaSizeBytes, SubAmount);
1395 }
1396
1397 // Copy arguments that are passed on the stack to the appropriate
1398 // stack locations.
1399 Variable *SP = Func->getTarget()->getPhysicalRegister(RegARM32::Reg_sp);
1400 for (auto &StackArg : StackArgs) {
1401 ConstantInteger32 *Loc =
1402 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second));
1403 Type Ty = StackArg.first->getType();
1404 OperandARM32Mem *Addr;
1405 constexpr bool SignExt = false;
1406 if (OperandARM32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) {
1407 Addr = OperandARM32Mem::create(Func, Ty, SP, Loc);
1408 } else {
1409 Variable *NewBase = Func->makeVariable(SP->getType());
1410 lowerArithmetic(
1411 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc));
1412 Addr = formMemoryOperand(NewBase, Ty);
1413 }
1414 lowerStore(InstStore::create(Func, StackArg.first, Addr));
1415 }
1416
1417 // Copy arguments to be passed in registers to the appropriate registers.
1418 for (auto &GPRArg : GPRArgs) {
1419 Variable *Reg = legalizeToVar(GPRArg.first, GPRArg.second);
1420 // Generate a FakeUse of register arguments so that they do not get
1421 // dead code eliminated as a result of the FakeKill of scratch
1422 // registers after the call.
1423 Context.insert(InstFakeUse::create(Func, Reg));
1321 } 1424 }
1322 1425
1323 // Generate the call instruction. Assign its result to a temporary 1426 // Generate the call instruction. Assign its result to a temporary
1324 // with high register allocation weight. 1427 // with high register allocation weight.
1325 Variable *Dest = Instr->getDest(); 1428 Variable *Dest = Instr->getDest();
1326 // ReturnReg doubles as ReturnRegLo as necessary. 1429 // ReturnReg doubles as ReturnRegLo as necessary.
1327 Variable *ReturnReg = nullptr; 1430 Variable *ReturnReg = nullptr;
1328 Variable *ReturnRegHi = nullptr; 1431 Variable *ReturnRegHi = nullptr;
1329 if (Dest) { 1432 if (Dest) {
1330 switch (Dest->getType()) { 1433 switch (Dest->getType()) {
(...skipping 23 matching lines...) Expand all
1354 case IceType_v16i8: 1457 case IceType_v16i8:
1355 case IceType_v8i16: 1458 case IceType_v8i16:
1356 case IceType_v4i32: 1459 case IceType_v4i32:
1357 case IceType_v4f32: 1460 case IceType_v4f32:
1358 // Use Q regs. 1461 // Use Q regs.
1359 UnimplementedError(Func->getContext()->getFlags()); 1462 UnimplementedError(Func->getContext()->getFlags());
1360 break; 1463 break;
1361 } 1464 }
1362 } 1465 }
1363 Operand *CallTarget = Instr->getCallTarget(); 1466 Operand *CallTarget = Instr->getCallTarget();
1467 // TODO(jvoung): Handle sandboxing.
1468 // const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
1469
1364 // Allow ConstantRelocatable to be left alone as a direct call, 1470 // Allow ConstantRelocatable to be left alone as a direct call,
1365 // but force other constants like ConstantInteger32 to be in 1471 // but force other constants like ConstantInteger32 to be in
1366 // a register and make it an indirect call. 1472 // a register and make it an indirect call.
1367 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { 1473 if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
1368 CallTarget = legalize(CallTarget, Legal_Reg); 1474 CallTarget = legalize(CallTarget, Legal_Reg);
1369 } 1475 }
1370 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); 1476 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget);
1371 Context.insert(NewCall); 1477 Context.insert(NewCall);
1372 if (ReturnRegHi) 1478 if (ReturnRegHi)
1373 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); 1479 Context.insert(InstFakeDef::create(Func, ReturnRegHi));
1374 1480
1481 // Add the appropriate offset to SP. The call instruction takes care
1482 // of resetting the stack offset during emission.
1483 if (ParameterAreaSizeBytes) {
1484 Operand *AddAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes),
1485 Legal_Reg | Legal_Flex);
1486 Variable *SP = Func->getTarget()->getPhysicalRegister(RegARM32::Reg_sp);
1487 _add(SP, SP, AddAmount);
1488 }
1489
1375 // Insert a register-kill pseudo instruction. 1490 // Insert a register-kill pseudo instruction.
1376 Context.insert(InstFakeKill::create(Func, NewCall)); 1491 Context.insert(InstFakeKill::create(Func, NewCall));
1377 1492
1378 // Generate a FakeUse to keep the call live if necessary. 1493 // Generate a FakeUse to keep the call live if necessary.
1379 if (Instr->hasSideEffects() && ReturnReg) { 1494 if (Instr->hasSideEffects() && ReturnReg) {
1380 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); 1495 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg);
1381 Context.insert(FakeUse); 1496 Context.insert(FakeUse);
1382 } 1497 }
1383 1498
1384 if (!Dest) 1499 if (!Dest)
(...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 << ".eabi_attribute 36, 1 @ Tag_FP_HP_extension\n" 2381 << ".eabi_attribute 36, 1 @ Tag_FP_HP_extension\n"
2267 << ".eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format\n" 2382 << ".eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format\n"
2268 << ".eabi_attribute 42, 1 @ Tag_MPextension_use\n" 2383 << ".eabi_attribute 42, 1 @ Tag_MPextension_use\n"
2269 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; 2384 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n";
2270 // Technically R9 is used for TLS with Sandboxing, and we reserve it. 2385 // Technically R9 is used for TLS with Sandboxing, and we reserve it.
2271 // However, for compatibility with current NaCl LLVM, don't claim that. 2386 // However, for compatibility with current NaCl LLVM, don't claim that.
2272 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 2387 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
2273 } 2388 }
2274 2389
2275 } // end of namespace Ice 2390 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/64bit.pnacl.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698