Insert int3 after non-returning calls at the end of basic blocks. (#17535)
[platform/upstream/coreclr.git] / src / jit / codegenlinear.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX            Code Generation Support Methods for Linear Codegen             XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13 #include "jitpch.h"
14 #ifdef _MSC_VER
15 #pragma hdrstop
16 #endif
17
18 #ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator.
19 #include "emit.h"
20 #include "codegen.h"
21
22 //------------------------------------------------------------------------
23 // genCodeForBBlist: Generate code for all the blocks in a method
24 //
25 // Arguments:
26 //    None
27 //
28 // Notes:
29 //    This is the main method for linear codegen. It calls genCodeForTreeNode
30 //    to generate the code for each node in each BasicBlock, and handles BasicBlock
31 //    boundaries and branches.
32 //
33 void CodeGen::genCodeForBBlist()
34 {
35     unsigned   varNum;
36     LclVarDsc* varDsc;
37
38     unsigned savedStkLvl;
39
40 #ifdef DEBUG
41     genInterruptibleUsed = true;
42
43     // You have to be careful if you create basic blocks from now on
44     compiler->fgSafeBasicBlockCreation = false;
45
46     // This stress mode is not comptible with fully interruptible GC
47     if (genInterruptible && compiler->opts.compStackCheckOnCall)
48     {
49         compiler->opts.compStackCheckOnCall = false;
50     }
51
52     // This stress mode is not comptible with fully interruptible GC
53     if (genInterruptible && compiler->opts.compStackCheckOnRet)
54     {
55         compiler->opts.compStackCheckOnRet = false;
56     }
57 #endif // DEBUG
58
59     // Prepare the blocks for exception handling codegen: mark the blocks that needs labels.
60     genPrepForEHCodegen();
61
62     assert(!compiler->fgFirstBBScratch ||
63            compiler->fgFirstBB == compiler->fgFirstBBScratch); // compiler->fgFirstBBScratch has to be first.
64
65     /* Initialize the spill tracking logic */
66
67     regSet.rsSpillBeg();
68
69     /* Initialize the line# tracking logic */
70
71     if (compiler->opts.compScopeInfo)
72     {
73         siInit();
74     }
75
76     // The current implementation of switch tables requires the first block to have a label so it
77     // can generate offsets to the switch label targets.
78     // TODO-CQ: remove this when switches have been re-implemented to not use this.
79     if (compiler->fgHasSwitch)
80     {
81         compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET;
82     }
83
84     genPendingCallLabel = nullptr;
85
86     /* Initialize the pointer tracking code */
87
88     gcInfo.gcRegPtrSetInit();
89     gcInfo.gcVarPtrSetInit();
90
91     /* If any arguments live in registers, mark those regs as such */
92
93     for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->lvaCount; varNum++, varDsc++)
94     {
95         /* Is this variable a parameter assigned to a register? */
96
97         if (!varDsc->lvIsParam || !varDsc->lvRegister)
98         {
99             continue;
100         }
101
102         /* Is the argument live on entry to the method? */
103
104         if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex))
105         {
106             continue;
107         }
108
109         /* Is this a floating-point argument? */
110
111         if (varDsc->IsFloatRegType())
112         {
113             continue;
114         }
115
116         noway_assert(!varTypeIsFloating(varDsc->TypeGet()));
117
118         /* Mark the register as holding the variable */
119
120         regTracker.rsTrackRegLclVar(varDsc->lvRegNum, varNum);
121     }
122
123     unsigned finallyNesting = 0;
124
125     // Make sure a set is allocated for compiler->compCurLife (in the long case), so we can set it to empty without
126     // allocation at the start of each basic block.
127     VarSetOps::AssignNoCopy(compiler, compiler->compCurLife, VarSetOps::MakeEmpty(compiler));
128
129     /*-------------------------------------------------------------------------
130      *
131      *  Walk the basic blocks and generate code for each one
132      *
133      */
134
135     BasicBlock* block;
136
137     for (block = compiler->fgFirstBB; block != nullptr; block = block->bbNext)
138     {
139 #ifdef DEBUG
140         if (compiler->verbose)
141         {
142             printf("\n=============== Generating ");
143             block->dspBlockHeader(compiler, true, true);
144             compiler->fgDispBBLiveness(block);
145         }
146 #endif // DEBUG
147
148         assert(LIR::AsRange(block).CheckLIR(compiler));
149
150         // Figure out which registers hold variables on entry to this block
151
152         regSet.ClearMaskVars();
153         gcInfo.gcRegGCrefSetCur = RBM_NONE;
154         gcInfo.gcRegByrefSetCur = RBM_NONE;
155
156         compiler->m_pLinearScan->recordVarLocationsAtStartOfBB(block);
157
158         genUpdateLife(block->bbLiveIn);
159
160         // Even if liveness didn't change, we need to update the registers containing GC references.
161         // genUpdateLife will update the registers live due to liveness changes. But what about registers that didn't
162         // change? We cleared them out above. Maybe we should just not clear them out, but update the ones that change
163         // here. That would require handling the changes in recordVarLocationsAtStartOfBB().
164
165         regMaskTP newLiveRegSet  = RBM_NONE;
166         regMaskTP newRegGCrefSet = RBM_NONE;
167         regMaskTP newRegByrefSet = RBM_NONE;
168 #ifdef DEBUG
169         VARSET_TP removedGCVars(VarSetOps::MakeEmpty(compiler));
170         VARSET_TP addedGCVars(VarSetOps::MakeEmpty(compiler));
171 #endif
172         VarSetOps::Iter iter(compiler, block->bbLiveIn);
173         unsigned        varIndex = 0;
174         while (iter.NextElem(&varIndex))
175         {
176             unsigned   varNum = compiler->lvaTrackedToVarNum[varIndex];
177             LclVarDsc* varDsc = &(compiler->lvaTable[varNum]);
178
179             if (varDsc->lvIsInReg())
180             {
181                 newLiveRegSet |= varDsc->lvRegMask();
182                 if (varDsc->lvType == TYP_REF)
183                 {
184                     newRegGCrefSet |= varDsc->lvRegMask();
185                 }
186                 else if (varDsc->lvType == TYP_BYREF)
187                 {
188                     newRegByrefSet |= varDsc->lvRegMask();
189                 }
190 #ifdef DEBUG
191                 if (verbose && VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex))
192                 {
193                     VarSetOps::AddElemD(compiler, removedGCVars, varIndex);
194                 }
195 #endif // DEBUG
196                 VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex);
197             }
198             else if (compiler->lvaIsGCTracked(varDsc))
199             {
200 #ifdef DEBUG
201                 if (verbose && !VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex))
202                 {
203                     VarSetOps::AddElemD(compiler, addedGCVars, varIndex);
204                 }
205 #endif // DEBUG
206                 VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex);
207             }
208         }
209
210         regSet.rsMaskVars = newLiveRegSet;
211
212 #ifdef DEBUG
213         if (compiler->verbose)
214         {
215             if (!VarSetOps::IsEmpty(compiler, addedGCVars))
216             {
217                 printf("\t\t\t\t\t\t\tAdded GCVars: ");
218                 dumpConvertedVarSet(compiler, addedGCVars);
219                 printf("\n");
220             }
221             if (!VarSetOps::IsEmpty(compiler, removedGCVars))
222             {
223                 printf("\t\t\t\t\t\t\tRemoved GCVars: ");
224                 dumpConvertedVarSet(compiler, removedGCVars);
225                 printf("\n");
226             }
227         }
228 #endif // DEBUG
229
230         gcInfo.gcMarkRegSetGCref(newRegGCrefSet DEBUGARG(true));
231         gcInfo.gcMarkRegSetByref(newRegByrefSet DEBUGARG(true));
232
233         /* Blocks with handlerGetsXcptnObj()==true use GT_CATCH_ARG to
234            represent the exception object (TYP_REF).
235            We mark REG_EXCEPTION_OBJECT as holding a GC object on entry
236            to the block,  it will be the first thing evaluated
237            (thanks to GTF_ORDER_SIDEEFF).
238          */
239
240         if (handlerGetsXcptnObj(block->bbCatchTyp))
241         {
242             for (GenTree* node : LIR::AsRange(block))
243             {
244                 if (node->OperGet() == GT_CATCH_ARG)
245                 {
246                     gcInfo.gcMarkRegSetGCref(RBM_EXCEPTION_OBJECT);
247                     break;
248                 }
249             }
250         }
251
252 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
253         genInsertNopForUnwinder(block);
254 #endif
255
256         /* Start a new code output block */
257
258         genUpdateCurrentFunclet(block);
259
260 #ifdef _TARGET_XARCH_
261         if (genAlignLoops && block->bbFlags & BBF_LOOP_HEAD)
262         {
263             getEmitter()->emitLoopAlign();
264         }
265 #endif
266
267 #ifdef DEBUG
268         if (compiler->opts.dspCode)
269         {
270             printf("\n      L_M%03u_BB%02u:\n", Compiler::s_compMethodsCount, block->bbNum);
271         }
272 #endif
273
274         block->bbEmitCookie = nullptr;
275
276         if (block->bbFlags & (BBF_JMP_TARGET | BBF_HAS_LABEL))
277         {
278             /* Mark a label and update the current set of live GC refs */
279
280             block->bbEmitCookie = getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur,
281                                                              gcInfo.gcRegByrefSetCur, FALSE);
282         }
283
284         if (block == compiler->fgFirstColdBlock)
285         {
286 #ifdef DEBUG
287             if (compiler->verbose)
288             {
289                 printf("\nThis is the start of the cold region of the method\n");
290             }
291 #endif
292             // We should never have a block that falls through into the Cold section
293             noway_assert(!block->bbPrev->bbFallsThrough());
294
295             // We require the block that starts the Cold section to have a label
296             noway_assert(block->bbEmitCookie);
297             getEmitter()->emitSetFirstColdIGCookie(block->bbEmitCookie);
298         }
299
300         /* Both stacks are always empty on entry to a basic block */
301
302         SetStackLevel(0);
303         genAdjustStackLevel(block);
304         savedStkLvl = genStackLevel;
305
306         /* Tell everyone which basic block we're working on */
307
308         compiler->compCurBB = block;
309
310         siBeginBlock(block);
311
312         // BBF_INTERNAL blocks don't correspond to any single IL instruction.
313         if (compiler->opts.compDbgInfo && (block->bbFlags & BBF_INTERNAL) &&
314             !compiler->fgBBisScratch(block)) // If the block is the distinguished first scratch block, then no need to
315                                              // emit a NO_MAPPING entry, immediately after the prolog.
316         {
317             genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::NO_MAPPING, true);
318         }
319
320         bool firstMapping = true;
321
322 #if FEATURE_EH_FUNCLETS
323         if (block->bbFlags & BBF_FUNCLET_BEG)
324         {
325             genReserveFuncletProlog(block);
326         }
327 #endif // FEATURE_EH_FUNCLETS
328
329         // Clear compCurStmt and compCurLifeTree.
330         compiler->compCurStmt     = nullptr;
331         compiler->compCurLifeTree = nullptr;
332
333         // Traverse the block in linear order, generating code for each node as we
334         // as we encounter it.
335         CLANG_FORMAT_COMMENT_ANCHOR;
336
337 #ifdef DEBUG
338         // Set the use-order numbers for each node.
339         {
340             int useNum = 0;
341             for (GenTree* node : LIR::AsRange(block).NonPhiNodes())
342             {
343                 assert((node->gtDebugFlags & GTF_DEBUG_NODE_CG_CONSUMED) == 0);
344
345                 node->gtUseNum = -1;
346                 if (node->isContained() || node->IsCopyOrReload())
347                 {
348                     continue;
349                 }
350
351                 for (GenTree* operand : node->Operands())
352                 {
353                     genNumberOperandUse(operand, useNum);
354                 }
355             }
356         }
357 #endif // DEBUG
358
359         IL_OFFSETX currentILOffset = BAD_IL_OFFSET;
360         for (GenTree* node : LIR::AsRange(block).NonPhiNodes())
361         {
362             // Do we have a new IL offset?
363             if (node->OperGet() == GT_IL_OFFSET)
364             {
365                 genEnsureCodeEmitted(currentILOffset);
366                 currentILOffset = node->gtStmt.gtStmtILoffsx;
367                 genIPmappingAdd(currentILOffset, firstMapping);
368                 firstMapping = false;
369             }
370
371 #ifdef DEBUG
372             if (node->OperGet() == GT_IL_OFFSET)
373             {
374                 noway_assert(node->gtStmt.gtStmtLastILoffs <= compiler->info.compILCodeSize ||
375                              node->gtStmt.gtStmtLastILoffs == BAD_IL_OFFSET);
376
377                 if (compiler->opts.dspCode && compiler->opts.dspInstrs &&
378                     node->gtStmt.gtStmtLastILoffs != BAD_IL_OFFSET)
379                 {
380                     while (genCurDispOffset <= node->gtStmt.gtStmtLastILoffs)
381                     {
382                         genCurDispOffset += dumpSingleInstr(compiler->info.compCode, genCurDispOffset, ">    ");
383                     }
384                 }
385             }
386 #endif // DEBUG
387
388             genCodeForTreeNode(node);
389             if (node->gtHasReg() && node->IsUnusedValue())
390             {
391                 genConsumeReg(node);
392             }
393         } // end for each node in block
394
395 #ifdef DEBUG
396         // The following set of register spill checks and GC pointer tracking checks used to be
397         // performed at statement boundaries. Now, with LIR, there are no statements, so they are
398         // performed at the end of each block.
399         // TODO: could these checks be performed more frequently? E.g., at each location where
400         // the register allocator says there are no live non-variable registers. Perhaps this could
401         // be done by using the map maintained by LSRA (operandToLocationInfoMap) to mark a node
402         // somehow when, after the execution of that node, there will be no live non-variable registers.
403
404         regSet.rsSpillChk();
405
406         /* Make sure we didn't bungle pointer register tracking */
407
408         regMaskTP ptrRegs       = gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur;
409         regMaskTP nonVarPtrRegs = ptrRegs & ~regSet.rsMaskVars;
410
411         // If return is a GC-type, clear it.  Note that if a common
412         // epilog is generated (genReturnBB) it has a void return
413         // even though we might return a ref.  We can't use the compRetType
414         // as the determiner because something we are tracking as a byref
415         // might be used as a return value of a int function (which is legal)
416         GenTree* blockLastNode = block->lastNode();
417         if ((blockLastNode != nullptr) && (blockLastNode->gtOper == GT_RETURN) &&
418             (varTypeIsGC(compiler->info.compRetType) ||
419              (blockLastNode->gtOp.gtOp1 != nullptr && varTypeIsGC(blockLastNode->gtOp.gtOp1->TypeGet()))))
420         {
421             nonVarPtrRegs &= ~RBM_INTRET;
422         }
423
424         if (nonVarPtrRegs)
425         {
426             printf("Regset after BB%02u gcr=", block->bbNum);
427             printRegMaskInt(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars);
428             compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegGCrefSetCur & ~regSet.rsMaskVars);
429             printf(", byr=");
430             printRegMaskInt(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars);
431             compiler->getEmitter()->emitDispRegSet(gcInfo.gcRegByrefSetCur & ~regSet.rsMaskVars);
432             printf(", regVars=");
433             printRegMaskInt(regSet.rsMaskVars);
434             compiler->getEmitter()->emitDispRegSet(regSet.rsMaskVars);
435             printf("\n");
436         }
437
438         noway_assert(nonVarPtrRegs == RBM_NONE);
439 #endif // DEBUG
440
441 #if defined(DEBUG)
442         if (block->bbNext == nullptr)
443         {
444 // Unit testing of the emitter: generate a bunch of instructions into the last block
445 // (it's as good as any, but better than the prolog, which can only be a single instruction
446 // group) then use COMPlus_JitLateDisasm=* to see if the late disassembler
447 // thinks the instructions are the same as we do.
448 #if defined(_TARGET_AMD64_) && defined(LATE_DISASM)
449             genAmd64EmitterUnitTests();
450 #elif defined(_TARGET_ARM64_)
451             genArm64EmitterUnitTests();
452 #endif // _TARGET_ARM64_
453         }
454 #endif // defined(DEBUG)
455
456         // It is possible to reach the end of the block without generating code for the current IL offset.
457         // For example, if the following IR ends the current block, no code will have been generated for
458         // offset 21:
459         //
460         //          (  0,  0) [000040] ------------                il_offset void   IL offset: 21
461         //
462         //     N001 (  0,  0) [000039] ------------                nop       void
463         //
464         // This can lead to problems when debugging the generated code. To prevent these issues, make sure
465         // we've generated code for the last IL offset we saw in the block.
466         genEnsureCodeEmitted(currentILOffset);
467
468         if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0))
469         {
470             siEndBlock(block);
471
472             /* Is this the last block, and are there any open scopes left ? */
473
474             bool isLastBlockProcessed = (block->bbNext == nullptr);
475             if (block->isBBCallAlwaysPair())
476             {
477                 isLastBlockProcessed = (block->bbNext->bbNext == nullptr);
478             }
479
480             if (isLastBlockProcessed && siOpenScopeList.scNext)
481             {
482                 /* This assert no longer holds, because we may insert a throw
483                    block to demarcate the end of a try or finally region when they
484                    are at the end of the method.  It would be nice if we could fix
485                    our code so that this throw block will no longer be necessary. */
486
487                 // noway_assert(block->bbCodeOffsEnd != compiler->info.compILCodeSize);
488
489                 siCloseAllOpenScopes();
490             }
491         }
492
493         SubtractStackLevel(savedStkLvl);
494
495 #ifdef DEBUG
496         // compCurLife should be equal to the liveOut set, except that we don't keep
497         // it up to date for vars that are not register candidates
498         // (it would be nice to have a xor set function)
499
500         VARSET_TP extraLiveVars(VarSetOps::Diff(compiler, block->bbLiveOut, compiler->compCurLife));
501         VarSetOps::UnionD(compiler, extraLiveVars, VarSetOps::Diff(compiler, compiler->compCurLife, block->bbLiveOut));
502         VarSetOps::Iter extraLiveVarIter(compiler, extraLiveVars);
503         unsigned        extraLiveVarIndex = 0;
504         while (extraLiveVarIter.NextElem(&extraLiveVarIndex))
505         {
506             unsigned   varNum = compiler->lvaTrackedToVarNum[extraLiveVarIndex];
507             LclVarDsc* varDsc = compiler->lvaTable + varNum;
508             assert(!varDsc->lvIsRegCandidate());
509         }
510 #endif
511
512         /* Both stacks should always be empty on exit from a basic block */
513         noway_assert(genStackLevel == 0);
514
515 #ifdef _TARGET_AMD64_
516         // On AMD64, we need to generate a NOP after a call that is the last instruction of the block, in several
517         // situations, to support proper exception handling semantics. This is mostly to ensure that when the stack
518         // walker computes an instruction pointer for a frame, that instruction pointer is in the correct EH region.
519         // The document "X64 and ARM ABIs.docx" has more details. The situations:
520         // 1. If the call instruction is in a different EH region as the instruction that follows it.
521         // 2. If the call immediately precedes an OS epilog. (Note that what the JIT or VM consider an epilog might
522         //    be slightly different from what the OS considers an epilog, and it is the OS-reported epilog that matters
523         //    here.)
524         // We handle case #1 here, and case #2 in the emitter.
525         if (getEmitter()->emitIsLastInsCall())
526         {
527             // Ok, the last instruction generated is a call instruction. Do any of the other conditions hold?
528             // Note: we may be generating a few too many NOPs for the case of call preceding an epilog. Technically,
529             // if the next block is a BBJ_RETURN, an epilog will be generated, but there may be some instructions
530             // generated before the OS epilog starts, such as a GS cookie check.
531             if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext))
532             {
533                 // We only need the NOP if we're not going to generate any more code as part of the block end.
534
535                 switch (block->bbJumpKind)
536                 {
537                     case BBJ_ALWAYS:
538                     case BBJ_THROW:
539                     case BBJ_CALLFINALLY:
540                     case BBJ_EHCATCHRET:
541                     // We're going to generate more code below anyway, so no need for the NOP.
542
543                     case BBJ_RETURN:
544                     case BBJ_EHFINALLYRET:
545                     case BBJ_EHFILTERRET:
546                         // These are the "epilog follows" case, handled in the emitter.
547
548                         break;
549
550                     case BBJ_NONE:
551                         if (block->bbNext == nullptr)
552                         {
553                             // Call immediately before the end of the code; we should never get here    .
554                             instGen(INS_BREAKPOINT); // This should never get executed
555                         }
556                         else
557                         {
558                             // We need the NOP
559                             instGen(INS_nop);
560                         }
561                         break;
562
563                     case BBJ_COND:
564                     case BBJ_SWITCH:
565                     // These can't have a call as the last instruction!
566
567                     default:
568                         noway_assert(!"Unexpected bbJumpKind");
569                         break;
570                 }
571             }
572         }
573 #endif // _TARGET_AMD64_
574
575         /* Do we need to generate a jump or return? */
576
577         switch (block->bbJumpKind)
578         {
579             case BBJ_ALWAYS:
580                 inst_JMP(EJ_jmp, block->bbJumpDest);
581                 break;
582
583             case BBJ_RETURN:
584                 genExitCode(block);
585                 break;
586
587             case BBJ_THROW:
588                 // If we have a throw at the end of a function or funclet, we need to emit another instruction
589                 // afterwards to help the OS unwinder determine the correct context during unwind.
590                 // We insert an unexecuted breakpoint instruction in several situations
591                 // following a throw instruction:
592                 // 1. If the throw is the last instruction of the function or funclet. This helps
593                 //    the OS unwinder determine the correct context during an unwind from the
594                 //    thrown exception.
595                 // 2. If this is this is the last block of the hot section.
596                 // 3. If the subsequent block is a special throw block.
597                 // 4. On AMD64, if the next block is in a different EH region.
598                 if ((block->bbNext == nullptr) || (block->bbNext->bbFlags & BBF_FUNCLET_BEG) ||
599                     !BasicBlock::sameEHRegion(block, block->bbNext) ||
600                     (!isFramePointerUsed() && compiler->fgIsThrowHlpBlk(block->bbNext)) ||
601                     block->bbNext == compiler->fgFirstColdBlock)
602                 {
603                     instGen(INS_BREAKPOINT); // This should never get executed
604                 }
605                 // Do likewise for blocks that end in DOES_NOT_RETURN calls
606                 // that were not caught by the above rules. This ensures that
607                 // gc register liveness doesn't change across call instructions
608                 // in fully-interruptible mode.
609                 else
610                 {
611                     GenTree* call = block->lastNode();
612
613                     if ((call != nullptr) && (call->gtOper == GT_CALL))
614                     {
615                         if ((call->gtCall.gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN) != 0)
616                         {
617                             instGen(INS_BREAKPOINT); // This should never get executed
618                         }
619                     }
620                 }
621
622                 break;
623
624             case BBJ_CALLFINALLY:
625                 block = genCallFinally(block);
626                 break;
627
628 #if FEATURE_EH_FUNCLETS
629
630             case BBJ_EHCATCHRET:
631                 genEHCatchRet(block);
632                 __fallthrough;
633
634             case BBJ_EHFINALLYRET:
635             case BBJ_EHFILTERRET:
636                 genReserveFuncletEpilog(block);
637                 break;
638
639 #else // !FEATURE_EH_FUNCLETS
640
641             case BBJ_EHCATCHRET:
642                 noway_assert(!"Unexpected BBJ_EHCATCHRET"); // not used on x86
643
644             case BBJ_EHFINALLYRET:
645             case BBJ_EHFILTERRET:
646                 genEHFinallyOrFilterRet(block);
647                 break;
648
649 #endif // !FEATURE_EH_FUNCLETS
650
651             case BBJ_NONE:
652             case BBJ_COND:
653             case BBJ_SWITCH:
654                 break;
655
656             default:
657                 noway_assert(!"Unexpected bbJumpKind");
658                 break;
659         }
660
661 #ifdef DEBUG
662         compiler->compCurBB = nullptr;
663 #endif
664
665     } //------------------ END-FOR each block of the method -------------------
666
667     /* Nothing is live at this point */
668     genUpdateLife(VarSetOps::MakeEmpty(compiler));
669
670     /* Finalize the spill  tracking logic */
671
672     regSet.rsSpillEnd();
673
674     /* Finalize the temp   tracking logic */
675
676     compiler->tmpEnd();
677
678 #ifdef DEBUG
679     if (compiler->verbose)
680     {
681         printf("\n# ");
682         printf("compCycleEstimate = %6d, compSizeEstimate = %5d ", compiler->compCycleEstimate,
683                compiler->compSizeEstimate);
684         printf("%s\n", compiler->info.compFullName);
685     }
686 #endif
687 }
688
689 /*
690 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
691 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
692 XX                                                                           XX
693 XX                         Register Management                               XX
694 XX                                                                           XX
695 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
696 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
697 */
698 //
699
700 //------------------------------------------------------------------------
701 // genGetAssignedReg: Get the register assigned to the given node
702 //
703 // Arguments:
704 //    tree      - the lclVar node whose assigned register we want
705 //
706 // Return Value:
707 //    The assigned regNumber
708 //
709 regNumber CodeGenInterface::genGetAssignedReg(GenTree* tree)
710 {
711     return tree->gtRegNum;
712 }
713
714 //------------------------------------------------------------------------
715 // genSpillVar: Spill a local variable
716 //
717 // Arguments:
718 //    tree      - the lclVar node for the variable being spilled
719 //
720 // Return Value:
721 //    None.
722 //
723 // Assumptions:
724 //    The lclVar must be a register candidate (lvRegCandidate)
725
726 void CodeGen::genSpillVar(GenTree* tree)
727 {
728     unsigned   varNum = tree->gtLclVarCommon.gtLclNum;
729     LclVarDsc* varDsc = &(compiler->lvaTable[varNum]);
730
731     assert(varDsc->lvIsRegCandidate());
732
733     // We don't actually need to spill if it is already living in memory
734     bool needsSpill = ((tree->gtFlags & GTF_VAR_DEF) == 0 && varDsc->lvIsInReg());
735     if (needsSpill)
736     {
737         // In order for a lclVar to have been allocated to a register, it must not have been aliasable, and can
738         // therefore be store-normalized (rather than load-normalized). In fact, not performing store normalization
739         // can lead to problems on architectures where a lclVar may be allocated to a register that is not
740         // addressable at the granularity of the lclVar's defined type (e.g. x86).
741         var_types lclTyp = genActualType(varDsc->TypeGet());
742         emitAttr  size   = emitTypeSize(lclTyp);
743
744         bool restoreRegVar = false;
745         if (tree->gtOper == GT_REG_VAR)
746         {
747             tree->SetOper(GT_LCL_VAR);
748             restoreRegVar = true;
749         }
750
751         instruction storeIns = ins_Store(lclTyp, compiler->isSIMDTypeLocalAligned(varNum));
752 #if CPU_LONG_USES_REGPAIR
753         if (varTypeIsMultiReg(tree))
754         {
755             assert(varDsc->lvRegNum == genRegPairLo(tree->gtRegPair));
756             assert(varDsc->lvOtherReg == genRegPairHi(tree->gtRegPair));
757             regNumber regLo = genRegPairLo(tree->gtRegPair);
758             regNumber regHi = genRegPairHi(tree->gtRegPair);
759             inst_TT_RV(storeIns, tree, regLo);
760             inst_TT_RV(storeIns, tree, regHi, 4);
761         }
762         else
763 #endif
764         {
765             assert(varDsc->lvRegNum == tree->gtRegNum);
766             inst_TT_RV(storeIns, tree, tree->gtRegNum, 0, size);
767         }
768
769         if (restoreRegVar)
770         {
771             tree->SetOper(GT_REG_VAR);
772         }
773
774         genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(tree));
775         gcInfo.gcMarkRegSetNpt(varDsc->lvRegMask());
776
777         if (VarSetOps::IsMember(compiler, gcInfo.gcTrkStkPtrLcls, varDsc->lvVarIndex))
778         {
779 #ifdef DEBUG
780             if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
781             {
782                 JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum);
783             }
784             else
785             {
786                 JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum);
787             }
788 #endif
789             VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
790         }
791     }
792
793     tree->gtFlags &= ~GTF_SPILL;
794     varDsc->lvRegNum = REG_STK;
795     if (varTypeIsMultiReg(tree))
796     {
797         varDsc->lvOtherReg = REG_STK;
798     }
799 }
800
801 //------------------------------------------------------------------------
802 // genUpdateVarReg: Update the current register location for a lclVar
803 //
804 // Arguments:
805 //    varDsc - the LclVarDsc for the lclVar
806 //    tree   - the lclVar node
807 //
808 // inline
809 void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTree* tree)
810 {
811     assert(tree->OperIsScalarLocal() || (tree->gtOper == GT_COPY));
812     varDsc->lvRegNum = tree->gtRegNum;
813 }
814
815 //------------------------------------------------------------------------
816 // sameRegAsDst: Return the child that has the same reg as the dst (if any)
817 //
818 // Arguments:
819 //    tree  - the node of interest
820 //    other - an out parameter to return the other child
821 //
822 // Notes:
823 //    If 'tree' has a child with the same assigned register as its target reg,
824 //    that child will be returned, and 'other' will contain the non-matching child.
825 //    Otherwise, both other and the return value will be nullptr.
826 //
827 GenTree* sameRegAsDst(GenTree* tree, GenTree*& other /*out*/)
828 {
829     if (tree->gtRegNum == REG_NA)
830     {
831         other = nullptr;
832         return nullptr;
833     }
834
835     GenTree* op1 = tree->gtOp.gtOp1;
836     GenTree* op2 = tree->gtOp.gtOp2;
837     if (op1->gtRegNum == tree->gtRegNum)
838     {
839         other = op2;
840         return op1;
841     }
842     if (op2->gtRegNum == tree->gtRegNum)
843     {
844         other = op1;
845         return op2;
846     }
847     else
848     {
849         other = nullptr;
850         return nullptr;
851     }
852 }
853
854 //------------------------------------------------------------------------
855 // genUnspillRegIfNeeded: Reload the value into a register, if needed
856 //
857 // Arguments:
858 //    tree - the node of interest.
859 //
860 // Notes:
861 //    In the normal case, the value will be reloaded into the register it
862 //    was originally computed into. However, if that register is not available,
863 //    the register allocator will have allocated a different register, and
864 //    inserted a GT_RELOAD to indicate the register into which it should be
865 //    reloaded.
866 //
867 void CodeGen::genUnspillRegIfNeeded(GenTree* tree)
868 {
869     regNumber dstReg      = tree->gtRegNum;
870     GenTree*  unspillTree = tree;
871
872     if (tree->gtOper == GT_RELOAD)
873     {
874         unspillTree = tree->gtOp.gtOp1;
875     }
876
877     if ((unspillTree->gtFlags & GTF_SPILLED) != 0)
878     {
879         if (genIsRegCandidateLocal(unspillTree))
880         {
881             // Reset spilled flag, since we are going to load a local variable from its home location.
882             unspillTree->gtFlags &= ~GTF_SPILLED;
883
884             GenTreeLclVarCommon* lcl    = unspillTree->AsLclVarCommon();
885             LclVarDsc*           varDsc = &compiler->lvaTable[lcl->gtLclNum];
886
887 // TODO-Cleanup: The following code could probably be further merged and cleaned up.
888 #ifdef _TARGET_XARCH_
889             // Load local variable from its home location.
890             // In most cases the tree type will indicate the correct type to use for the load.
891             // However, if it is NOT a normalizeOnLoad lclVar (i.e. NOT a small int that always gets
892             // widened when loaded into a register), and its size is not the same as genActualType of
893             // the type of the lclVar, then we need to change the type of the tree node when loading.
894             // This situation happens due to "optimizations" that avoid a cast and
895             // simply retype the node when using long type lclVar as an int.
896             // While loading the int in that case would work for this use of the lclVar, if it is
897             // later used as a long, we will have incorrectly truncated the long.
898             // In the normalizeOnLoad case ins_Load will return an appropriate sign- or zero-
899             // extending load.
900
901             var_types treeType = unspillTree->TypeGet();
902             if (treeType != genActualType(varDsc->lvType) && !varTypeIsGC(treeType) && !varDsc->lvNormalizeOnLoad())
903             {
904                 assert(!varTypeIsGC(varDsc));
905                 var_types spillType = genActualType(varDsc->lvType);
906                 unspillTree->gtType = spillType;
907                 inst_RV_TT(ins_Load(spillType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), dstReg, unspillTree);
908                 unspillTree->gtType = treeType;
909             }
910             else
911             {
912                 inst_RV_TT(ins_Load(treeType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)), dstReg, unspillTree);
913             }
914 #elif defined(_TARGET_ARM64_)
915             var_types targetType = unspillTree->gtType;
916             if (targetType != genActualType(varDsc->lvType) && !varTypeIsGC(targetType) && !varDsc->lvNormalizeOnLoad())
917             {
918                 assert(!varTypeIsGC(varDsc));
919                 targetType = genActualType(varDsc->lvType);
920             }
921             instruction ins  = ins_Load(targetType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum));
922             emitAttr    attr = emitTypeSize(targetType);
923             emitter*    emit = getEmitter();
924
925             // Fixes Issue #3326
926             attr = varTypeIsFloating(targetType) ? attr : emit->emitInsAdjustLoadStoreAttr(ins, attr);
927
928             // Load local variable from its home location.
929             inst_RV_TT(ins, dstReg, unspillTree, 0, attr);
930 #elif defined(_TARGET_ARM_)
931             var_types   targetType = unspillTree->gtType;
932             instruction ins        = ins_Load(targetType, compiler->isSIMDTypeLocalAligned(lcl->gtLclNum));
933             emitAttr    attr       = emitTypeSize(targetType);
934
935             // Load local variable from its home location.
936             inst_RV_TT(ins, dstReg, unspillTree, 0, attr);
937 #else
938             NYI("Unspilling not implemented for this target architecture.");
939 #endif
940
941             // TODO-Review: We would like to call:
942             //      genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(tree));
943             // instead of the following code, but this ends up hitting this assert:
944             //      assert((regSet.rsMaskVars & regMask) == 0);
945             // due to issues with LSRA resolution moves.
946             // So, just force it for now. This probably indicates a condition that creates a GC hole!
947             //
948             // Extra note: I think we really want to call something like gcInfo.gcUpdateForRegVarMove,
949             // because the variable is not really going live or dead, but that method is somewhat poorly
950             // factored because it, in turn, updates rsMaskVars which is part of RegSet not GCInfo.
951             // TODO-Cleanup: This code exists in other CodeGen*.cpp files, and should be moved to CodeGenCommon.cpp.
952
953             // Don't update the variable's location if we are just re-spilling it again.
954
955             if ((unspillTree->gtFlags & GTF_SPILL) == 0)
956             {
957                 genUpdateVarReg(varDsc, tree);
958 #ifdef DEBUG
959                 if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
960                 {
961                     JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", lcl->gtLclNum);
962                 }
963 #endif // DEBUG
964                 VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
965
966 #ifdef DEBUG
967                 if (compiler->verbose)
968                 {
969                     printf("\t\t\t\t\t\t\tV%02u in reg ", lcl->gtLclNum);
970                     varDsc->PrintVarReg();
971                     printf(" is becoming live  ");
972                     compiler->printTreeID(unspillTree);
973                     printf("\n");
974                 }
975 #endif // DEBUG
976
977                 regSet.AddMaskVars(genGetRegMask(varDsc));
978             }
979
980             gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet());
981         }
982         else if (unspillTree->IsMultiRegCall())
983         {
984             GenTreeCall*         call        = unspillTree->AsCall();
985             ReturnTypeDesc*      retTypeDesc = call->GetReturnTypeDesc();
986             unsigned             regCount    = retTypeDesc->GetReturnRegCount();
987             GenTreeCopyOrReload* reloadTree  = nullptr;
988             if (tree->OperGet() == GT_RELOAD)
989             {
990                 reloadTree = tree->AsCopyOrReload();
991             }
992
993             // In case of multi-reg call node, GTF_SPILLED flag on it indicates that
994             // one or more of its result regs are spilled.  Call node needs to be
995             // queried to know which specific result regs to be unspilled.
996             for (unsigned i = 0; i < regCount; ++i)
997             {
998                 unsigned flags = call->GetRegSpillFlagByIdx(i);
999                 if ((flags & GTF_SPILLED) != 0)
1000                 {
1001                     var_types dstType        = retTypeDesc->GetReturnRegType(i);
1002                     regNumber unspillTreeReg = call->GetRegNumByIdx(i);
1003
1004                     if (reloadTree != nullptr)
1005                     {
1006                         dstReg = reloadTree->GetRegNumByIdx(i);
1007                         if (dstReg == REG_NA)
1008                         {
1009                             dstReg = unspillTreeReg;
1010                         }
1011                     }
1012                     else
1013                     {
1014                         dstReg = unspillTreeReg;
1015                     }
1016
1017                     TempDsc* t = regSet.rsUnspillInPlace(call, unspillTreeReg, i);
1018                     getEmitter()->emitIns_R_S(ins_Load(dstType), emitActualTypeSize(dstType), dstReg, t->tdTempNum(),
1019                                               0);
1020                     compiler->tmpRlsTemp(t);
1021                     gcInfo.gcMarkRegPtrVal(dstReg, dstType);
1022                 }
1023             }
1024
1025             unspillTree->gtFlags &= ~GTF_SPILLED;
1026         }
1027 #ifdef _TARGET_ARM_
1028         else if (unspillTree->OperIsPutArgSplit())
1029         {
1030             GenTreePutArgSplit* splitArg = unspillTree->AsPutArgSplit();
1031             unsigned            regCount = splitArg->gtNumRegs;
1032
1033             // In case of split struct argument node, GTF_SPILLED flag on it indicates that
1034             // one or more of its result regs are spilled.  Call node needs to be
1035             // queried to know which specific result regs to be unspilled.
1036             for (unsigned i = 0; i < regCount; ++i)
1037             {
1038                 unsigned flags = splitArg->GetRegSpillFlagByIdx(i);
1039                 if ((flags & GTF_SPILLED) != 0)
1040                 {
1041                     BYTE*     gcPtrs  = splitArg->gtGcPtrs;
1042                     var_types dstType = splitArg->GetRegType(i);
1043                     regNumber dstReg  = splitArg->GetRegNumByIdx(i);
1044
1045                     TempDsc* t = regSet.rsUnspillInPlace(splitArg, dstReg, i);
1046                     getEmitter()->emitIns_R_S(ins_Load(dstType), emitActualTypeSize(dstType), dstReg, t->tdTempNum(),
1047                                               0);
1048                     compiler->tmpRlsTemp(t);
1049                     gcInfo.gcMarkRegPtrVal(dstReg, dstType);
1050                 }
1051             }
1052
1053             unspillTree->gtFlags &= ~GTF_SPILLED;
1054         }
1055         else if (unspillTree->OperIsMultiRegOp())
1056         {
1057             GenTreeMultiRegOp* multiReg = unspillTree->AsMultiRegOp();
1058             unsigned           regCount = multiReg->GetRegCount();
1059
1060             // In case of split struct argument node, GTF_SPILLED flag on it indicates that
1061             // one or more of its result regs are spilled.  Call node needs to be
1062             // queried to know which specific result regs to be unspilled.
1063             for (unsigned i = 0; i < regCount; ++i)
1064             {
1065                 unsigned flags = multiReg->GetRegSpillFlagByIdx(i);
1066                 if ((flags & GTF_SPILLED) != 0)
1067                 {
1068                     var_types dstType = multiReg->GetRegType(i);
1069                     regNumber dstReg  = multiReg->GetRegNumByIdx(i);
1070
1071                     TempDsc* t = regSet.rsUnspillInPlace(multiReg, dstReg, i);
1072                     getEmitter()->emitIns_R_S(ins_Load(dstType), emitActualTypeSize(dstType), dstReg, t->tdTempNum(),
1073                                               0);
1074                     compiler->tmpRlsTemp(t);
1075                     gcInfo.gcMarkRegPtrVal(dstReg, dstType);
1076                 }
1077             }
1078
1079             unspillTree->gtFlags &= ~GTF_SPILLED;
1080         }
1081 #endif
1082         else
1083         {
1084             TempDsc* t = regSet.rsUnspillInPlace(unspillTree, unspillTree->gtRegNum);
1085             getEmitter()->emitIns_R_S(ins_Load(unspillTree->gtType), emitActualTypeSize(unspillTree->TypeGet()), dstReg,
1086                                       t->tdTempNum(), 0);
1087             compiler->tmpRlsTemp(t);
1088
1089             unspillTree->gtFlags &= ~GTF_SPILLED;
1090             gcInfo.gcMarkRegPtrVal(dstReg, unspillTree->TypeGet());
1091         }
1092     }
1093 }
1094
1095 //------------------------------------------------------------------------
1096 // genCopyRegIfNeeded: Copy the given node into the specified register
1097 //
1098 // Arguments:
1099 //    node - The node that has been evaluated (consumed).
1100 //    needReg - The register in which its value is needed.
1101 //
1102 // Notes:
1103 //    This must be a node that has a register.
1104 //
1105 void CodeGen::genCopyRegIfNeeded(GenTree* node, regNumber needReg)
1106 {
1107     assert((node->gtRegNum != REG_NA) && (needReg != REG_NA));
1108     assert(!node->isUsedFromSpillTemp());
1109     if (node->gtRegNum != needReg)
1110     {
1111         inst_RV_RV(INS_mov, needReg, node->gtRegNum, node->TypeGet());
1112     }
1113 }
1114
1115 // Do Liveness update for a subnodes that is being consumed by codegen
1116 // including the logic for reload in case is needed and also takes care
1117 // of locating the value on the desired register.
1118 void CodeGen::genConsumeRegAndCopy(GenTree* node, regNumber needReg)
1119 {
1120     if (needReg == REG_NA)
1121     {
1122         return;
1123     }
1124     regNumber treeReg = genConsumeReg(node);
1125     genCopyRegIfNeeded(node, needReg);
1126 }
1127
1128 // Check that registers are consumed in the right order for the current node being generated.
1129 #ifdef DEBUG
1130 void CodeGen::genNumberOperandUse(GenTree* const operand, int& useNum) const
1131 {
1132     assert(operand != nullptr);
1133
1134     // Ignore argument placeholders.
1135     if (operand->OperGet() == GT_ARGPLACE)
1136     {
1137         return;
1138     }
1139
1140     assert(operand->gtUseNum == -1);
1141
1142     if (!operand->isContained() && !operand->IsCopyOrReload())
1143     {
1144         operand->gtUseNum = useNum;
1145         useNum++;
1146     }
1147     else
1148     {
1149         for (GenTree* operand : operand->Operands())
1150         {
1151             genNumberOperandUse(operand, useNum);
1152         }
1153     }
1154 }
1155
1156 void CodeGen::genCheckConsumeNode(GenTree* const node)
1157 {
1158     assert(node != nullptr);
1159
1160     if (verbose)
1161     {
1162         if (node->gtUseNum == -1)
1163         {
1164             // nothing wrong if the node was not consumed
1165         }
1166         else if ((node->gtDebugFlags & GTF_DEBUG_NODE_CG_CONSUMED) != 0)
1167         {
1168             printf("Node was consumed twice:\n");
1169             compiler->gtDispTree(node, nullptr, nullptr, true);
1170         }
1171         else if ((lastConsumedNode != nullptr) && (node->gtUseNum < lastConsumedNode->gtUseNum))
1172         {
1173             printf("Nodes were consumed out-of-order:\n");
1174             compiler->gtDispTree(lastConsumedNode, nullptr, nullptr, true);
1175             compiler->gtDispTree(node, nullptr, nullptr, true);
1176         }
1177     }
1178
1179     assert((node->OperGet() == GT_CATCH_ARG) || ((node->gtDebugFlags & GTF_DEBUG_NODE_CG_CONSUMED) == 0));
1180     assert((lastConsumedNode == nullptr) || (node->gtUseNum == -1) || (node->gtUseNum > lastConsumedNode->gtUseNum));
1181
1182     node->gtDebugFlags |= GTF_DEBUG_NODE_CG_CONSUMED;
1183     lastConsumedNode = node;
1184 }
1185 #endif // DEBUG
1186
1187 //--------------------------------------------------------------------
1188 // genConsumeReg: Do liveness update for a subnode that is being
1189 // consumed by codegen.
1190 //
1191 // Arguments:
1192 //    tree - GenTree node
1193 //
1194 // Return Value:
1195 //    Returns the reg number of tree.
1196 //    In case of multi-reg call node returns the first reg number
1197 //    of the multi-reg return.
1198 regNumber CodeGen::genConsumeReg(GenTree* tree)
1199 {
1200     if (tree->OperGet() == GT_COPY)
1201     {
1202         genRegCopy(tree);
1203     }
1204
1205     // Handle the case where we have a lclVar that needs to be copied before use (i.e. because it
1206     // interferes with one of the other sources (or the target, if it's a "delayed use" register)).
1207     // TODO-Cleanup: This is a special copyReg case in LSRA - consider eliminating these and
1208     // always using GT_COPY to make the lclVar location explicit.
1209     // Note that we have to do this before calling genUpdateLife because otherwise if we spill it
1210     // the lvRegNum will be set to REG_STK and we will lose track of what register currently holds
1211     // the lclVar (normally when a lclVar is spilled it is then used from its former register
1212     // location, which matches the gtRegNum on the node).
1213     // (Note that it doesn't matter if we call this before or after genUnspillRegIfNeeded
1214     // because if it's on the stack it will always get reloaded into tree->gtRegNum).
1215     if (genIsRegCandidateLocal(tree))
1216     {
1217         GenTreeLclVarCommon* lcl    = tree->AsLclVarCommon();
1218         LclVarDsc*           varDsc = &compiler->lvaTable[lcl->GetLclNum()];
1219         if (varDsc->lvRegNum != REG_STK && varDsc->lvRegNum != tree->gtRegNum)
1220         {
1221             inst_RV_RV(ins_Copy(tree->TypeGet()), tree->gtRegNum, varDsc->lvRegNum);
1222         }
1223     }
1224
1225     genUnspillRegIfNeeded(tree);
1226
1227     // genUpdateLife() will also spill local var if marked as GTF_SPILL by calling CodeGen::genSpillVar
1228     genUpdateLife(tree);
1229
1230     assert(tree->gtHasReg());
1231
1232     // there are three cases where consuming a reg means clearing the bit in the live mask
1233     // 1. it was not produced by a local
1234     // 2. it was produced by a local that is going dead
1235     // 3. it was produced by a local that does not live in that reg (like one allocated on the stack)
1236
1237     if (genIsRegCandidateLocal(tree))
1238     {
1239         GenTreeLclVarCommon* lcl    = tree->AsLclVarCommon();
1240         LclVarDsc*           varDsc = &compiler->lvaTable[lcl->GetLclNum()];
1241         assert(varDsc->lvLRACandidate);
1242
1243         if ((tree->gtFlags & GTF_VAR_DEATH) != 0)
1244         {
1245             gcInfo.gcMarkRegSetNpt(genRegMask(varDsc->lvRegNum));
1246         }
1247         else if (varDsc->lvRegNum == REG_STK)
1248         {
1249             // We have loaded this into a register only temporarily
1250             gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum));
1251         }
1252     }
1253     else
1254     {
1255         gcInfo.gcMarkRegSetNpt(tree->gtGetRegMask());
1256     }
1257
1258     genCheckConsumeNode(tree);
1259     return tree->gtRegNum;
1260 }
1261
1262 // Do liveness update for an address tree: one of GT_LEA, GT_LCL_VAR, or GT_CNS_INT (for call indirect).
1263 void CodeGen::genConsumeAddress(GenTree* addr)
1264 {
1265     if (!addr->isContained())
1266     {
1267         genConsumeReg(addr);
1268     }
1269     else if (addr->OperGet() == GT_LEA)
1270     {
1271         genConsumeAddrMode(addr->AsAddrMode());
1272     }
1273 }
1274
1275 // do liveness update for a subnode that is being consumed by codegen
1276 void CodeGen::genConsumeAddrMode(GenTreeAddrMode* addr)
1277 {
1278     genConsumeOperands(addr);
1279 }
1280
1281 void CodeGen::genConsumeRegs(GenTree* tree)
1282 {
1283 #if !defined(_TARGET_64BIT_)
1284     if (tree->OperGet() == GT_LONG)
1285     {
1286         genConsumeRegs(tree->gtGetOp1());
1287         genConsumeRegs(tree->gtGetOp2());
1288         return;
1289     }
1290 #endif // !defined(_TARGET_64BIT_)
1291
1292     if (tree->isUsedFromSpillTemp())
1293     {
1294         // spill temps are un-tracked and hence no need to update life
1295     }
1296     else if (tree->isContained())
1297     {
1298         if (tree->isIndir())
1299         {
1300             genConsumeAddress(tree->AsIndir()->Addr());
1301         }
1302 #ifdef _TARGET_XARCH_
1303         else if (tree->OperIsLocalRead())
1304         {
1305             // A contained lcl var must be living on stack and marked as reg optional, or not be a
1306             // register candidate.
1307             unsigned   varNum = tree->AsLclVarCommon()->GetLclNum();
1308             LclVarDsc* varDsc = compiler->lvaTable + varNum;
1309
1310             noway_assert(varDsc->lvRegNum == REG_STK);
1311             noway_assert(tree->IsRegOptional() || !varDsc->lvLRACandidate);
1312
1313             // Update the life of the lcl var.
1314             genUpdateLife(tree);
1315         }
1316 #endif // _TARGET_XARCH_
1317         else if (tree->OperIsInitVal())
1318         {
1319             genConsumeReg(tree->gtGetOp1());
1320         }
1321         else if (tree->OperIsHWIntrinsic())
1322         {
1323             genConsumeReg(tree->gtGetOp1());
1324         }
1325         else
1326         {
1327 #ifdef FEATURE_SIMD
1328             // (In)Equality operation that produces bool result, when compared
1329             // against Vector zero, marks its Vector Zero operand as contained.
1330             assert(tree->OperIsLeaf() || tree->IsIntegralConstVector(0));
1331 #else
1332             assert(tree->OperIsLeaf());
1333 #endif
1334         }
1335     }
1336     else
1337     {
1338         genConsumeReg(tree);
1339     }
1340 }
1341
1342 //------------------------------------------------------------------------
1343 // genConsumeOperands: Do liveness update for the operands of a unary or binary tree
1344 //
1345 // Arguments:
1346 //    tree - the GenTreeOp whose operands will have their liveness updated.
1347 //
1348 // Return Value:
1349 //    None.
1350 //
1351 // Notes:
1352 //    Note that this logic is localized here because we must do the liveness update in
1353 //    the correct execution order.  This is important because we may have two operands
1354 //    that involve the same lclVar, and if one is marked "lastUse" we must handle it
1355 //    after the first.
1356
1357 void CodeGen::genConsumeOperands(GenTreeOp* tree)
1358 {
1359     GenTree* firstOp  = tree->gtOp1;
1360     GenTree* secondOp = tree->gtOp2;
1361
1362     if (firstOp != nullptr)
1363     {
1364         genConsumeRegs(firstOp);
1365     }
1366     if (secondOp != nullptr)
1367     {
1368         genConsumeRegs(secondOp);
1369     }
1370 }
1371
1372 #if FEATURE_PUT_STRUCT_ARG_STK
1373 //------------------------------------------------------------------------
1374 // genConsumePutStructArgStk: Do liveness update for the operands of a PutArgStk node.
1375 //                      Also loads in the right register the addresses of the
1376 //                      src/dst for rep mov operation.
1377 //
1378 // Arguments:
1379 //    putArgNode - the PUTARG_STK tree.
1380 //    dstReg     - the dstReg for the rep move operation.
1381 //    srcReg     - the srcReg for the rep move operation.
1382 //    sizeReg    - the sizeReg for the rep move operation.
1383 //
1384 // Return Value:
1385 //    None.
1386 //
1387 // Notes:
1388 //    sizeReg can be REG_NA when this function is used to consume the dstReg and srcReg
1389 //    for copying on the stack a struct with references.
1390 //    The source address/offset is determined from the address on the GT_OBJ node, while
1391 //    the destination address is the address contained in 'm_stkArgVarNum' plus the offset
1392 //    provided in the 'putArgNode'.
1393 //    m_stkArgVarNum must be set to  the varnum for the local used for placing the "by-value" args on the stack.
1394
1395 void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode,
1396                                         regNumber         dstReg,
1397                                         regNumber         srcReg,
1398                                         regNumber         sizeReg)
1399 {
1400     // The putArgNode children are always contained. We should not consume any registers.
1401     assert(putArgNode->gtGetOp1()->isContained());
1402
1403     // Get the source address.
1404     GenTree* src = putArgNode->gtGetOp1();
1405     assert(varTypeIsStruct(src));
1406     assert((src->gtOper == GT_OBJ) || ((src->gtOper == GT_IND && varTypeIsSIMD(src))));
1407     GenTree* srcAddr = src->gtGetOp1();
1408
1409     size_t size = putArgNode->getArgSize();
1410
1411     assert(dstReg != REG_NA);
1412     assert(srcReg != REG_NA);
1413
1414     // Consume the registers only if they are not contained or set to REG_NA.
1415     if (srcAddr->gtRegNum != REG_NA)
1416     {
1417         genConsumeReg(srcAddr);
1418     }
1419
1420     // If the op1 is already in the dstReg - nothing to do.
1421     // Otherwise load the op1 (GT_ADDR) into the dstReg to copy the struct on the stack by value.
1422     CLANG_FORMAT_COMMENT_ANCHOR;
1423
1424 #ifdef _TARGET_X86_
1425     assert(dstReg != REG_SPBASE);
1426     inst_RV_RV(INS_mov, dstReg, REG_SPBASE);
1427 #else  // !_TARGET_X86_
1428     GenTree* dstAddr = putArgNode;
1429     if (dstAddr->gtRegNum != dstReg)
1430     {
1431         // Generate LEA instruction to load the stack of the outgoing var + SlotNum offset (or the incoming arg area
1432         // for tail calls) in RDI.
1433         // Destination is always local (on the stack) - use EA_PTRSIZE.
1434         assert(m_stkArgVarNum != BAD_VAR_NUM);
1435         getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, dstReg, m_stkArgVarNum, putArgNode->getArgOffset());
1436     }
1437 #endif // !_TARGET_X86_
1438
1439     if (srcAddr->gtRegNum != srcReg)
1440     {
1441         if (srcAddr->OperIsLocalAddr())
1442         {
1443             // The OperLocalAddr is always contained.
1444             assert(srcAddr->isContained());
1445             GenTreeLclVarCommon* lclNode = srcAddr->AsLclVarCommon();
1446
1447             // Generate LEA instruction to load the LclVar address in RSI.
1448             // Source is known to be on the stack. Use EA_PTRSIZE.
1449             unsigned int offset = 0;
1450             if (srcAddr->OperGet() == GT_LCL_FLD_ADDR)
1451             {
1452                 offset = srcAddr->AsLclFld()->gtLclOffs;
1453             }
1454             getEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, srcReg, lclNode->gtLclNum, offset);
1455         }
1456         else
1457         {
1458             assert(srcAddr->gtRegNum != REG_NA);
1459             // Source is not known to be on the stack. Use EA_BYREF.
1460             getEmitter()->emitIns_R_R(INS_mov, EA_BYREF, srcReg, srcAddr->gtRegNum);
1461         }
1462     }
1463
1464     if (sizeReg != REG_NA)
1465     {
1466         inst_RV_IV(INS_mov, sizeReg, size, EA_PTRSIZE);
1467     }
1468 }
1469 #endif // FEATURE_PUT_STRUCT_ARG_STK
1470
1471 #ifdef _TARGET_ARM_
1472 //------------------------------------------------------------------------
1473 // genConsumeArgRegSplit: Consume register(s) in Call node to set split struct argument.
1474 //                        Liveness update for the PutArgSplit node is not needed
1475 //
1476 // Arguments:
1477 //    putArgNode - the PUTARG_STK tree.
1478 //
1479 // Return Value:
1480 //    None.
1481 //
1482 void CodeGen::genConsumeArgSplitStruct(GenTreePutArgSplit* putArgNode)
1483 {
1484     assert(putArgNode->OperGet() == GT_PUTARG_SPLIT);
1485     assert(putArgNode->gtHasReg());
1486
1487     genUnspillRegIfNeeded(putArgNode);
1488
1489     // Skip updating GC info
1490     // GC info for all argument registers will be cleared in caller
1491
1492     genCheckConsumeNode(putArgNode);
1493 }
1494 #endif
1495
1496 //------------------------------------------------------------------------
1497 // genSetBlockSize: Ensure that the block size is in the given register
1498 //
1499 // Arguments:
1500 //    blkNode - The block node
1501 //    sizeReg - The register into which the block's size should go
1502 //
1503
1504 void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg)
1505 {
1506     if (sizeReg != REG_NA)
1507     {
1508         unsigned blockSize = blkNode->Size();
1509         if (blockSize != 0)
1510         {
1511             assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0);
1512             genSetRegToIcon(sizeReg, blockSize);
1513         }
1514         else
1515         {
1516             noway_assert(blkNode->gtOper == GT_STORE_DYN_BLK);
1517             GenTree* sizeNode = blkNode->AsDynBlk()->gtDynamicSize;
1518             if (sizeNode->gtRegNum != sizeReg)
1519             {
1520                 inst_RV_RV(INS_mov, sizeReg, sizeNode->gtRegNum, sizeNode->TypeGet());
1521             }
1522         }
1523     }
1524 }
1525
1526 //------------------------------------------------------------------------
1527 // genConsumeBlockSrc: Consume the source address register of a block node, if any.
1528 //
1529 // Arguments:
1530 //    blkNode - The block node
1531
1532 void CodeGen::genConsumeBlockSrc(GenTreeBlk* blkNode)
1533 {
1534     GenTree* src = blkNode->Data();
1535     if (blkNode->OperIsCopyBlkOp())
1536     {
1537         // For a CopyBlk we need the address of the source.
1538         if (src->OperGet() == GT_IND)
1539         {
1540             src = src->gtOp.gtOp1;
1541         }
1542         else
1543         {
1544             // This must be a local.
1545             // For this case, there is no source address register, as it is a
1546             // stack-based address.
1547             assert(src->OperIsLocal());
1548             return;
1549         }
1550     }
1551     else
1552     {
1553         if (src->OperIsInitVal())
1554         {
1555             src = src->gtGetOp1();
1556         }
1557     }
1558     genConsumeReg(src);
1559 }
1560
1561 //------------------------------------------------------------------------
1562 // genSetBlockSrc: Ensure that the block source is in its allocated register.
1563 //
1564 // Arguments:
1565 //    blkNode - The block node
1566 //    srcReg  - The register in which to set the source (address or init val).
1567 //
1568 void CodeGen::genSetBlockSrc(GenTreeBlk* blkNode, regNumber srcReg)
1569 {
1570     GenTree* src = blkNode->Data();
1571     if (blkNode->OperIsCopyBlkOp())
1572     {
1573         // For a CopyBlk we need the address of the source.
1574         if (src->OperGet() == GT_IND)
1575         {
1576             src = src->gtOp.gtOp1;
1577         }
1578         else
1579         {
1580             // This must be a local struct.
1581             // Load its address into srcReg.
1582             inst_RV_TT(INS_lea, srcReg, src, 0, EA_BYREF);
1583             return;
1584         }
1585     }
1586     else
1587     {
1588         if (src->OperIsInitVal())
1589         {
1590             src = src->gtGetOp1();
1591         }
1592     }
1593     genCopyRegIfNeeded(src, srcReg);
1594 }
1595
1596 //------------------------------------------------------------------------
1597 // genConsumeBlockOp: Ensure that the block's operands are enregistered
1598 //                    as needed.
1599 // Arguments:
1600 //    blkNode - The block node
1601 //
1602 // Notes:
1603 //    This ensures that the operands are consumed in the proper order to
1604 //    obey liveness modeling.
1605
1606 void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg)
1607 {
1608     // We have to consume the registers, and perform any copies, in the actual execution order: dst, src, size.
1609     //
1610     // Note that the register allocator ensures that the registers ON THE NODES will not interfere
1611     // with one another if consumed (i.e. reloaded or moved to their ASSIGNED reg) in execution order.
1612     // Further, it ensures that they will not interfere with one another if they are then copied
1613     // to the REQUIRED register (if a fixed register requirement) in execution order.  This requires,
1614     // then, that we first consume all the operands, then do any necessary moves.
1615
1616     GenTree* const dstAddr = blkNode->Addr();
1617
1618     // First, consume all the sources in order.
1619     genConsumeReg(dstAddr);
1620     genConsumeBlockSrc(blkNode);
1621     if (blkNode->OperGet() == GT_STORE_DYN_BLK)
1622     {
1623         genConsumeReg(blkNode->AsDynBlk()->gtDynamicSize);
1624     }
1625
1626     // Next, perform any necessary moves.
1627     genCopyRegIfNeeded(dstAddr, dstReg);
1628     genSetBlockSrc(blkNode, srcReg);
1629     genSetBlockSize(blkNode, sizeReg);
1630 }
1631
1632 //-------------------------------------------------------------------------
1633 // genProduceReg: do liveness update for register produced by the current
1634 // node in codegen.
1635 //
1636 // Arguments:
1637 //     tree   -  Gentree node
1638 //
1639 // Return Value:
1640 //     None.
1641 void CodeGen::genProduceReg(GenTree* tree)
1642 {
1643 #ifdef DEBUG
1644     assert((tree->gtDebugFlags & GTF_DEBUG_NODE_CG_PRODUCED) == 0);
1645     tree->gtDebugFlags |= GTF_DEBUG_NODE_CG_PRODUCED;
1646 #endif
1647
1648     if (tree->gtFlags & GTF_SPILL)
1649     {
1650         // Code for GT_COPY node gets generated as part of consuming regs by its parent.
1651         // A GT_COPY node in turn produces reg result and it should never be marked to
1652         // spill.
1653         //
1654         // Similarly GT_RELOAD node gets generated as part of consuming regs by its
1655         // parent and should never be marked for spilling.
1656         noway_assert(!tree->IsCopyOrReload());
1657
1658         if (genIsRegCandidateLocal(tree))
1659         {
1660             // Store local variable to its home location.
1661             // Ensure that lclVar stores are typed correctly.
1662             unsigned varNum = tree->gtLclVarCommon.gtLclNum;
1663             assert(!compiler->lvaTable[varNum].lvNormalizeOnStore() ||
1664                    (tree->TypeGet() == genActualType(compiler->lvaTable[varNum].TypeGet())));
1665             inst_TT_RV(ins_Store(tree->gtType, compiler->isSIMDTypeLocalAligned(varNum)), tree, tree->gtRegNum);
1666         }
1667         else
1668         {
1669             // In case of multi-reg call node, spill flag on call node
1670             // indicates that one or more of its allocated regs need to
1671             // be spilled.  Call node needs to be further queried to
1672             // know which of its result regs needs to be spilled.
1673             if (tree->IsMultiRegCall())
1674             {
1675                 GenTreeCall*    call        = tree->AsCall();
1676                 ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
1677                 unsigned        regCount    = retTypeDesc->GetReturnRegCount();
1678
1679                 for (unsigned i = 0; i < regCount; ++i)
1680                 {
1681                     unsigned flags = call->GetRegSpillFlagByIdx(i);
1682                     if ((flags & GTF_SPILL) != 0)
1683                     {
1684                         regNumber reg = call->GetRegNumByIdx(i);
1685                         regSet.rsSpillTree(reg, call, i);
1686                         gcInfo.gcMarkRegSetNpt(genRegMask(reg));
1687                     }
1688                 }
1689             }
1690 #ifdef _TARGET_ARM_
1691             else if (tree->OperIsPutArgSplit())
1692             {
1693                 GenTreePutArgSplit* argSplit = tree->AsPutArgSplit();
1694                 unsigned            regCount = argSplit->gtNumRegs;
1695
1696                 for (unsigned i = 0; i < regCount; ++i)
1697                 {
1698                     unsigned flags = argSplit->GetRegSpillFlagByIdx(i);
1699                     if ((flags & GTF_SPILL) != 0)
1700                     {
1701                         regNumber reg = argSplit->GetRegNumByIdx(i);
1702                         regSet.rsSpillTree(reg, argSplit, i);
1703                         gcInfo.gcMarkRegSetNpt(genRegMask(reg));
1704                     }
1705                 }
1706             }
1707             else if (tree->OperIsMultiRegOp())
1708             {
1709                 GenTreeMultiRegOp* multiReg = tree->AsMultiRegOp();
1710                 unsigned           regCount = multiReg->GetRegCount();
1711
1712                 for (unsigned i = 0; i < regCount; ++i)
1713                 {
1714                     unsigned flags = multiReg->GetRegSpillFlagByIdx(i);
1715                     if ((flags & GTF_SPILL) != 0)
1716                     {
1717                         regNumber reg = multiReg->GetRegNumByIdx(i);
1718                         regSet.rsSpillTree(reg, multiReg, i);
1719                         gcInfo.gcMarkRegSetNpt(genRegMask(reg));
1720                     }
1721                 }
1722             }
1723 #endif // _TARGET_ARM_
1724             else
1725             {
1726                 regSet.rsSpillTree(tree->gtRegNum, tree);
1727                 gcInfo.gcMarkRegSetNpt(genRegMask(tree->gtRegNum));
1728             }
1729
1730             tree->gtFlags |= GTF_SPILLED;
1731             tree->gtFlags &= ~GTF_SPILL;
1732
1733             return;
1734         }
1735     }
1736
1737     genUpdateLife(tree);
1738
1739     // If we've produced a register, mark it as a pointer, as needed.
1740     if (tree->gtHasReg())
1741     {
1742         // We only mark the register in the following cases:
1743         // 1. It is not a register candidate local. In this case, we're producing a
1744         //    register from a local, but the local is not a register candidate. Thus,
1745         //    we must be loading it as a temp register, and any "last use" flag on
1746         //    the register wouldn't be relevant.
1747         // 2. The register candidate local is going dead. There's no point to mark
1748         //    the register as live, with a GC pointer, if the variable is dead.
1749         if (!genIsRegCandidateLocal(tree) || ((tree->gtFlags & GTF_VAR_DEATH) == 0))
1750         {
1751             // Multi-reg call node will produce more than one register result.
1752             // Mark all the regs produced by call node.
1753             if (tree->IsMultiRegCall())
1754             {
1755                 GenTreeCall*    call        = tree->AsCall();
1756                 ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
1757                 unsigned        regCount    = retTypeDesc->GetReturnRegCount();
1758
1759                 for (unsigned i = 0; i < regCount; ++i)
1760                 {
1761                     regNumber reg  = call->GetRegNumByIdx(i);
1762                     var_types type = retTypeDesc->GetReturnRegType(i);
1763                     gcInfo.gcMarkRegPtrVal(reg, type);
1764                 }
1765             }
1766             else if (tree->IsCopyOrReloadOfMultiRegCall())
1767             {
1768                 // we should never see reload of multi-reg call here
1769                 // because GT_RELOAD gets generated in reg consuming path.
1770                 noway_assert(tree->OperGet() == GT_COPY);
1771
1772                 // A multi-reg GT_COPY node produces those regs to which
1773                 // copy has taken place.
1774                 GenTreeCopyOrReload* copy        = tree->AsCopyOrReload();
1775                 GenTreeCall*         call        = copy->gtGetOp1()->AsCall();
1776                 ReturnTypeDesc*      retTypeDesc = call->GetReturnTypeDesc();
1777                 unsigned             regCount    = retTypeDesc->GetReturnRegCount();
1778
1779                 for (unsigned i = 0; i < regCount; ++i)
1780                 {
1781                     var_types type    = retTypeDesc->GetReturnRegType(i);
1782                     regNumber fromReg = call->GetRegNumByIdx(i);
1783                     regNumber toReg   = copy->GetRegNumByIdx(i);
1784
1785                     if (toReg != REG_NA)
1786                     {
1787                         gcInfo.gcMarkRegPtrVal(toReg, type);
1788                     }
1789                 }
1790             }
1791             else
1792             {
1793                 gcInfo.gcMarkRegPtrVal(tree->gtRegNum, tree->TypeGet());
1794             }
1795         }
1796     }
1797 }
1798
1799 // transfer gc/byref status of src reg to dst reg
1800 void CodeGen::genTransferRegGCState(regNumber dst, regNumber src)
1801 {
1802     regMaskTP srcMask = genRegMask(src);
1803     regMaskTP dstMask = genRegMask(dst);
1804
1805     if (gcInfo.gcRegGCrefSetCur & srcMask)
1806     {
1807         gcInfo.gcMarkRegSetGCref(dstMask);
1808     }
1809     else if (gcInfo.gcRegByrefSetCur & srcMask)
1810     {
1811         gcInfo.gcMarkRegSetByref(dstMask);
1812     }
1813     else
1814     {
1815         gcInfo.gcMarkRegSetNpt(dstMask);
1816     }
1817 }
1818
1819 // generates an ip-relative call or indirect call via reg ('call reg')
1820 //     pass in 'addr' for a relative call or 'base' for a indirect register call
1821 //     methHnd - optional, only used for pretty printing
1822 //     retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC)
1823 //
1824 // clang-format off
1825 void CodeGen::genEmitCall(int                   callType,
1826                           CORINFO_METHOD_HANDLE methHnd,
1827                           INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo)
1828                           void*                 addr
1829                           X86_ARG(ssize_t argSize),
1830                           emitAttr              retSize
1831                           MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
1832                           IL_OFFSETX            ilOffset,
1833                           regNumber             base,
1834                           bool                  isJump,
1835                           bool                  isNoGC)
1836 {
1837 #if !defined(_TARGET_X86_)
1838     ssize_t argSize = 0;
1839 #endif // !defined(_TARGET_X86_)
1840     getEmitter()->emitIns_Call(emitter::EmitCallType(callType),
1841                                methHnd,
1842                                INDEBUG_LDISASM_COMMA(sigInfo)
1843                                addr,
1844                                argSize,
1845                                retSize
1846                                MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
1847                                gcInfo.gcVarPtrSetCur,
1848                                gcInfo.gcRegGCrefSetCur,
1849                                gcInfo.gcRegByrefSetCur,
1850                                ilOffset, base, REG_NA, 0, 0, isJump,
1851                                emitter::emitNoGChelper(compiler->eeGetHelperNum(methHnd)));
1852 }
1853 // clang-format on
1854
1855 // generates an indirect call via addressing mode (call []) given an indir node
1856 //     methHnd - optional, only used for pretty printing
1857 //     retSize - emitter type of return for GC purposes, should be EA_BYREF, EA_GCREF, or EA_PTRSIZE(not GC)
1858 //
1859 // clang-format off
1860 void CodeGen::genEmitCall(int                   callType,
1861                           CORINFO_METHOD_HANDLE methHnd,
1862                           INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo)
1863                           GenTreeIndir*         indir
1864                           X86_ARG(ssize_t argSize),
1865                           emitAttr              retSize
1866                           MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
1867                           IL_OFFSETX            ilOffset)
1868 {
1869 #if !defined(_TARGET_X86_)
1870     ssize_t argSize = 0;
1871 #endif // !defined(_TARGET_X86_)
1872     genConsumeAddress(indir->Addr());
1873
1874     getEmitter()->emitIns_Call(emitter::EmitCallType(callType),
1875                                methHnd,
1876                                INDEBUG_LDISASM_COMMA(sigInfo)
1877                                nullptr,
1878                                argSize,
1879                                retSize
1880                                MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
1881                                gcInfo.gcVarPtrSetCur,
1882                                gcInfo.gcRegGCrefSetCur,
1883                                gcInfo.gcRegByrefSetCur,
1884                                ilOffset,
1885                                (indir->Base()  != nullptr) ? indir->Base()->gtRegNum  : REG_NA,
1886                                (indir->Index() != nullptr) ? indir->Index()->gtRegNum : REG_NA,
1887                                indir->Scale(),
1888                                indir->Offset());
1889 }
1890 // clang-format on
1891
1892 //------------------------------------------------------------------------
1893 // genCodeForCast: Generates the code for GT_CAST.
1894 //
1895 // Arguments:
1896 //    tree - the GT_CAST node.
1897 //
1898 void CodeGen::genCodeForCast(GenTreeOp* tree)
1899 {
1900     assert(tree->OperIs(GT_CAST));
1901
1902     var_types targetType = tree->TypeGet();
1903
1904     if (varTypeIsFloating(targetType) && varTypeIsFloating(tree->gtOp1))
1905     {
1906         // Casts float/double <--> double/float
1907         genFloatToFloatCast(tree);
1908     }
1909     else if (varTypeIsFloating(tree->gtOp1))
1910     {
1911         // Casts float/double --> int32/int64
1912         genFloatToIntCast(tree);
1913     }
1914     else if (varTypeIsFloating(targetType))
1915     {
1916         // Casts int32/uint32/int64/uint64 --> float/double
1917         genIntToFloatCast(tree);
1918     }
1919 #ifndef _TARGET_64BIT_
1920     else if (varTypeIsLong(tree->gtOp1))
1921     {
1922         genLongToIntCast(tree);
1923     }
1924 #endif // !_TARGET_64BIT_
1925     else
1926     {
1927         // Casts int <--> int
1928         genIntToIntCast(tree);
1929     }
1930     // The per-case functions call genProduceReg()
1931 }
1932
1933 #endif // !LEGACY_BACKEND