Merge pull request #10609 from alpencolt/ryu-arm-locallock
authorBruce Forstall <brucefo@microsoft.com>
Tue, 4 Apr 2017 20:20:32 +0000 (13:20 -0700)
committerGitHub <noreply@github.com>
Tue, 4 Apr 2017 20:20:32 +0000 (13:20 -0700)
[RyuJIT/ARM32] Localloc implementation in codegen

25 files changed:
src/jit/codegenarm.cpp
src/jit/codegenarm64.cpp
src/jit/codegencommon.cpp
src/jit/lsraarm.cpp
tests/src/AllTestProjects.sln
tests/src/JIT/CodeGenBringUpTests/LocallocB_N.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocB_N.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocB_N_PSP.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocB_N_PSP.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117_PSP.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117_PSP.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1_PSP.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1_PSP.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001_PSP.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001_PSP.csproj [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5_PSP.cs [new file with mode: 0644]
tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5_PSP.csproj [new file with mode: 0644]

index 1a2c855..2cbd0c6 100644 (file)
@@ -40,14 +40,6 @@ void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFla
 }
 
 //------------------------------------------------------------------------
-// genEmitGSCookieCheck: Generate code to check that the GS cookie wasn't thrashed by a buffer overrun.
-//
-void CodeGen::genEmitGSCookieCheck(bool pushReg)
-{
-    NYI("ARM genEmitGSCookieCheck");
-}
-
-//------------------------------------------------------------------------
 // genCallFinally: Generate a call to the finally block.
 //
 BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
@@ -517,6 +509,10 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
 
     switch (treeNode->gtOper)
     {
+        case GT_LCLHEAP:
+            genLclHeap(treeNode);
+            break;
+
         case GT_CNS_INT:
         case GT_CNS_DBL:
             genSetRegToConst(targetReg, targetType, treeNode);
@@ -1315,6 +1311,328 @@ void CodeGen::genMultiRegCallStoreToLocal(GenTreePtr treeNode)
     varDsc->lvRegNum = REG_STK;
 }
 
