summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Sullivan <briansul@microsoft.com>2019-03-20 16:43:53 -0700
committerBrian Sullivan <briansul@microsoft.com>2019-03-20 16:43:53 -0700
commit8e1882ee40cda54233cbdb4d5d47e9825978ddb5 (patch)
tree36dc6b19fd0ff72aa97a995e97f32211e4f30dc0
parentb2c397b649181f793d6c29f1de78d0aee0a52596 (diff)
parent69dc790d171783584f5af3a5da60a25e2c301899 (diff)
downloadcoreclr-8e1882ee40cda54233cbdb4d5d47e9825978ddb5.tar.gz
coreclr-8e1882ee40cda54233cbdb4d5d47e9825978ddb5.tar.bz2
coreclr-8e1882ee40cda54233cbdb4d5d47e9825978ddb5.zip
Merge branch 'master' into hva-tests
-rw-r--r--azure-pipelines.yml14
-rw-r--r--eng/build-job.yml7
-rw-r--r--eng/kill_tasks.cmd10
-rw-r--r--src/dlls/mscorrc/mscorrc.rc2
-rw-r--r--src/dlls/mscorrc/resource.h2
-rw-r--r--src/jit/codegen.h18
-rw-r--r--src/jit/codegenarmarch.cpp3
-rw-r--r--src/jit/codegencommon.cpp71
-rw-r--r--src/jit/codegeninterface.h8
-rw-r--r--src/jit/codegenlinear.cpp10
-rw-r--r--src/jit/codegenxarch.cpp3
-rw-r--r--src/jit/scopeinfo.cpp168
-rw-r--r--src/jit/treelifeupdater.cpp3
-rw-r--r--src/vm/dllimport.cpp1
-rw-r--r--src/vm/ilmarshalers.cpp86
-rw-r--r--src/vm/ilmarshalers.h32
-rw-r--r--src/vm/mlinfo.cpp57
-rw-r--r--src/vm/mtypes.h2
-rw-r--r--tests/src/GC/API/GC/Collect.csproj1
-rw-r--r--tests/src/Interop/CMakeLists.txt1
-rw-r--r--tests/src/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt42
-rw-r--r--tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs66
-rw-r--r--tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj44
-rw-r--r--tests/src/Interop/IJW/CopyConstructorMarshaler/IjwCopyConstructorMarshaler.cpp106
-rw-r--r--tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.cs221
-rw-r--r--tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj39
26 files changed, 876 insertions, 141 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 5016d7514a..9711bb7271 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -108,6 +108,13 @@ jobs:
parameters:
jobTemplate: build-job.yml
buildConfig: checked
+ ${{ if eq(variables['Build.DefinitionName'], 'coreclr-outerloop-gcstress0x3-gcstress0xc') }}:
+ platforms:
+ - Linux_arm
+ - Linux_arm64
+ - Linux_x64
+ - Windows_NT_x64
+ - Windows_NT_x86
#
# Release build (Pull request)
@@ -142,6 +149,13 @@ jobs:
parameters:
jobTemplate: test-job.yml
buildConfig: checked
+ ${{ if eq(variables['Build.DefinitionName'], 'coreclr-outerloop-gcstress0x3-gcstress0xc') }}:
+ platforms:
+ - Linux_arm
+ - Linux_arm64
+ - Linux_x64
+ - Windows_NT_x64
+ - Windows_NT_x86
jobParameters:
${{ if eq(variables['Build.DefinitionName'], 'coreclr-ci') }}:
testGroup: innerloop
diff --git a/eng/build-job.yml b/eng/build-job.yml
index 7e9f631c01..1d3cde4baf 100644
--- a/eng/build-job.yml
+++ b/eng/build-job.yml
@@ -195,10 +195,3 @@ jobs:
targetPath: $(Build.SourcesDirectory)/bin/Logs
continueOnError: true
condition: always()
-
- # Kill tasks that hold onto files on Windows. Otherwise git clean
- # may fail for later jobs on the same agent.
- - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - script: eng/kill_tasks.cmd
- displayName: Kill tasks that hold on to files
- condition: always()
diff --git a/eng/kill_tasks.cmd b/eng/kill_tasks.cmd
deleted file mode 100644
index ee7099c94d..0000000000
--- a/eng/kill_tasks.cmd
+++ /dev/null
@@ -1,10 +0,0 @@
-@if not defined _echo @echo off
-setlocal EnableDelayedExpansion
-
-:: Check if VBCSCompiler.exe is running
-tasklist /fi "imagename eq VBCSCompiler.exe" |find ":" > nul
-:: Compiler is running if errorlevel == 1
-if errorlevel 1 (
- echo Stop VBCSCompiler.exe execution.
- for /f "tokens=2 delims=," %%F in ('tasklist /nh /fi "imagename eq VBCSCompiler.exe" /fo csv') do taskkill /f /PID %%~F
-)
diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc
index 517c548bd7..8e272ad2af 100644
--- a/src/dlls/mscorrc/mscorrc.rc
+++ b/src/dlls/mscorrc/mscorrc.rc
@@ -557,6 +557,7 @@ BEGIN
IDS_EE_BADMARSHAL_DECIMALARRAY "Invalid managed/unmanaged type combination (Decimal[] must be paired with an ArraySubType of Struct or Currency)."
IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS "Invalid managed/unmanaged type combination (Windows Runtime parameters and fields must not have a MarshalAs attribute set)."
IDS_EE_BADMARSHAL_WINRT_MISSING_GUID "Invalid managed/unmanaged type combination (Windows Runtime interfaces, classes and delegates must have a Guid or a default interface)."
+ IDS_EE_BADMARSHAL_WINRT_COPYCTOR "Windows Runtime marshaler does not support types with copy constructor."
IDS_EE_BADMARSHAL_WINRT_DELEGATE "Invalid managed/unmanaged type combination (Delegates must be Windows Runtime delegates)."
IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_WINRT_IFACE "The default interface must refer to a Windows Runtime interface with a GUID."
IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_SUBTYPE "The default interface must refer to an interface that is implemented by the type."
@@ -611,6 +612,7 @@ BEGIN
IDS_EE_BADMARSHAL_ASANYRESTRICTION "AsAny cannot be used on return types, ByRef parameters, ArrayWithOffset, or parameters passed from unmanaged to managed."
IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION "VBByRefStr can only be used in combination with in/out, ByRef managed-to-unmanaged strings."
IDS_EE_BADMARSHAL_AWORESTRICTION "ArrayWithOffsets can only be marshaled as inout, non-ByRef, managed-to-unmanaged parameters."
+ IDS_EE_BADMARSHAL_COPYCTORRESTRICTION "Classes with copy-ctors can only be marshaled by value."
IDS_EE_BADMARSHAL_ARGITERATORRESTRICTION "ArgIterators cannot be marshaled ByRef."
IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION "HandleRefs cannot be marshaled ByRef or from unmanaged to managed."
IDS_EE_BADMARSHAL_SAFEHANDLENATIVETOCOM "SafeHandles cannot be marshaled from unmanaged to managed."
diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h
index cec39bbb30..a7d94874f4 100644
--- a/src/dlls/mscorrc/resource.h
+++ b/src/dlls/mscorrc/resource.h
@@ -718,3 +718,5 @@
#define IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL 0x2644
#define IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO 0x2645
#define IDS_EE_BADMARSHAL_STRING_OUT 0x2646
+#define IDS_EE_BADMARSHAL_COPYCTORRESTRICTION 0x2647
+#define IDS_EE_BADMARSHAL_WINRT_COPYCTOR 0x2648
diff --git a/src/jit/codegen.h b/src/jit/codegen.h
index be20865c0e..11c81c4b91 100644
--- a/src/jit/codegen.h
+++ b/src/jit/codegen.h
@@ -561,8 +561,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
siVarLoc* varLoc);
void genSetScopeInfo();
+#ifdef USING_SCOPE_INFO
+ void genSetScopeInfoUsingsiScope();
-protected:
/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -668,7 +669,6 @@ public:
const char* siStackVarName(size_t offs, size_t size, unsigned reg, unsigned stkOffs);
#endif // LATE_DISASM
-public:
/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -749,14 +749,16 @@ protected:
void psiEndPrologScope(psiScope* scope);
void psSetScopeOffset(psiScope* newScope, LclVarDsc* lclVarDsc1);
+#endif // USING_SCOPE_INFO
-/*****************************************************************************
- * TrnslLocalVarInfo
- *
- * This struct holds the LocalVarInfo in terms of the generated native code
- * after a call to genSetScopeInfo()
- */
+ /*****************************************************************************
+ * TrnslLocalVarInfo
+ *
+ * This struct holds the LocalVarInfo in terms of the generated native code
+ * after a call to genSetScopeInfo()
+ */
+protected:
#ifdef DEBUG
struct TrnslLocalVarInfo
diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp
index 50180133d4..0c84bedb75 100644
--- a/src/jit/codegenarmarch.cpp
+++ b/src/jit/codegenarmarch.cpp
@@ -3860,11 +3860,12 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
#ifdef _TARGET_ARM_
compiler->unwindAllocStack(frameSize);
-
+#ifdef USING_SCOPE_INFO
if (!doubleAlignOrFramePointerUsed())
{
psiAdjustStackLevel(frameSize);
}
+#endif // USING_SCOPE_INFO
#endif // _TARGET_ARM_
}
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index b90cf5548d..2b5236b82a 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -732,8 +732,9 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
JITDUMP("\t\t\t\t\t\t\tV%02u becoming live\n", varNum);
}
}
-
+#ifdef USING_SCOPE_INFO
codeGen->siUpdate();
+#endif // USING_SCOPE_INFO
}
// Need an explicit instantiation.
@@ -3804,11 +3805,12 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
assert(varDsc->lvSize() >= baseOffset + (unsigned)size);
}
#endif // !UNIX_AMD64_ABI
-
+#ifdef USING_SCOPE_INFO
if (regArgTab[argNum].slot == 1)
{
psiMoveToStack(varNum);
}
+#endif // USING_SCOPE_INFO
}
/* mark the argument as processed */
@@ -3952,9 +3954,10 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
regArgMaskLive &= ~genRegMask(varDscSrc->lvArgReg);
regArgMaskLive &= ~genRegMask(varDscDest->lvArgReg);
-
+#ifdef USING_SCOPE_INFO
psiMoveToReg(varNumSrc);
psiMoveToReg(varNumDest);
+#endif // USING_SCOPE_INFO
}
else
#endif // _TARGET_XARCH_
@@ -4016,9 +4019,9 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
regSet.verifyRegUsed(xtraReg);
*pXtraRegClobbered = true;
-
+#ifdef USING_SCOPE_INFO
psiMoveToReg(varNumDest, xtraReg);
-
+#endif // USING_SCOPE_INFO
/* start moving everything to its right place */
while (srcReg != begReg)
@@ -4083,9 +4086,9 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
getEmitter()->emitIns_R_R(insCopy, size, destRegNum, xtraReg);
regSet.verifyRegUsed(destRegNum);
-
+#ifdef USING_SCOPE_INFO
psiMoveToReg(varNumSrc);
-
+#endif // USING_SCOPE_INFO
/* mark the beginning register as processed */
regArgTab[srcReg].processed = true;
@@ -4269,8 +4272,9 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
#endif
getEmitter()->emitIns_R_R(ins_Copy(destMemType), size, destRegNum, regNum);
-
+#ifdef USING_SCOPE_INFO
psiMoveToReg(varNum);
+#endif // USING_SCOPE_INFO
}
/* mark the argument as processed */
@@ -4404,8 +4408,9 @@ void CodeGen::genEnregisterIncomingStackArgs()
getEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), regNum, varNum, 0);
regSet.verifyRegUsed(regNum);
-
+#ifdef USING_SCOPE_INFO
psiMoveToReg(varNum);
+#endif // USING_SCOPE_INFO
}
}
@@ -5247,12 +5252,12 @@ void CodeGen::genPushCalleeSavedRegisters()
{
inst_RV(INS_push, reg, TYP_REF);
compiler->unwindPush(reg);
-
+#ifdef USING_SCOPE_INFO
if (!doubleAlignOrFramePointerUsed())
{
psiAdjustStackLevel(REGSIZE_BYTES);
}
-
+#endif // USING_SCOPE_INFO
rsPushRegs &= ~regBit;
}
}
@@ -7531,7 +7536,9 @@ void CodeGen::genEstablishFramePointer(int delta, bool reportUnwindData)
if (delta == 0)
{
getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_FPBASE, REG_SPBASE);
+#ifdef USING_SCOPE_INFO
psiMoveESPtoEBP();
+#endif // USING_SCOPE_INFO
}
else
{
@@ -7633,12 +7640,13 @@ void CodeGen::genFnProlog()
printf("\n__prolog:\n");
}
#endif
-
+#ifdef USING_SCOPE_INFO
if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0))
{
// Create new scopes for the method-parameters for the prolog-block.
psiBegProlog();
}
+#endif // USING_SCOPE_INFO
#ifdef DEBUG
@@ -7963,8 +7971,9 @@ void CodeGen::genFnProlog()
{
inst_RV(INS_push, REG_FPBASE, TYP_REF);
compiler->unwindPush(REG_FPBASE);
+#ifdef USING_SCOPE_INFO
psiAdjustStackLevel(REGSIZE_BYTES);
-
+#endif // USING_SCOPE_INFO
#ifndef _TARGET_AMD64_ // On AMD64, establish the frame pointer after the "sub rsp"
genEstablishFramePointer(0, /*reportUnwindData*/ true);
#endif // !_TARGET_AMD64_
@@ -8284,12 +8293,12 @@ void CodeGen::genFnProlog()
genPrologPadForReJit();
getEmitter()->emitMarkPrologEnd();
}
-
+#ifdef USING_SCOPE_INFO
if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0))
{
psiEndProlog();
}
-
+#endif // USING_SCOPE_INFO
if (hasGCRef)
{
getEmitter()->emitSetFrameRangeGCRs(GCrefLo, GCrefHi);
@@ -10486,27 +10495,40 @@ void CodeGen::genSetScopeInfo()
}
noway_assert(compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0));
- noway_assert(psiOpenScopeList.scNext == nullptr);
-
- unsigned i;
- unsigned scopeCnt = siScopeCnt + psiScopeCnt;
- compiler->eeSetLVcount(scopeCnt);
+ unsigned varsHomeCount = 0;
+#ifdef USING_SCOPE_INFO
+ varsHomeCount = siScopeCnt + psiScopeCnt;
+#endif // USING_SCOPE_INFO
+ compiler->eeSetLVcount(varsHomeCount);
#ifdef DEBUG
- genTrnslLocalVarCount = scopeCnt;
- if (scopeCnt)
+ genTrnslLocalVarCount = varsHomeCount;
+ if (varsHomeCount)
{
- genTrnslLocalVarInfo = new (compiler, CMK_DebugOnly) TrnslLocalVarInfo[scopeCnt];
+ genTrnslLocalVarInfo = new (compiler, CMK_DebugOnly) TrnslLocalVarInfo[varsHomeCount];
}
#endif
+#ifdef USING_SCOPE_INFO
+ genSetScopeInfoUsingsiScope();
+#endif // USING_SCOPE_INFO
+
+ compiler->eeSetLVdone();
+}
+
+#ifdef USING_SCOPE_INFO
+void CodeGen::genSetScopeInfoUsingsiScope()
+{
+ noway_assert(psiOpenScopeList.scNext == nullptr);
+
// Record the scopes found for the parameters over the prolog.
// The prolog needs to be treated differently as a variable may not
// have the same info in the prolog block as is given by compiler->lvaTable.
// eg. A register parameter is actually on the stack, before it is loaded to reg.
CodeGen::psiScope* scopeP;
+ unsigned i;
for (i = 0, scopeP = psiScopeList.scNext; i < psiScopeCnt; i++, scopeP = scopeP->scNext)
{
@@ -10563,9 +10585,8 @@ void CodeGen::genSetScopeInfo()
genSetScopeInfo(psiScopeCnt + i, startOffs, endOffs - startOffs, scopeL->scVarNum, scopeL->scLVnum,
scopeL->scAvailable, &varLoc);
}
-
- compiler->eeSetLVdone();
}
+#endif // USING_SCOPE_INFO
//------------------------------------------------------------------------
// genSetScopeInfo: Record scope information for debug info
diff --git a/src/jit/codegeninterface.h b/src/jit/codegeninterface.h
index 94fd8f4635..9a67649084 100644
--- a/src/jit/codegeninterface.h
+++ b/src/jit/codegeninterface.h
@@ -25,6 +25,12 @@
#include "jitgcinfo.h"
#include "treelifeupdater.h"
+// Disable this flag to avoid using psiScope/siScope info to report reporting
+// variables' home location during the method/prolog code.
+#if 1
+#define USING_SCOPE_INFO
+#endif // USING_SCOPE_INFO
+
// Forward reference types
class CodeGenInterface;
@@ -385,7 +391,9 @@ private:
bool m_cgFullPtrRegMap;
public:
+#ifdef USING_SCOPE_INFO
virtual void siUpdate() = 0;
+#endif // USING_SCOPE_INFO
/* These are the different addressing modes used to access a local var.
* The JIT has to report the location of the locals back to the EE
diff --git a/src/jit/codegenlinear.cpp b/src/jit/codegenlinear.cpp
index 149bb3333f..c0a20343a3 100644
--- a/src/jit/codegenlinear.cpp
+++ b/src/jit/codegenlinear.cpp
@@ -84,12 +84,13 @@ void CodeGen::genInitializeRegisterState()
// iterated.
void CodeGen::genInitialize()
{
+#ifdef USING_SCOPE_INFO
// Initialize the line# tracking logic
-
if (compiler->opts.compScopeInfo)
{
siInit();
}
+#endif // USING_SCOPE_INFO
// The current implementation of switch tables requires the first block to have a label so it
// can generate offsets to the switch label targets.
@@ -350,9 +351,9 @@ void CodeGen::genCodeForBBlist()
/* Tell everyone which basic block we're working on */
compiler->compCurBB = block;
-
+#ifdef USING_SCOPE_INFO
siBeginBlock(block);
-
+#endif // USING_SCOPE_INFO
// BBF_INTERNAL blocks don't correspond to any single IL instruction.
if (compiler->opts.compDbgInfo && (block->bbFlags & BBF_INTERNAL) &&
!compiler->fgBBisScratch(block)) // If the block is the distinguished first scratch block, then no need to
@@ -508,7 +509,7 @@ void CodeGen::genCodeForBBlist()
// This can lead to problems when debugging the generated code. To prevent these issues, make sure
// we've generated code for the last IL offset we saw in the block.
genEnsureCodeEmitted(currentILOffset);
-
+#ifdef USING_SCOPE_INFO
if (compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0))
{
siEndBlock(block);
@@ -533,6 +534,7 @@ void CodeGen::genCodeForBBlist()
siCloseAllOpenScopes();
}
}
+#endif // USING_SCOPE_INFO
SubtractStackLevel(savedStkLvl);
diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp
index f332b0043a..9256650978 100644
--- a/src/jit/codegenxarch.cpp
+++ b/src/jit/codegenxarch.cpp
@@ -2333,11 +2333,12 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
}
compiler->unwindAllocStack(frameSize);
-
+#ifdef USING_SCOPE_INFO
if (!doubleAlignOrFramePointerUsed())
{
psiAdjustStackLevel(frameSize);
}
+#endif // USING_SCOPE_INFO
}
//------------------------------------------------------------------------
diff --git a/src/jit/scopeinfo.cpp b/src/jit/scopeinfo.cpp
index 3a47a32453..9e8d6b911c 100644
--- a/src/jit/scopeinfo.cpp
+++ b/src/jit/scopeinfo.cpp
@@ -131,30 +131,6 @@ bool CodeGenInterface::siVarLoc::vlIsOnStk(regNumber reg, signed offset) const
}
//------------------------------------------------------------------------
-// siVarLoc: Non-empty constructor of siVarLoc struct
-// Arguments:
-// varDsc - a "LclVarDsc *" to the variable it is desired to build the "siVarLoc".
-// baseReg - a "regNumber" use as a base for the offset.
-// offset - a signed amount of bytes distance from "baseReg" for the position of the variable.
-// isFramePointerUsed - a boolean variable
-//
-// Notes:
-// Called for every psiScope in "psiScopeList" codegen.h
-CodeGenInterface::siVarLoc::siVarLoc(const LclVarDsc* varDsc, regNumber baseReg, int offset, bool isFramePointerUsed)
-{
- var_types type = genActualType(varDsc->TypeGet());
-
- if (varDsc->lvIsInReg())
- {
- siFillRegisterVarLoc(varDsc, type, baseReg, offset, isFramePointerUsed);
- }
- else
- {
- siFillStackVarLoc(varDsc, type, baseReg, offset, isFramePointerUsed);
- }
-}
-
-//------------------------------------------------------------------------
// Equals: Compares first reference and then values of the structures.
//
// Arguments:
@@ -228,65 +204,6 @@ bool CodeGenInterface::siVarLoc::Equals(const siVarLoc* lhs, const siVarLoc* rhs
}
//------------------------------------------------------------------------
-// getSiVarLoc: Creates a "CodegenInterface::siVarLoc" instance from using the properties
-// of the "psiScope" instance.
-//
-// Notes:
-// Called for every psiScope in "psiScopeList" codegen.h
-CodeGenInterface::siVarLoc CodeGen::psiScope::getSiVarLoc() const
-{
- CodeGenInterface::siVarLoc varLoc;
-
- if (scRegister)
- {
- varLoc.vlType = VLT_REG;
- varLoc.vlReg.vlrReg = (regNumber)u1.scRegNum;
- }
- else
- {
- varLoc.vlType = VLT_STK;
- varLoc.vlStk.vlsBaseReg = (regNumber)u2.scBaseReg;
- varLoc.vlStk.vlsOffset = u2.scOffset;
- }
-
- return varLoc;
-}
-
-//------------------------------------------------------------------------
-// getSiVarLoc: Returns a "siVarLoc" instance representing the place where the variable
-// is given its description, "baseReg", and "offset" (if needed).
-//
-// Arguments:
-// varDsc - a "LclVarDsc *" to the variable it is desired to build the "siVarLoc".
-// scope - a "siScope" Scope info of the variable.
-//
-// Return Value:
-// A "siVarLoc" filled with the correct case struct fields for the variable, which could live
-// in a register, an stack position, or a combination of both.
-//
-// Notes:
-// Called for each siScope in siScopeList when "genSetScopeInfo".
-CodeGenInterface::siVarLoc CodeGen::getSiVarLoc(const LclVarDsc* varDsc, const siScope* scope) const
-{
- // For stack vars, find the base register, and offset
-
- regNumber baseReg;
- signed offset = varDsc->lvStkOffs;
-
- if (!varDsc->lvFramePointerBased)
- {
- baseReg = REG_SPBASE;
- offset += scope->scStackLevel;
- }
- else
- {
- baseReg = REG_FPBASE;
- }
-
- return CodeGenInterface::siVarLoc(varDsc, baseReg, offset, isFramePointerUsed());
-}
-
-//------------------------------------------------------------------------
// siFillStackVarLoc: Fill "siVarLoc" struct indicating the stack position of the variable
// using "LclVarDsc" and "baseReg"/"offset".
//
@@ -471,6 +388,90 @@ void CodeGenInterface::siVarLoc::siFillRegisterVarLoc(
}
}
+//------------------------------------------------------------------------
+// siVarLoc: Non-empty constructor of siVarLoc struct
+// Arguments:
+// varDsc - a "LclVarDsc *" to the variable it is desired to build the "siVarLoc".
+// baseReg - a "regNumber" use as a base for the offset.
+// offset - a signed amount of bytes distance from "baseReg" for the position of the variable.
+// isFramePointerUsed - a boolean variable
+//
+// Notes:
+// Called for every psiScope in "psiScopeList" codegen.h
+CodeGenInterface::siVarLoc::siVarLoc(const LclVarDsc* varDsc, regNumber baseReg, int offset, bool isFramePointerUsed)
+{
+ var_types type = genActualType(varDsc->TypeGet());
+
+ if (varDsc->lvIsInReg())
+ {
+ siFillRegisterVarLoc(varDsc, type, baseReg, offset, isFramePointerUsed);
+ }
+ else
+ {
+ siFillStackVarLoc(varDsc, type, baseReg, offset, isFramePointerUsed);
+ }
+}
+
+#ifdef USING_SCOPE_INFO
+//------------------------------------------------------------------------
+// getSiVarLoc: Returns a "siVarLoc" instance representing the place where the variable
+// is given its description, "baseReg", and "offset" (if needed).
+//
+// Arguments:
+// varDsc - a "LclVarDsc *" to the variable it is desired to build the "siVarLoc".
+// scope - a "siScope" Scope info of the variable.
+//
+// Return Value:
+// A "siVarLoc" filled with the correct case struct fields for the variable, which could live
+// in a register, an stack position, or a combination of both.
+//
+// Notes:
+// Called for each siScope in siScopeList when "genSetScopeInfo".
+CodeGenInterface::siVarLoc CodeGen::getSiVarLoc(const LclVarDsc* varDsc, const siScope* scope) const
+{
+ // For stack vars, find the base register, and offset
+
+ regNumber baseReg;
+ signed offset = varDsc->lvStkOffs;
+
+ if (!varDsc->lvFramePointerBased)
+ {
+ baseReg = REG_SPBASE;
+ offset += scope->scStackLevel;
+ }
+ else
+ {
+ baseReg = REG_FPBASE;
+ }
+
+ return CodeGenInterface::siVarLoc(varDsc, baseReg, offset, isFramePointerUsed());
+}
+
+//------------------------------------------------------------------------
+// getSiVarLoc: Creates a "CodegenInterface::siVarLoc" instance from using the properties
+// of the "psiScope" instance.
+//
+// Notes:
+// Called for every psiScope in "psiScopeList" codegen.h
+CodeGenInterface::siVarLoc CodeGen::psiScope::getSiVarLoc() const
+{
+ CodeGenInterface::siVarLoc varLoc;
+
+ if (scRegister)
+ {
+ varLoc.vlType = VLT_REG;
+ varLoc.vlReg.vlrReg = (regNumber)u1.scRegNum;
+ }
+ else
+ {
+ varLoc.vlType = VLT_STK;
+ varLoc.vlStk.vlsBaseReg = (regNumber)u2.scBaseReg;
+ varLoc.vlStk.vlsOffset = u2.scOffset;
+ }
+
+ return varLoc;
+}
+
/*============================================================================
*
* Implementation for ScopeInfo
@@ -1613,3 +1614,4 @@ void CodeGen::psiEndProlog()
psiEndPrologScope(scope);
}
}
+#endif // USING_SCOPE_INFO
diff --git a/src/jit/treelifeupdater.cpp b/src/jit/treelifeupdater.cpp
index ecfdaeee86..d5e3ad9a0b 100644
--- a/src/jit/treelifeupdater.cpp
+++ b/src/jit/treelifeupdater.cpp
@@ -245,8 +245,9 @@ void TreeLifeUpdater<ForCodeGen>::UpdateLifeVar(GenTree* tree)
}
#endif // DEBUG
}
-
+#ifdef USING_SCOPE_INFO
compiler->codeGen->siUpdate();
+#endif // USING_SCOPE_INFO
}
}
diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp
index 6fb16c51f6..f4c2838385 100644
--- a/src/vm/dllimport.cpp
+++ b/src/vm/dllimport.cpp
@@ -4139,6 +4139,7 @@ static void CreateNDirectStubWorker(StubState* pss,
COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_BADNATL_THISCALL);
}
+ fHasCopyCtorArgs = info.GetMarshalType() == MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR ? TRUE : FALSE;
argidx++;
}
diff --git a/src/vm/ilmarshalers.cpp b/src/vm/ilmarshalers.cpp
index 2b7f7a6cdf..7d8f04671c 100644
--- a/src/vm/ilmarshalers.cpp
+++ b/src/vm/ilmarshalers.cpp
@@ -3292,6 +3292,92 @@ ILCriticalHandleMarshaler::ReturnOverride(
return OVERRIDDEN;
} // ILCriticalHandleMarshaler::ReturnOverride
+MarshalerOverrideStatus ILBlittableValueClassWithCopyCtorMarshaler::ArgumentOverride(NDirectStubLinker* psl,
+ BOOL byref,
+ BOOL fin,
+ BOOL fout,
+ BOOL fManagedToNative,
+ OverrideProcArgs* pargs,
+ UINT* pResID,
+ UINT argidx,
+ UINT nativeStackOffset)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ ILCodeStream* pslIL = psl->GetMarshalCodeStream();
+ ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
+
+ if (byref)
+ {
+ *pResID = IDS_EE_BADMARSHAL_COPYCTORRESTRICTION;
+ return DISALLOWED;
+ }
+
+ if (fManagedToNative)
+ {
+ // 1) create new native value type local
+ // 2) run new->CopyCtor(old)
+ // 3) run old->Dtor()
+
+ LocalDesc locDesc(pargs->mm.m_pMT);
+
+ DWORD dwNewValueTypeLocal;
+
+ // Step 1
+ dwNewValueTypeLocal = pslIL->NewLocal(locDesc);
+
+ // Step 2
+ if (pargs->mm.m_pCopyCtor)
+ {
+ // Managed copy constructor has signature of CopyCtor(T* new, T old);
+ pslIL->EmitLDLOCA(dwNewValueTypeLocal);
+ pslIL->EmitLDARG(argidx);
+ pslIL->EmitCALL(pslIL->GetToken(pargs->mm.m_pCopyCtor), 2, 0);
+ }
+ else
+ {
+ pslIL->EmitLDARG(argidx);
+ pslIL->EmitLDOBJ(pslIL->GetToken(pargs->mm.m_pMT));
+ pslIL->EmitSTLOC(dwNewValueTypeLocal);
+ }
+
+ // Step 3
+ if (pargs->mm.m_pDtor)
+ {
+ // Managed destructor has signature of Destructor(T old);
+ pslIL->EmitLDARG(argidx);
+ pslIL->EmitCALL(pslIL->GetToken(pargs->mm.m_pDtor), 1, 0);
+ }
+#ifdef _TARGET_X86_
+ pslIL->SetStubTargetArgType(&locDesc); // native type is the value type
+ pslILDispatch->EmitLDLOC(dwNewValueTypeLocal); // we load the local directly
+#else
+ pslIL->SetStubTargetArgType(ELEMENT_TYPE_I); // native type is a pointer
+ pslILDispatch->EmitLDLOCA(dwNewValueTypeLocal);
+#endif
+
+ return OVERRIDDEN;
+ }
+ else
+ {
+ // nothing to do but pass the value along
+ // note that on x86 the argument comes by-value but is converted to pointer by the UM thunk
+ // so that we don't make copies that would not be accounted for by copy ctors
+ LocalDesc locDesc(pargs->mm.m_pMT);
+ locDesc.MakeCopyConstructedPointer();
+
+ pslIL->SetStubTargetArgType(&locDesc); // native type is a pointer
+ pslILDispatch->EmitLDARG(argidx);
+
+ return OVERRIDDEN;
+ }
+}
LocalDesc ILArgIteratorMarshaler::GetNativeType()
{
diff --git a/src/vm/ilmarshalers.h b/src/vm/ilmarshalers.h
index 99a3d8f8d6..c892ae66a9 100644
--- a/src/vm/ilmarshalers.h
+++ b/src/vm/ilmarshalers.h
@@ -2725,8 +2725,40 @@ protected:
virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
};
+class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler
+{
+public:
+ enum
+ {
+ c_fInOnly = TRUE,
+ c_nativeSize = VARIABLESIZE,
+ c_CLRSize = sizeof(OBJECTREF),
+ };
+ LocalDesc GetManagedType()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return LocalDesc();
+ }
+ LocalDesc GetNativeType()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return LocalDesc();
+ }
+
+ static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
+ BOOL byref,
+ BOOL fin,
+ BOOL fout,
+ BOOL fManagedToNative,
+ OverrideProcArgs* pargs,
+ UINT* pResID,
+ UINT argidx,
+ UINT nativeStackOffset);
+
+
+};
class ILArgIteratorMarshaler : public ILMarshaler
{
diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp
index e007891aa8..edbf759322 100644
--- a/src/vm/mlinfo.cpp
+++ b/src/vm/mlinfo.cpp
@@ -1438,6 +1438,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
CorNativeType nativeType = NATIVE_TYPE_DEFAULT;
Assembly *pAssembly = pModule->GetAssembly();
+ BOOL fNeedsCopyCtor = FALSE;
m_BestFit = BestFit;
m_ThrowOnUnmappableChar = ThrowOnUnmappableChar;
m_ms = ms;
@@ -1548,6 +1549,21 @@ MarshalInfo::MarshalInfo(Module* pModule,
IfFailGoto(sig.GetElemType(NULL), lFail);
mtype = sig.PeekElemTypeNormalized(pModule, pTypeContext);
+ // Check for Copy Constructor Modifier - peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE
+ // turning into a primitive.
+ if (sig.PeekElemTypeClosed(pModule, pTypeContext) == ELEMENT_TYPE_VALUETYPE)
+ {
+ // Skip ET_BYREF
+ IfFailGoto(sigtmp.GetByte(NULL), lFail);
+
+ if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
+ sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
+ {
+ mtype = ELEMENT_TYPE_VALUETYPE;
+ fNeedsCopyCtor = TRUE;
+ m_byref = FALSE;
+ }
+ }
}
else
{
@@ -1590,6 +1606,19 @@ MarshalInfo::MarshalInfo(Module* pModule,
IfFailGoto(E_FAIL, lFail);
}
+ // Check for Copy Constructor Modifier
+ if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
+ sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
+ {
+ mtype = mtype2;
+
+ // Keep the sig pointer in sync with mtype (skip ELEMENT_TYPE_PTR) because for the rest
+ // of this method we are pretending that the parameter is a value type passed by-value.
+ IfFailGoto(sig.GetElemType(NULL), lFail);
+
+ fNeedsCopyCtor = TRUE;
+ m_byref = FALSE;
+ }
}
}
else
@@ -2684,6 +2713,29 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
else
{
+ if (fNeedsCopyCtor)
+ {
+#ifdef FEATURE_COMINTEROP
+ if (m_ms == MARSHAL_SCENARIO_WINRT)
+ {
+ // our WinRT-optimized GetCOMIPFromRCW helpers don't support copy
+ // constructor stubs so make sure that this marshaler will not be used
+ m_resID = IDS_EE_BADMARSHAL_WINRT_COPYCTOR;
+ IfFailGoto(E_FAIL, lFail);
+ }
+#endif
+
+ MethodDesc *pCopyCtor;
+ MethodDesc *pDtor;
+ FindCopyCtor(pModule, m_pMT, &pCopyCtor);
+ FindDtor(pModule, m_pMT, &pDtor);
+
+ m_args.mm.m_pMT = m_pMT;
+ m_args.mm.m_pCopyCtor = pCopyCtor;
+ m_args.mm.m_pDtor = pDtor;
+ m_type = MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR;
+ }
+ else
#ifdef _TARGET_X86_
// JIT64 is not aware of normalized value types and this optimization
// (returning small value types by value in registers) is already done in JIT64.
@@ -3398,6 +3450,7 @@ UINT16 MarshalInfo::GetNativeSize(MarshalType mtype, MarshalScenario ms)
{
case MARSHAL_TYPE_BLITTABLEVALUECLASS:
case MARSHAL_TYPE_VALUECLASS:
+ case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
return (UINT16) m_pMT->GetNativeSize();
default:
@@ -4049,6 +4102,7 @@ DispParamMarshaler *MarshalInfo::GenerateDispParamMarshaler()
case MARSHAL_TYPE_BLITTABLEVALUECLASS:
case MARSHAL_TYPE_BLITTABLEPTR:
case MARSHAL_TYPE_LAYOUTCLASSPTR:
+ case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
pDispParamMarshaler = new DispParamRecordMarshaler(m_pMT);
break;
@@ -4350,6 +4404,9 @@ VOID MarshalInfo::MarshalTypeToString(SString& strMarshalType, BOOL fSizeIsSpeci
case MARSHAL_TYPE_ARGITERATOR:
strRetVal = W("ArgIterator");
break;
+ case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
+ strRetVal = W("blittable value class with copy constructor");
+ break;
#ifdef FEATURE_COMINTEROP
case MARSHAL_TYPE_OBJECT:
strRetVal = W("VARIANT");
diff --git a/src/vm/mtypes.h b/src/vm/mtypes.h
index af21d267c7..5f75eeb6e6 100644
--- a/src/vm/mtypes.h
+++ b/src/vm/mtypes.h
@@ -88,7 +88,7 @@ DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_VALUECLASS, ValueClassMa
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_REFERENCECUSTOMMARSHALER, ReferenceCustomMarshaler, false)
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_ARGITERATOR, ArgIteratorMarshaler, false)
-
+DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR, BlittableValueClassWithCopyCtorMarshaler, false)
#ifdef FEATURE_COMINTEROP
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_OBJECT, ObjectMarshaler, false)
diff --git a/tests/src/GC/API/GC/Collect.csproj b/tests/src/GC/API/GC/Collect.csproj
index 6a07e5527a..36a935e502 100644
--- a/tests/src/GC/API/GC/Collect.csproj
+++ b/tests/src/GC/API/GC/Collect.csproj
@@ -11,6 +11,7 @@
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<CLRTestPriority>1</CLRTestPriority>
+ <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt
index b4dec5750d..32e4b77e16 100644
--- a/tests/src/Interop/CMakeLists.txt
+++ b/tests/src/Interop/CMakeLists.txt
@@ -89,5 +89,6 @@ if(WIN32)
if(NOT CLR_CMAKE_PLATFORM_ARCH_ARM64)
add_subdirectory(IJW/ManagedCallingNative/IjwNativeDll)
add_subdirectory(IJW/NativeCallingManaged/IjwNativeCallingManagedDll)
+ add_subdirectory(IJW/CopyConstructorMarshaler)
endif()
endif(WIN32)
diff --git a/tests/src/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt b/tests/src/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt
new file mode 100644
index 0000000000..57726a4318
--- /dev/null
+++ b/tests/src/Interop/IJW/CopyConstructorMarshaler/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required (VERSION 2.6)
+project (CopyConstructorMarshaler)
+include_directories( ${INC_PLATFORM_DIR} )
+set(SOURCES IjwCopyConstructorMarshaler.cpp)
+
+if (WIN32)
+ # 4365 - signed/unsigned mismatch
+ add_compile_options(/wd4365)
+
+ # IJW
+ add_compile_options(/clr)
+
+ # IJW requires the CRT as a dll, not linked in
+ add_compile_options(/MD$<$<OR:$<CONFIG:Debug>,$<CONFIG:Checked>>:d>)
+
+ # CMake enables /RTC1 and /EHsc by default, but they're not compatible with /clr, so remove them
+ if(CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
+ string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+ endif()
+
+ if(CMAKE_CXX_FLAGS MATCHES "/EHsc")
+ string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ endif()
+
+ # IJW isn't compatible with CFG
+ if(CMAKE_CXX_FLAGS MATCHES "/guard:cf")
+ string(REPLACE "/guard:cf" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ endif()
+
+ # IJW isn't compatible with GR-
+ if(CMAKE_CXX_FLAGS MATCHES "/GR-")
+ string(REPLACE "/GR-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ endif()
+
+endif()
+
+# add the shared library
+add_library (IjwCopyConstructorMarshaler SHARED ${SOURCES})
+target_link_libraries(IjwCopyConstructorMarshaler ${LINK_LIBRARIES_ADDITIONAL})
+
+# add the install targets
+install (TARGETS IjwCopyConstructorMarshaler DESTINATION bin)
diff --git a/tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs b/tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs
new file mode 100644
index 0000000000..d589cd4fe8
--- /dev/null
+++ b/tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs
@@ -0,0 +1,66 @@
+// 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.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+namespace CopyConstructorMarshaler
+{
+ class CopyConstructorMarshaler
+ {
+ static int Main(string[] args)
+ {
+ if(Environment.OSVersion.Platform != PlatformID.Win32NT || TestLibrary.Utilities.IsWindows7)
+ {
+ return 100;
+ }
+
+ try
+ {
+ // Load a fake mscoree.dll to avoid starting desktop
+ LoadLibraryEx(Path.Combine(Environment.CurrentDirectory, "mscoree.dll"), IntPtr.Zero, 0);
+
+ Assembly ijwNativeDll = Assembly.Load("IjwCopyConstructorMarshaler");
+ Type testType = ijwNativeDll.GetType("TestClass");
+ object testInstance = Activator.CreateInstance(testType);
+ MethodInfo testMethod = testType.GetMethod("PInvokeNumCopies");
+
+ // PInvoke will copy twice. Once from argument to parameter, and once from the managed to native parameter.
+ Assert.AreEqual(2, (int)testMethod.Invoke(testInstance, null));
+
+ testMethod = testType.GetMethod("ReversePInvokeNumCopies");
+
+ // Reverse PInvoke will copy 3 times. Two are from the same paths as the PInvoke,
+ // and the third is from the reverse P/Invoke call.
+ Assert.AreEqual(3, (int)testMethod.Invoke(testInstance, null));
+
+ testMethod = testType.GetMethod("PInvokeNumCopiesDerivedType");
+
+ // PInvoke will copy twice. Once from argument to parameter, and once from the managed to native parameter.
+ Assert.AreEqual(2, (int)testMethod.Invoke(testInstance, null));
+
+ testMethod = testType.GetMethod("ReversePInvokeNumCopiesDerivedType");
+
+ // Reverse PInvoke will copy 3 times. Two are from the same paths as the PInvoke,
+ // and the third is from the reverse P/Invoke call.
+ Assert.AreEqual(3, (int)testMethod.Invoke(testInstance, null));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ return 101;
+ }
+ return 100;
+ }
+
+ [DllImport("kernel32.dll")]
+ static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, int dwFlags);
+
+ [DllImport("kernel32.dll")]
+ static extern IntPtr GetModuleHandle(string lpModuleName);
+ }
+}
diff --git a/tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj b/tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj
new file mode 100644
index 0000000000..34aad536a0
--- /dev/null
+++ b/tests/src/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj
@@ -0,0 +1,44 @@
+<?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" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>CopyConstructorMarshaler</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{49D1D482-E783-4CA9-B6BA-A9714BF81036}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+
+ <!-- IJW is Windows-only -->
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+
+ <!-- IJW is not supported on ARM64 -->
+ <DisableProjectBuild Condition="'$(Platform)' == 'arm64'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <PropertyGroup>
+ <CopyDebugCRTDllsToOutputDirectory>true</CopyDebugCRTDllsToOutputDirectory>
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="CopyConstructorMarshaler.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="CMakeLists.txt" />
+ <ProjectReference Include="../FakeMscoree/CMakeLists.txt" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/IJW/CopyConstructorMarshaler/IjwCopyConstructorMarshaler.cpp b/tests/src/Interop/IJW/CopyConstructorMarshaler/IjwCopyConstructorMarshaler.cpp
new file mode 100644
index 0000000000..b82c33b349
--- /dev/null
+++ b/tests/src/Interop/IJW/CopyConstructorMarshaler/IjwCopyConstructorMarshaler.cpp
@@ -0,0 +1,106 @@
+// 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.
+
+#pragma managed
+class A
+{
+ int copyCount;
+
+public:
+ A()
+ :copyCount(0)
+ {};
+
+ A(A& other)
+ :copyCount(other.copyCount + 1)
+ {}
+
+ int GetCopyCount()
+ {
+ return copyCount;
+ }
+};
+
+class B : public A
+{
+ int bCopyCount;
+
+public:
+ B()
+ :A(),
+ bCopyCount(0)
+ {};
+
+ B(B& other)
+ :A(other),
+ bCopyCount(other.bCopyCount + 1)
+ {}
+
+ int GetBCopyCount()
+ {
+ return bCopyCount;
+ }
+};
+
+int Managed_GetCopyCount(A a)
+{
+ return a.GetCopyCount();
+}
+
+int Managed_GetCopyCount(B b)
+{
+ return b.GetBCopyCount();
+}
+
+#pragma unmanaged
+
+int GetCopyCount(A a)
+{
+ return a.GetCopyCount();
+}
+
+int GetCopyCount_ViaManaged(A a)
+{
+ return Managed_GetCopyCount(a);
+}
+
+int GetCopyCount(B b)
+{
+ return b.GetBCopyCount();
+}
+
+int GetCopyCount_ViaManaged(B b)
+{
+ return Managed_GetCopyCount(b);
+}
+
+#pragma managed
+
+public ref class TestClass
+{
+public:
+ int PInvokeNumCopies()
+ {
+ A a;
+ return GetCopyCount(a);
+ }
+
+ int PInvokeNumCopiesDerivedType()
+ {
+ B b;
+ return GetCopyCount(b);
+ }
+
+ int ReversePInvokeNumCopies()
+ {
+ A a;
+ return GetCopyCount_ViaManaged(a);
+ }
+
+ int ReversePInvokeNumCopiesDerivedType()
+ {
+ B b;
+ return GetCopyCount_ViaManaged(b);
+ }
+};
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.cs
new file mode 100644
index 0000000000..0a589d18e8
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.cs
@@ -0,0 +1,221 @@
+// 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;
+using System.Threading;
+
+// Repro for issue fixed 18582 (also seein in 23309) -- stack overflow when remorphing
+// call with a lot of arguments and some CSEs when running with limited stack (as is
+// done when CLR is hosted by IIS).
+
+class GitHub_18582
+{
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Consume(
+ int x000, int x001, int x002, int x003, int x004, int x005, int x006, int x007, int x008, int x009,
+ int x010, int x011, int x012, int x013, int x014, int x015, int x016, int x017, int x018, int x019,
+ int x020, int x021, int x022, int x023, int x024, int x025, int x026, int x027, int x028, int x029,
+ int x030, int x031, int x032, int x033, int x034, int x035, int x036, int x037, int x038, int x039,
+ int x040, int x041, int x042, int x043, int x044, int x045, int x046, int x047, int x048, int x049,
+ int x050, int x051, int x052, int x053, int x054, int x055, int x056, int x057, int x058, int x059,
+ int x060, int x061, int x062, int x063, int x064, int x065, int x066, int x067, int x068, int x069,
+ int x070, int x071, int x072, int x073, int x074, int x075, int x076, int x077, int x078, int x079,
+ int x080, int x081, int x082, int x083, int x084, int x085, int x086, int x087, int x088, int x089,
+ int x090, int x091, int x092, int x093, int x094, int x095, int x096, int x097, int x098, int x099,
+ int x100, int x101, int x102, int x103, int x104, int x105, int x106, int x107, int x108, int x109,
+ int x110, int x111, int x112, int x113, int x114, int x115, int x116, int x117, int x118, int x119,
+ int x120, int x121, int x122, int x123, int x124, int x125, int x126, int x127, int x128, int x129,
+ int x130, int x131, int x132, int x133, int x134, int x135, int x136, int x137, int x138, int x139,
+ int x140, int x141, int x142, int x143, int x144, int x145, int x146, int x147, int x148, int x149,
+ int x150, int x151, int x152, int x153, int x154, int x155, int x156, int x157, int x158, int x159,
+ int x160, int x161, int x162, int x163, int x164, int x165, int x166, int x167, int x168, int x169,
+ int x170, int x171, int x172, int x173, int x174, int x175, int x176, int x177, int x178, int x179,
+ int x180, int x181, int x182, int x183, int x184, int x185, int x186, int x187, int x188, int x189,
+ int x190, int x191, int x192, int x193, int x194, int x195, int x196, int x197, int x198, int x199,
+ int x200, int x201, int x202, int x203, int x204, int x205, int x206, int x207, int x208, int x209,
+ int x210, int x211, int x212, int x213, int x214, int x215, int x216, int x217, int x218, int x219,
+ int x220, int x221, int x222, int x223, int x224, int x225, int x226, int x227, int x228, int x229,
+ int x230, int x231, int x232, int x233, int x234, int x235, int x236, int x237, int x238, int x239,
+ int x240, int x241, int x242, int x243, int x244, int x245, int x246, int x247, int x248, int x249,
+ int x250, int x251, int x252, int x253, int x254, int x255, int x256, int x257, int x258, int x259,
+ int x260, int x261, int x262, int x263, int x264, int x265, int x266, int x267, int x268, int x269,
+ int x270, int x271, int x272, int x273, int x274, int x275, int x276, int x277, int x278, int x279,
+ int x280, int x281, int x282, int x283, int x284, int x285, int x286, int x287, int x288, int x289,
+ int x290, int x291, int x292, int x293, int x294, int x295, int x296, int x297, int x298, int x299,
+ int x300, int x301, int x302, int x303, int x304, int x305, int x306, int x307, int x308, int x309,
+ int x310, int x311, int x312, int x313, int x314, int x315, int x316, int x317, int x318, int x319,
+ int x320, int x321, int x322, int x323, int x324, int x325, int x326, int x327, int x328, int x329,
+ int x330, int x331, int x332, int x333, int x334, int x335, int x336, int x337, int x338, int x339,
+ int x340, int x341, int x342, int x343, int x344, int x345, int x346, int x347, int x348, int x349,
+ int x350, int x351, int x352, int x353, int x354, int x355, int x356, int x357, int x358, int x359,
+ int x360, int x361, int x362, int x363, int x364, int x365, int x366, int x367, int x368, int x369,
+ int x370, int x371, int x372, int x373, int x374, int x375, int x376, int x377, int x378, int x379,
+ int x380, int x381, int x382, int x383, int x384, int x385, int x386, int x387, int x388, int x389,
+ int x390, int x391, int x392, int x393, int x394, int x395, int x396, int x397, int x398, int x399,
+ int x400, int x401, int x402, int x403, int x404, int x405, int x406, int x407, int x408, int x409,
+ int x410, int x411, int x412, int x413, int x414, int x415, int x416, int x417, int x418, int x419,
+ int x420, int x421, int x422, int x423, int x424, int x425, int x426, int x427, int x428, int x429,
+ int x430, int x431, int x432, int x433, int x434, int x435, int x436, int x437, int x438, int x439,
+ int x440, int x441, int x442, int x443, int x444, int x445, int x446, int x447, int x448, int x449,
+ int x450, int x451, int x452, int x453, int x454, int x455, int x456, int x457, int x458, int x459,
+ int x460, int x461, int x462, int x463, int x464, int x465, int x466, int x467, int x468, int x469,
+ int x470, int x471, int x472, int x473, int x474, int x475, int x476, int x477, int x478, int x479,
+ int x480, int x481, int x482, int x483, int x484, int x485, int x486, int x487, int x488, int x489,
+ int x490, int x491, int x492, int x493, int x494, int x495, int x496, int x497, int x498, int x499,
+ int x500, int x501, int x502, int x503, int x504, int x505, int x506, int x507, int x508, int x509,
+ int x510, int x511, int x512, int x513, int x514, int x515, int x516, int x517, int x518, int x519,
+ int x520, int x521, int x522, int x523, int x524, int x525, int x526, int x527, int x528, int x529,
+ int x530, int x531, int x532, int x533, int x534, int x535, int x536, int x537, int x538, int x539,
+ int x540, int x541, int x542, int x543, int x544, int x545, int x546, int x547, int x548, int x549,
+ int x550, int x551, int x552, int x553, int x554, int x555, int x556, int x557, int x558, int x559,
+ int x560, int x561, int x562, int x563, int x564, int x565, int x566, int x567, int x568, int x569,
+ int x570, int x571, int x572, int x573, int x574, int x575, int x576, int x577, int x578, int x579,
+ int x580, int x581, int x582, int x583, int x584, int x585, int x586, int x587, int x588, int x589,
+ int x590, int x591, int x592, int x593, int x594, int x595, int x596, int x597, int x598, int x599,
+ int x600, int x601, int x602, int x603, int x604, int x605, int x606, int x607, int x608, int x609,
+ int x610, int x611, int x612, int x613, int x614, int x615, int x616, int x617, int x618, int x619,
+ int x620, int x621, int x622, int x623, int x624, int x625, int x626, int x627, int x628, int x629,
+ int x630, int x631, int x632, int x633, int x634, int x635, int x636, int x637, int x638, int x639,
+ int x640, int x641, int x642, int x643, int x644, int x645, int x646, int x647, int x648, int x649,
+ int x650, int x651, int x652, int x653, int x654, int x655, int x656, int x657, int x658, int x659,
+ int x660, int x661, int x662, int x663, int x664, int x665, int x666, int x667, int x668, int x669,
+ int x670, int x671, int x672, int x673, int x674, int x675, int x676, int x677, int x678, int x679,
+ int x680, int x681, int x682, int x683, int x684, int x685, int x686, int x687, int x688, int x689,
+ int x690, int x691, int x692, int x693, int x694, int x695, int x696, int x697, int x698, int x699,
+ int x700, int x701, int x702, int x703, int x704, int x705, int x706, int x707, int x708, int x709,
+ int x710, int x711, int x712, int x713, int x714, int x715, int x716, int x717, int x718, int x719,
+ int x720, int x721, int x722, int x723, int x724, int x725, int x726, int x727, int x728, int x729,
+ int x730, int x731, int x732, int x733, int x734, int x735, int x736, int x737, int x738, int x739,
+ int x740, int x741, int x742, int x743, int x744, int x745, int x746, int x747, int x748, int x749,
+ int x750, int x751, int x752, int x753, int x754, int x755, int x756, int x757, int x758, int x759,
+ int x760, int x761, int x762, int x763, int x764, int x765, int x766, int x767, int x768, int x769,
+ int x770, int x771, int x772, int x773, int x774, int x775, int x776, int x777, int x778, int x779,
+ int x780, int x781, int x782, int x783, int x784, int x785, int x786, int x787, int x788, int x789,
+ int x790, int x791, int x792, int x793, int x794, int x795, int x796, int x797, int x798, int x799,
+ int x800, int x801, int x802, int x803, int x804, int x805, int x806, int x807, int x808, int x809,
+ int x810, int x811, int x812, int x813, int x814, int x815, int x816, int x817, int x818, int x819,
+ int x820, int x821, int x822, int x823, int x824, int x825, int x826, int x827, int x828, int x829,
+ int x830, int x831, int x832, int x833, int x834, int x835, int x836, int x837, int x838, int x839,
+ int x840, int x841, int x842, int x843, int x844, int x845, int x846, int x847, int x848, int x849)
+ {
+ s_x = x000 + x099 + x749 + x849;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int q() => s_x + 1;
+
+ public static void Test()
+ {
+ int z = s_x;
+ Consume(
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ q(), q(), q(), q(), q(), q(), q(), q(), q(), q(),
+ z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1);
+ }
+
+ static int s_x;
+
+ public static int Main()
+ {
+ s_x = 1;
+ int expected = 8;
+ Thread t = new Thread(Test, 512 * 1024);
+ t.Start();
+ t.Join();
+
+ if (s_x == expected)
+ {
+ Console.WriteLine("PASSED");
+ return 100;
+ }
+ else
+ {
+ Console.WriteLine($"FAILED, got {s_x}, expected {expected}");
+ return -1;
+ }
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj
new file mode 100644
index 0000000000..5243a9a46c
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_18582/GitHub_18582.csproj
@@ -0,0 +1,39 @@
+<?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>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <CLRTestPriority>1</CLRTestPriority>
+ </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>
+ <PropertyGroup>
+ <DebugType></DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="GitHub_18582.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project> \ No newline at end of file