+//--------------------------------------------------------------------------------------
+// genLclHeap: Generate code for localloc
+//
+// Description:
+//      There are 2 ways depending from build version to generate code for localloc:
+//          1) For debug build where memory should be initialized we generate loop
+//             which invoke push {tmpReg} N times.
+//          2) Fore /o build  However, we tickle the pages to ensure that SP is always
+//             valid and is in sync with the "stack guard page". Amount of iteration
+//             is N/PAGE_SIZE.
+//
+// Comments:
+//      There can be some optimization:
+//          1) It's not needed to generate loop for zero size allocation
+//          2) For small allocation (less than 4 store) we unroll loop
+//          3) For allocation less than PAGE_SIZE and when it's not needed to initialize
+//             memory to zero, we can just increment SP.
+//
+// Notes: Size N should be aligned to STACK_ALIGN before any allocation
+//
+void CodeGen::genLclHeap(GenTreePtr tree)
+{
+    assert(tree->OperGet() == GT_LCLHEAP);
+
+    GenTreePtr size = tree->gtOp.gtOp1;
+    noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
+
+    // Result of localloc will be returned in regCnt.
+    // Also it used as temporary register in code generation
+    // for storing allocation size
+    regNumber   regCnt          = tree->gtRegNum;
+    regMaskTP   tmpRegsMask     = tree->gtRsvdRegs;
+    regNumber   pspSymReg       = REG_NA;
+    var_types   type            = genActualType(size->gtType);
+    emitAttr    easz            = emitTypeSize(type);
+    BasicBlock* endLabel        = nullptr;
+    BasicBlock* loop            = nullptr;
+    unsigned    stackAdjustment = 0;
+
+#ifdef DEBUG
+    // Verify ESP
+    if (compiler->opts.compStackCheckOnRet)
+    {
+        noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC &&
+                     compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister &&
+                     compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame);
+        getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
+
+        BasicBlock*  esp_check = genCreateTempLabel();
+        emitJumpKind jmpEqual  = genJumpKindForOper(GT_EQ, CK_SIGNED);
+        inst_JMP(jmpEqual, esp_check);
+        getEmitter()->emitIns(INS_BREAKPOINT);
+        genDefineTempLabel(esp_check);
+    }
+#endif
+
+    noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes
+    noway_assert(genStackLevel == 0);   // Can't have anything on the stack
+
+    // Whether method has PSPSym.
+    bool hasPspSym;
+#if FEATURE_EH_FUNCLETS
+    hasPspSym = (compiler->lvaPSPSym != BAD_VAR_NUM);
+#else
+    hasPspSym = false;
+#endif
+
+    // Check to 0 size allocations
+    // size_t amount = 0;
+    if (size->IsCnsIntOrI())
+    {
+        // If size is a constant, then it must be contained.
+        assert(size->isContained());
+
+        // If amount is zero then return null in regCnt
+        size_t amount = size->gtIntCon.gtIconVal;
+        if (amount == 0)
+        {
+            instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt);
+            goto BAILOUT;
+        }
+    }
+    else
+    {
+        // If 0 bail out by returning null in regCnt
+        genConsumeRegAndCopy(size, regCnt);
+        endLabel = genCreateTempLabel();
+        getEmitter()->emitIns_R_R(INS_TEST, easz, regCnt, regCnt);
+        emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED);
+        inst_JMP(jmpEqual, endLabel);
+    }
+
+    stackAdjustment = 0;
+#if FEATURE_EH_FUNCLETS
+    // If we have PSPsym, then need to re-locate it after localloc.
+    if (hasPspSym)
+    {
+        stackAdjustment += STACK_ALIGN;
+
+        // Save a copy of PSPSym
+        assert(genCountBits(tmpRegsMask) >= 1);
+        regMaskTP pspSymRegMask = genFindLowestBit(tmpRegsMask);
+        tmpRegsMask &= ~pspSymRegMask;
+        pspSymReg = genRegNumFromMask(pspSymRegMask);
+        getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, pspSymReg, compiler->lvaPSPSym, 0);
+    }
+#endif
+
+#if FEATURE_FIXED_OUT_ARGS
+    // If we have an outgoing arg area then we must adjust the SP by popping off the
+    // outgoing arg area. We will restore it right before we return from this method.
+    if (compiler->lvaOutgoingArgSpaceSize > 0)
+    {
+        assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain
+                                                                        // aligned
+        inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE);
+        stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
+    }
+#endif
+
+    // Put aligned allocation size to regCnt
+    if (size->IsCnsIntOrI())
+    {
+        // 'amount' is the total number of bytes to localloc to properly STACK_ALIGN
+        size_t amount = size->gtIntCon.gtIconVal;
+        amount        = AlignUp(amount, STACK_ALIGN);
+
+        // For small allocations we will generate up to four stp instructions
+        size_t cntStackAlignedWidthItems = (amount >> STACK_ALIGN_SHIFT);
+        if (cntStackAlignedWidthItems <= 4)
+        {
+            instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt);
+
+            while (cntStackAlignedWidthItems != 0)
+            {
+                inst_IV(INS_push, (unsigned)genRegMask(regCnt));
+                cntStackAlignedWidthItems -= 1;
+            }
+
+            goto ALLOC_DONE;
+        }
+        else if (!compiler->info.compInitMem && (amount < compiler->eeGetPageSize())) // must be < not <=
+        {
+            // Since the size is a page or less, simply adjust the SP value
+            // The SP might already be in the guard page, must touch it BEFORE
+            // the alloc, not after.
+            getEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, regCnt, REG_SP, 0);
+            inst_RV_IV(INS_sub, REG_SP, amount, EA_PTRSIZE);
+            goto ALLOC_DONE;
+        }
+
+        // regCnt will be the total number of bytes to locAlloc
+        genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG);
+    }
+    else
+    {
+        // Round up the number of bytes to allocate to a STACK_ALIGN boundary.
+        inst_RV_IV(INS_add, regCnt, (STACK_ALIGN - 1), emitActualTypeSize(type));
+        inst_RV_IV(INS_AND, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type));
+    }
+
+    // Allocation
+    if (compiler->info.compInitMem)
+    {
+        // At this point 'regCnt' is set to the total number of bytes to locAlloc.
+        // Since we have to zero out the allocated memory AND ensure that RSP is always valid
+        // by tickling the pages, we will just push 0's on the stack.
+
+        assert(tmpRegsMask != RBM_NONE);
+        assert(genCountBits(tmpRegsMask) >= 1);
+
+        regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
+        tmpRegsMask &= ~regCntMask;
+        regNumber regTmp = genRegNumFromMask(regCntMask);
+        instGen_Set_Reg_To_Zero(EA_PTRSIZE, regTmp);
+
+        // Loop:
+        BasicBlock* loop = genCreateTempLabel();
+        genDefineTempLabel(loop);
+
+        noway_assert(STACK_ALIGN == 8);
+        inst_IV(INS_push, (unsigned)genRegMask(regTmp));
+        inst_IV(INS_push, (unsigned)genRegMask(regTmp));
+
+        // If not done, loop
+        // Note that regCnt is the number of bytes to stack allocate.
+        assert(genIsValidIntReg(regCnt));
+        getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, regCnt, regCnt, STACK_ALIGN);
+        emitJumpKind jmpNotEqual = genJumpKindForOper(GT_NE, CK_SIGNED);
+        inst_JMP(jmpNotEqual, loop);
+    }
+    else
+    {
+        // At this point 'regCnt' is set to the total number of bytes to locAlloc.
+        //
+        // We don't need to zero out the allocated memory. However, we do have
+        // to tickle the pages to ensure that SP is always valid and is
+        // in sync with the "stack guard page".  Note that in the worst
+        // case SP is on the last byte of the guard page.  Thus you must
+        // touch SP+0 first not SP+0x1000.
+        //
+        // Another subtlety is that you don't want SP to be exactly on the
+        // boundary of the guard page because PUSH is predecrement, thus
+        // call setup would not touch the guard page but just beyond it
+        //
+        // Note that we go through a few hoops so that SP never points to
+        // illegal pages at any time during the ticking process
+        //
+        //       subs  regCnt, SP, regCnt      // regCnt now holds ultimate SP
+        //       jb    Loop                    // result is smaller than orignial SP (no wrap around)
+        //       mov   regCnt, #0              // Overflow, pick lowest possible value
+        //
+        //  Loop:
+        //       ldr   regTmp, [SP + 0]        // tickle the page - read from the page
+        //       sub   regTmp, SP, PAGE_SIZE   // decrement SP by PAGE_SIZE
+        //       cmp   regTmp, regCnt
+        //       jb    Done
+        //       mov   SP, regTmp
+        //       j     Loop
+        //
+        //  Done:
+        //       mov   SP, regCnt
+        //
+
+        // Setup the regTmp
+        assert(tmpRegsMask != RBM_NONE);
+        assert(genCountBits(tmpRegsMask) == 1);
+        regNumber regTmp = genRegNumFromMask(tmpRegsMask);
+
+        BasicBlock* loop = genCreateTempLabel();
+        BasicBlock* done = genCreateTempLabel();
+
+        //       subs  regCnt, SP, regCnt      // regCnt now holds ultimate SP
+        getEmitter()->emitIns_R_R_R(INS_sub, EA_PTRSIZE, regCnt, REG_SPBASE, regCnt);
+
+        inst_JMP(EJ_vc, loop); // branch if the V flag is not set
+
+        // Ups... Overflow, set regCnt to lowest possible value
+        instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt);
+
+        genDefineTempLabel(loop);
+
+        // tickle the page - Read from the updated SP - this triggers a page fault when on the guard page
+        getEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, regTmp, REG_SPBASE, 0);
+
+        // decrement SP by PAGE_SIZE
+        getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, regTmp, REG_SPBASE, compiler->eeGetPageSize());
+
+        getEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, regTmp, regCnt);
+        emitJumpKind jmpLTU = genJumpKindForOper(GT_LT, CK_UNSIGNED);
+        inst_JMP(jmpLTU, done);
+
+        // Update SP to be at the next page of stack that we will tickle
+        getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_SPBASE, regCnt);
+
+        // Jump to loop and tickle new stack address
+        inst_JMP(EJ_jmp, loop);
+
+        // Done with stack tickle loop
+        genDefineTempLabel(done);
+
+        // Now just move the final value to SP
+        getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_SPBASE, regCnt);
+    }
+
+ALLOC_DONE:
+    // Re-adjust SP to allocate PSPSym and out-going arg area
+    if (stackAdjustment != 0)
+    {
+        assert((stackAdjustment % STACK_ALIGN) == 0); // This must be true for the stack to remain aligned
+        assert(stackAdjustment > 0);
+        getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, (int)stackAdjustment);
+
+#if FEATURE_EH_FUNCLETS
+        // Write PSPSym to its new location.
+        if (hasPspSym)
+        {
+            assert(genIsValidIntReg(pspSymReg));
+            getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, pspSymReg, compiler->lvaPSPSym, 0);
+        }
+#endif
+        // Return the stackalloc'ed address in result register.
+        // regCnt = RSP + stackAdjustment.
+        getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, regCnt, REG_SPBASE, (int)stackAdjustment);
+    }
+    else // stackAdjustment == 0
+    {
+        // Move the final value of SP to regCnt
+        inst_RV_RV(INS_mov, regCnt, REG_SPBASE);
+    }
+
+BAILOUT:
+    if (endLabel != nullptr)
+        genDefineTempLabel(endLabel);
+
+    // Write the lvaLocAllocSPvar stack frame slot
+    if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
+    {
+        getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, regCnt, compiler->lvaLocAllocSPvar, 0);
+    }
+
+#if STACK_PROBES
+    if (compiler->opts.compNeedStackProbes)
+    {
+        genGenerateStackProbe();
+    }
+#endif
+
+#ifdef DEBUG
+    // Update new ESP
+    if (compiler->opts.compStackCheckOnRet)
+    {
+        noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC &&
+                     compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister &&
+                     compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame);
+        getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, regCnt, compiler->lvaReturnEspCheck, 0);
+    }
+#endif
+
+    genProduceReg(tree);
+}
+
 //------------------------------------------------------------------------
 // genTableBasedSwitch: generate code for a switch statement based on a table of ip-relative offsets
 //
index 5698be9..1b8d1c3 100644 (file)
@@ -1283,49 +1283,6 @@ void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFla
     instGen_Set_Reg_To_Imm(emitActualTypeSize(type), reg, val, flags);
 }
 
-/*****************************************************************************
- *
- *   Generate code to check that the GS cookie wasn't thrashed by a buffer
- *   overrun.  On ARM64 we always use REG_TMP_0 and REG_TMP_1 as temp registers
- *   and this works fine in the case of tail calls
- *   Implementation Note: pushReg = true, in case of tail calls.
- */
-void CodeGen::genEmitGSCookieCheck(bool pushReg)
-{
-    noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal);
-
-    // Make sure that the return register is reported as live GC-ref so that any GC that kicks in while
-    // executing GS cookie check will not collect the object pointed to by REG_INTRET (R0).
-    if (!pushReg && (compiler->info.compRetType == TYP_REF))
-        gcInfo.gcRegGCrefSetCur |= RBM_INTRET;
-
-    regNumber regGSConst = REG_TMP_0;
-    regNumber regGSValue = REG_TMP_1;
-
-    if (compiler->gsGlobalSecurityCookieAddr == nullptr)
-    {
-        // load the GS cookie constant into a reg
-        //
-        genSetRegToIcon(regGSConst, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL);
-    }
-    else
-    {
-        // Ngen case - GS cookie constant needs to be accessed through an indirection.
-        instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSConst, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
-        getEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSConst, regGSConst, 0);
-    }
-    // Load this method's GS value from the stack frame
-    getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSValue, compiler->lvaGSSecurityCookie, 0);
-    // Compare with the GC cookie constant
-    getEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, regGSConst, regGSValue);
-
-    BasicBlock*  gsCheckBlk = genCreateTempLabel();
-    emitJumpKind jmpEqual   = genJumpKindForOper(GT_EQ, CK_SIGNED);
-    inst_JMP(jmpEqual, gsCheckBlk);
-    genEmitHelperCall(CORINFO_HELP_FAIL_FAST, 0, EA_UNKNOWN);
-    genDefineTempLabel(gsCheckBlk);
-}
-
 BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
 {
     // Generate a call to the finally, like this:
index e9546f8..3432444 100644 (file)
@@ -2610,6 +2610,51 @@ emitJumpKind CodeGen::genJumpKindForOper(genTreeOps cmp, CompareKind compareKind
     return result;
 }
 
+#ifndef LEGACY_BACKEND
+#ifdef _TARGET_ARMARCH_
+//------------------------------------------------------------------------
+// genEmitGSCookieCheck: Generate code to check that the GS cookie
+// wasn't thrashed by a buffer overrun. Coomon code for ARM32 and ARM64
+//
+void CodeGen::genEmitGSCookieCheck(bool pushReg)
+{
+    noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal);
+
+    // Make sure that the return register is reported as live GC-ref so that any GC that kicks in while
+    // executing GS cookie check will not collect the object pointed to by REG_INTRET (R0).
+    if (!pushReg && (compiler->info.compRetType == TYP_REF))
+        gcInfo.gcRegGCrefSetCur |= RBM_INTRET;
+
+    regNumber regGSConst = REG_TMP_0;
+    regNumber regGSValue = REG_TMP_1;
+
+    if (compiler->gsGlobalSecurityCookieAddr == nullptr)
+    {
+        // load the GS cookie constant into a reg
+        //
+        genSetRegToIcon(regGSConst, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL);
+    }
+    else
+    {
+        // Ngen case - GS cookie constant needs to be accessed through an indirection.
+        instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSConst, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
+        getEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSConst, regGSConst, 0);
+    }
+    // Load this method's GS value from the stack frame
+    getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSValue, compiler->lvaGSSecurityCookie, 0);
+    // Compare with the GC cookie constant
+    getEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, regGSConst, regGSValue);
+
+    BasicBlock*  gsCheckBlk = genCreateTempLabel();
+    emitJumpKind jmpEqual   = genJumpKindForOper(GT_EQ, CK_SIGNED);
+    inst_JMP(jmpEqual, gsCheckBlk);
+    // regGSConst and regGSValue aren't needed anymore, we can use them for helper call
+    genEmitHelperCall(CORINFO_HELP_FAIL_FAST, 0, EA_UNKNOWN, regGSConst);
+    genDefineTempLabel(gsCheckBlk);
+}
+#endif // _TARGET_ARMARCH_
+#endif // !LEGACY_BACKEND
+
 /*****************************************************************************
  *
  *  Generate an exit sequence for a return from a method (note: when compiling
@@ -8094,6 +8139,14 @@ void CodeGen::genFinalizeFrame()
     }
 #endif // defined(_TARGET_ARMARCH_)
 
+#if defined(_TARGET_ARM_)
+    // If there are any reserved registers, add them to the
+    if (regSet.rsMaskResvd != RBM_NONE)
+    {
+        regSet.rsSetRegsModified(regSet.rsMaskResvd);
+    }
+#endif // _TARGET_ARM_
+
 #ifdef DEBUG
     if (verbose)
     {
index 0c5fa72..912fd36 100644 (file)
@@ -728,6 +728,88 @@ void Lowering::TreeNodeInfoInitPutArgStk(GenTreePutArgStk* argNode, fgArgTabEntr
     }
 }
 
+void Lowering::TreeNodeInfoInitLclHeap(GenTree* tree)
+{
+    TreeNodeInfo* info     = &(tree->gtLsraInfo);
+    LinearScan*   l        = m_lsra;
+    Compiler*     compiler = comp;
+
+    info->srcCount = 1;
+    info->dstCount = 1;
+
+    // Need a variable number of temp regs (see genLclHeap() in codegenarm.cpp):
+    // Here '-' means don't care.
+    //
+    //  Size?                   Init Memory?    # temp regs
+    //   0                          -               0
+    //   const and <=4 ptr words    -             hasPspSym ? 1 : 0
+    //   const and <PageSize        No            hasPspSym ? 1 : 0
+    //   >4 ptr words               Yes           hasPspSym ? 2 : 1
+    //   Non-const                  Yes           hasPspSym ? 2 : 1
+    //   Non-const                  No            hasPspSym ? 2 : 1
+
+    bool hasPspSym;
+#if FEATURE_EH_FUNCLETS
+    hasPspSym = (compiler->lvaPSPSym != BAD_VAR_NUM);
+#else
+    hasPspSym = false;
+#endif
+
+    GenTreePtr size = tree->gtOp.gtOp1;
+    if (size->IsCnsIntOrI())
+    {
+        MakeSrcContained(tree, size);
+
+        size_t sizeVal = size->gtIntCon.gtIconVal;
+        if (sizeVal == 0)
+        {
+            info->internalIntCount = 0;
+        }
+        else
+        {
+            sizeVal                          = AlignUp(sizeVal, STACK_ALIGN);
+            size_t cntStackAlignedWidthItems = (sizeVal >> STACK_ALIGN_SHIFT);
+
+            // For small allocations up to 4 store instructions
+            if (cntStackAlignedWidthItems <= 4)
+            {
+                info->internalIntCount = 0;
+            }
+            else if (!compiler->info.compInitMem)
+            {
+                // No need to initialize allocated stack space.
+                if (sizeVal < compiler->eeGetPageSize())
+                {
+                    info->internalIntCount = 0;
+                }
+                else
+                {
+                    // target (regCnt) + tmp + [psp]
+                    info->internalIntCount       = 1;
+                    info->isInternalRegDelayFree = true;
+                }
+            }
+            else
+            {
+                // target (regCnt) + tmp + [psp]
+                info->internalIntCount       = 1;
+                info->isInternalRegDelayFree = true;
+            }
+
+            if (hasPspSym)
+            {
+                info->internalIntCount++;
+            }
+        }
+    }
+    else
+    {
+        // target (regCnt) + tmp + [psp]
+        info->internalIntCount       = hasPspSym ? 2 : 1;
+        info->isInternalRegDelayFree = true;
+    }
+}
+
 //------------------------------------------------------------------------
 // TreeNodeInfoInitBlockStore: Set the NodeInfo for a block store.
 //
@@ -1296,6 +1378,10 @@ void Lowering::TreeNodeInfoInit(GenTree* tree)
             TreeNodeInfoInitBlockStore(tree->AsBlk());
             break;
 
+        case GT_LCLHEAP:
+            TreeNodeInfoInitLclHeap(tree);
+            break;
+
         case GT_STOREIND:
         {
             info->srcCount = 2;
index be437ec..679f2d7 100644 (file)
@@ -837,6 +837,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Localloc", "JIT\CodeGenBrin
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocLarge", "JIT\CodeGenBringUpTests\LocallocLarge.csproj", "{C5578A39-72FF-4D25-99DA-96A8A99C6740}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocB_N", "JIT\CodeGenBringUpTests\LocallocB_N.csproj", "{38302715-A140-493E-AEF4-3E8F9EE99195}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocB_N_PSP", "JIT\CodeGenBringUpTests\LocallocB_N_PSP.csproj", "{6222AF08-F765-44C2-B48C-3C040D62303F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB117", "JIT\CodeGenBringUpTests\LocallocCnstB117.csproj", "{5A0F2889-91F1-4670-A4AF-9AF0598E22B7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB117_PSP", "JIT\CodeGenBringUpTests\LocallocCnstB117_PSP.csproj", "{C82D33B6-5779-4E19-8220-1DEA587203B1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB1", "JIT\CodeGenBringUpTests\LocallocCnstB1.csproj", "{4240086D-0722-4E93-A6DD-BF779715CE73}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB1_PSP", "JIT\CodeGenBringUpTests\LocallocCnstB1_PSP.csproj", "{18F8266B-2F59-4058-8FE6-6B8368CD0D0F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB5001", "JIT\CodeGenBringUpTests\LocallocCnstB5001.csproj", "{E7B36F3A-CD18-4F21-8898-CA43C5FDEA1E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB5001_PSP", "JIT\CodeGenBringUpTests\LocallocCnstB5001_PSP.csproj", "{1EB5785A-2050-4AD1-820B-F46CCCC3C65A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB5", "JIT\CodeGenBringUpTests\LocallocCnstB5.csproj", "{061E4E38-14A9-4305-AD27-5A01A95E9FCE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocallocCnstB5_PSP", "JIT\CodeGenBringUpTests\LocallocCnstB5_PSP.csproj", "{5F015026-51D0-4EF7-B538-24E8864F31D6}"
+EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LongArgsAndReturn", "JIT\CodeGenBringUpTests\LongArgsAndReturn.csproj", "{FC3E9CEC-7659-471A-8B2E-8CFB3FBFDB4E}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lt1", "JIT\CodeGenBringUpTests\Lt1.csproj", "{A7850EBD-6701-473E-8686-99535F0794A6}"
@@ -33450,6 +33470,16 @@ Global
                {C6DC8E85-DCD2-49A0-977D-CE9795552632} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
                {8BA7A4A1-EBB6-44CD-828B-F2BA5523691A} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
                {650B07D3-9BC0-4EF8-8557-44200EC13261} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {38302715-A140-493E-AEF4-3E8F9EE99195} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {6222AF08-F765-44C2-B48C-3C040D62303F} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {5A0F2889-91F1-4670-A4AF-9AF0598E22B7} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {C82D33B6-5779-4E19-8220-1DEA587203B1} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {4240086D-0722-4E93-A6DD-BF779715CE73} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {18F8266B-2F59-4058-8FE6-6B8368CD0D0F} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {E7B36F3A-CD18-4F21-8898-CA43C5FDEA1E} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {1EB5785A-2050-4AD1-820B-F46CCCC3C65A} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {061E4E38-14A9-4305-AD27-5A01A95E9FCE} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
+               {5F015026-51D0-4EF7-B538-24E8864F31D6} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
                {C5578A39-72FF-4D25-99DA-96A8A99C6740} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
                {FC3E9CEC-7659-471A-8B2E-8CFB3FBFDB4E} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
                {A7850EBD-6701-473E-8686-99535F0794A6} = {954F04D0-2FFD-4923-BE9A-2F9F58145708}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocB_N.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocB_N.cs
new file mode 100644 (file)
index 0000000..3d01df6
--- /dev/null
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocB_N(int n)
+    {
+        byte* a = stackalloc byte[n];
+
+        for (int i = 0; i < n; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        for (int i = 0; i < n; i++)
+        {
+            if (!CHECK(a[i], (byte) i)) return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocB_N(1);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N - Test 1: Failed on index: " + ret);
+            return Fail;
+        }
+
+        ret = LocallocB_N(5);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N - Test 2: Failed on index: " + ret);
+            return Fail;
+        }
+
+        ret = LocallocB_N(117);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N - Test 3: Failed on index: " + ret);
+            return Fail;
+        }
+
+        ret = LocallocB_N(5001);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N - Test 4: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocB_N.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocB_N.csproj
new file mode 100644 (file)
index 0000000..4b23894
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{38302715-A140-493E-AEF4-3E8F9EE99195}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocB_N.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocB_N_PSP.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocB_N_PSP.cs
new file mode 100644 (file)
index 0000000..4dd836e
--- /dev/null
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocB_N_PSP(int n)
+    {
+        byte* a = stackalloc byte[n];
+        int i;
+        for (i = 0; i < n; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        i = 0;
+        try
+        {
+            for (; i < n; i++)
+            {
+                if (!CHECK(a[i], (byte) i)) return i;
+            }
+        }
+        catch
+        {
+            Console.WriteLine("ERROR!!!");
+            return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocB_N_PSP(1);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N_PSP - Test 1: Failed on index: " + ret);
+            return Fail;
+        }
+
+        ret = LocallocB_N_PSP(5);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N_PSP - Test 2: Failed on index: " + ret);
+            return Fail;
+        }
+
+        ret = LocallocB_N_PSP(117);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N_PSP - Test 3: Failed on index: " + ret);
+            return Fail;
+        }
+
+        ret = LocallocB_N_PSP(5001);
+        if (ret != -1) {
+            Console.WriteLine("LocallocB_N_PSP - Test 4: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocB_N_PSP.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocB_N_PSP.csproj
new file mode 100644 (file)
index 0000000..079264c
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{6222AF08-F765-44C2-B48C-3C040D62303F}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocB_N_PSP.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1.cs
new file mode 100644 (file)
index 0000000..59a0db4
--- /dev/null
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB1()
+    {
+        byte* a = stackalloc byte[1];
+        for (int i = 0; i < 1; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        for (int i = 0; i < 1; i++)
+        {
+            if (!CHECK(a[i], (byte) i)) return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB1();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB1: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1.csproj
new file mode 100644 (file)
index 0000000..669255e
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4240086D-0722-4E93-A6DD-BF779715CE73}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB1.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117.cs
new file mode 100644 (file)
index 0000000..b399379
--- /dev/null
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB117()
+    {
+        byte* a = stackalloc byte[117];
+        for (int i = 0; i < 117; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        for (int i = 0; i < 117; i++)
+        {
+            if (!CHECK(a[i], (byte) i)) return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB117();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB117: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117.csproj
new file mode 100644 (file)
index 0000000..239a2e6
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5A0F2889-91F1-4670-A4AF-9AF0598E22B7}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB117.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117_PSP.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117_PSP.cs
new file mode 100644 (file)
index 0000000..4518f0a
--- /dev/null
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB117_PSP()
+    {
+        byte* a = stackalloc byte[117];
+        int i;
+        for (i = 0; i < 117; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        i = 0;
+        try
+        {
+            for (; i < 117; i++)
+            {
+                if (!CHECK(a[i], (byte) i)) return i;
+            }
+        }
+        catch
+        {
+            Console.WriteLine("ERROR!!!");
+            return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB117_PSP();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB117_PSP: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117_PSP.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB117_PSP.csproj
new file mode 100644 (file)
index 0000000..b4dbad3
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{C82D33B6-5779-4E19-8220-1DEA587203B1}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB117_PSP.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1_PSP.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1_PSP.cs
new file mode 100644 (file)
index 0000000..834d1d8
--- /dev/null
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB1_PSP()
+    {
+        byte* a = stackalloc byte[1];
+        int i;
+        for (i = 0; i < 1; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        i = 0;
+        try
+        {
+            for (; i < 1; i++)
+            {
+                if (!CHECK(a[i], (byte) i)) return i;
+            }
+        }
+        catch
+        {
+            Console.WriteLine("ERROR!!!");
+            return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB1_PSP();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB1_PSP: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1_PSP.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB1_PSP.csproj
new file mode 100644 (file)
index 0000000..696a5c5
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{18F8266B-2F59-4058-8FE6-6B8368CD0D0F}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB1_PSP.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5.cs
new file mode 100644 (file)
index 0000000..81c34b4
--- /dev/null
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB5()
+    {
+        byte* a = stackalloc byte[5];
+        for (int i = 0; i < 5; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        for (int i = 0; i < 5; i++)
+        {
+            if (!CHECK(a[i], (byte) i)) return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB5();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB5: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5.csproj
new file mode 100644 (file)
index 0000000..7d3c080
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{061E4E38-14A9-4305-AD27-5A01A95E9FCE}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB5.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001.cs
new file mode 100644 (file)
index 0000000..27557bd
--- /dev/null
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB5001()
+    {
+        byte* a = stackalloc byte[5001];
+        for (int i = 0; i < 5001; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        for (int i = 0; i < 5001; i++)
+        {
+            if (!CHECK(a[i], (byte) i)) return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB5001();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB5001: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001.csproj
new file mode 100644 (file)
index 0000000..65b3ff1
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{E7B36F3A-CD18-4F21-8898-CA43C5FDEA1E}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB5001.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001_PSP.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001_PSP.cs
new file mode 100644 (file)
index 0000000..ce411de
--- /dev/null
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB5001_PSP()
+    {
+        byte* a = stackalloc byte[5001];
+        int i;
+        for (i = 0; i < 5001; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        i = 0;
+        try
+        {
+            for (; i < 5001; i++)
+            {
+                if (!CHECK(a[i], (byte) i)) return i;
+            }
+        }
+        catch
+        {
+            Console.WriteLine("ERROR!!!");
+            return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB5001_PSP();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB5001_PSP: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001_PSP.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5001_PSP.csproj
new file mode 100644 (file)
index 0000000..40c3b17
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{1EB5785A-2050-4AD1-820B-F46CCCC3C65A}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB5001_PSP.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5_PSP.cs b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5_PSP.cs
new file mode 100644 (file)
index 0000000..f19b4fc
--- /dev/null
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+
+using System;
+using System.Runtime.CompilerServices;
+public class BringUpTest
+{
+    const int Pass = 100;
+    const int Fail = -1;
+
+    // Reduce all values to byte
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe bool CHECK(byte check, byte expected) {
+        return check == expected;
+    }
+
+    [MethodImplAttribute(MethodImplOptions.NoInlining)]
+    public static unsafe int LocallocCnstB5_PSP()
+    {
+        byte* a = stackalloc byte[5];
+        int i;
+        for (i = 0; i < 5; i++)
+        {
+            a[i] = (byte) i;
+        }
+
+        i = 0;
+        try
+        {
+            for (; i < 5; i++)
+            {
+                if (!CHECK(a[i], (byte) i)) return i;
+            }
+        }
+        catch
+        {
+            Console.WriteLine("ERROR!!!");
+            return i;
+        }
+
+        return -1;
+    }
+
+    public static int Main()
+    {
+        int ret;
+
+        ret = LocallocCnstB5_PSP();
+        if (ret != -1) {
+            Console.WriteLine("LocallocCnstB5_PSP: Failed on index: " + ret);
+            return Fail;
+        }
+
+        return Pass;
+    }
+}
diff --git a/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5_PSP.csproj b/tests/src/JIT/CodeGenBringUpTests/LocallocCnstB5_PSP.csproj
new file mode 100644 (file)
index 0000000..10e269b
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5F015026-51D0-4EF7-B538-24E8864F31D6}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="LocallocCnstB5_PSP.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
\ No newline at end of file