summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/codegen.h4
-rw-r--r--src/jit/codegenarm.cpp28
-rw-r--r--src/jit/codegenarm64.cpp28
-rw-r--r--src/jit/codegencommon.cpp68
-rw-r--r--src/jit/codegenlinear.cpp20
-rw-r--r--src/jit/codegenxarch.cpp63
-rw-r--r--src/jit/compiler.cpp10
-rw-r--r--src/jit/compiler.h32
-rw-r--r--src/jit/morph.cpp14
-rw-r--r--tests/src/Interop/SizeConst/SizeConstTest.cs2
-rw-r--r--tests/src/JIT/Directed/pinvoke/pinvoke-bug.cs2
-rw-r--r--tests/src/JIT/Directed/pinvoke/sin.cs4
12 files changed, 170 insertions, 105 deletions
diff --git a/src/jit/codegen.h b/src/jit/codegen.h
index 8910ee63f1..06670aaac6 100644
--- a/src/jit/codegen.h
+++ b/src/jit/codegen.h
@@ -1186,6 +1186,10 @@ protected:
#endif // !_TARGET_X86_
#endif // !FEATURE_PUT_STRUCT_ARG_STK
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
+ void genStackPointerCheck(bool doStackPointerCheck, unsigned lvaStackPointerVar);
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
+
#ifdef DEBUG
GenTree* lastConsumedNode;
void genNumberOperandUse(GenTree* const operand, int& useNum) const;
diff --git a/src/jit/codegenarm.cpp b/src/jit/codegenarm.cpp
index 1e6044fc97..21267a69c6 100644
--- a/src/jit/codegenarm.cpp
+++ b/src/jit/codegenarm.cpp
@@ -277,23 +277,6 @@ void CodeGen::genLclHeap(GenTree* tree)
BasicBlock* endLabel = 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
@@ -504,17 +487,6 @@ BAILOUT:
}
#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, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
- }
-#endif
-
genProduceReg(tree);
}
diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp
index b2a793b156..affef95a08 100644
--- a/src/jit/codegenarm64.cpp
+++ b/src/jit/codegenarm64.cpp
@@ -1845,23 +1845,6 @@ void CodeGen::genLclHeap(GenTree* tree)
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_bkpt);
- 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
@@ -2115,17 +2098,6 @@ BAILOUT:
}
#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, targetReg, compiler->lvaReturnEspCheck, 0);
- }
-#endif
-
genProduceReg(tree);
}
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index 0d4cd7da5f..79ca6c0b64 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -3691,6 +3691,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
#if !defined(UNIX_AMD64_ABI)
assert((i > 0) || (regNum == varDsc->lvArgReg));
#endif // defined(UNIX_AMD64_ABI)
+
// Is the arg dead on entry to the method ?
if ((regArgMaskLive & genRegMask(regNum)) == 0)
@@ -3916,6 +3917,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
continue;
}
#endif // defined(UNIX_AMD64_ABI)
+
// If the arg is dead on entry to the method, skip it
if (regArgTab[argNum].processed)
@@ -4543,6 +4545,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
getEmitter()->emitIns_R_R_I(INS_mov, EA_8BYTE, destRegNum, nextRegNum, 1);
}
#endif // defined(_TARGET_ARM64_) && defined(FEATURE_SIMD)
+
// Mark the rest of the argument registers corresponding to this multi-reg type as
// being processed and no longer live.
for (int regSlot = 1; regSlot < argRegCount; regSlot++)
@@ -8035,6 +8038,7 @@ void CodeGen::genFnProlog()
noway_assert(!isFramePointerUsed() || loOffs != 0);
#endif // !defined(_TARGET_AMD64_)
+
// printf(" Untracked tmp at [EBP-%04X]\n", -stkOffs);
hasUntrLcl = true;
@@ -8581,15 +8585,15 @@ void CodeGen::genFnProlog()
#endif // _TARGET_X86_
-#ifdef DEBUG
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
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, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
+ noway_assert(compiler->lvaReturnSpCheck != 0xCCCCCCCC &&
+ compiler->lvaTable[compiler->lvaReturnSpCheck].lvDoNotEnregister &&
+ compiler->lvaTable[compiler->lvaReturnSpCheck].lvOnFrame);
+ getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnSpCheck, 0);
}
-#endif
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
getEmitter()->emitEndProlog();
compiler->unwindEndProlog();
@@ -11927,4 +11931,56 @@ void CodeGen::genReturn(GenTree* treeNode)
}
}
#endif // PROFILING_SUPPORTED
+
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
+ bool doStackPointerCheck = compiler->opts.compStackCheckOnRet;
+
+#if FEATURE_EH_FUNCLETS
+ // Don't do stack pointer check at the return from a funclet; only for the main function.
+ if (compiler->funCurrentFunc()->funKind != FUNC_ROOT)
+ {
+ doStackPointerCheck = false;
+ }
+#else // !FEATURE_EH_FUNCLETS
+ // Don't generate stack checks for x86 finally/filter EH returns: these are not invoked
+ // with the same SP as the main function. See also CodeGen::genEHFinallyOrFilterRet().
+ if ((compiler->compCurBB->bbJumpKind == BBJ_EHFINALLYRET) || (compiler->compCurBB->bbJumpKind == BBJ_EHFILTERRET))
+ {
+ doStackPointerCheck = false;
+ }
+#endif // !FEATURE_EH_FUNCLETS
+
+ genStackPointerCheck(doStackPointerCheck, compiler->lvaReturnSpCheck);
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
}
+
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
+
+//------------------------------------------------------------------------
+// genStackPointerCheck: Generate code to check the stack pointer against a saved value.
+// This is a debug check.
+//
+// Arguments:
+// doStackPointerCheck - If true, do the stack pointer check, otherwise do nothing.
+// lvaStackPointerVar - The local variable number that holds the value of the stack pointer
+// we are comparing against.
+//
+// Return Value:
+// None
+//
+void CodeGen::genStackPointerCheck(bool doStackPointerCheck, unsigned lvaStackPointerVar)
+{
+ if (doStackPointerCheck)
+ {
+ noway_assert(lvaStackPointerVar != 0xCCCCCCCC && compiler->lvaTable[lvaStackPointerVar].lvDoNotEnregister &&
+ compiler->lvaTable[lvaStackPointerVar].lvOnFrame);
+ getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, REG_SPBASE, lvaStackPointerVar, 0);
+
+ BasicBlock* sp_check = genCreateTempLabel();
+ getEmitter()->emitIns_J(INS_je, sp_check);
+ instGen(INS_BREAKPOINT);
+ genDefineTempLabel(sp_check);
+ }
+}
+
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
diff --git a/src/jit/codegenlinear.cpp b/src/jit/codegenlinear.cpp
index 9647600ec8..f474b88ab1 100644
--- a/src/jit/codegenlinear.cpp
+++ b/src/jit/codegenlinear.cpp
@@ -41,19 +41,31 @@ void CodeGen::genCodeForBBlist()
// You have to be careful if you create basic blocks from now on
compiler->fgSafeBasicBlockCreation = false;
+#endif // DEBUG
+
+#if defined(DEBUG) && defined(_TARGET_X86_)
- // This stress mode is not compatible with fully interruptible GC
+ // Check stack pointer on call stress mode is not compatible with fully interruptible GC. REVIEW: why?
+ //
if (genInterruptible && compiler->opts.compStackCheckOnCall)
{
compiler->opts.compStackCheckOnCall = false;
}
- // This stress mode is not compatible with fully interruptible GC
- if (genInterruptible && compiler->opts.compStackCheckOnRet)
+#endif // defined(DEBUG) && defined(_TARGET_X86_)
+
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
+
+ // Check stack pointer on return stress mode is not compatible with fully interruptible GC. REVIEW: why?
+ // It is also not compatible with any function that makes a tailcall: we aren't smart enough to only
+ // insert the SP check in the non-tailcall returns.
+ //
+ if ((genInterruptible || compiler->compTailCallUsed) && compiler->opts.compStackCheckOnRet)
{
compiler->opts.compStackCheckOnRet = false;
}
-#endif // DEBUG
+
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
// Prepare the blocks for exception handling codegen: mark the blocks that needs labels.
genPrepForEHCodegen();
diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp
index 92c858e56c..e81f5bab03 100644
--- a/src/jit/codegenxarch.cpp
+++ b/src/jit/codegenxarch.cpp
@@ -2197,20 +2197,7 @@ void CodeGen::genLclHeap(GenTree* tree)
BasicBlock* endLabel = nullptr;
#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);
- }
+ genStackPointerCheck(compiler->opts.compStackCheckOnRet, compiler->lvaReturnSpCheck);
#endif
noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes
@@ -2518,13 +2505,13 @@ BAILOUT:
#endif
#ifdef DEBUG
- // Update new ESP
+ // Update local variable to reflect the new stack pointer.
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, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
+ noway_assert(compiler->lvaReturnSpCheck != 0xCCCCCCCC &&
+ compiler->lvaTable[compiler->lvaReturnSpCheck].lvDoNotEnregister &&
+ compiler->lvaTable[compiler->lvaReturnSpCheck].lvOnFrame);
+ getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnSpCheck, 0);
}
#endif
@@ -5212,6 +5199,17 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
}
}
+#if defined(DEBUG) && defined(_TARGET_X86_)
+ // Store the stack pointer so we can check it after the call.
+ if (compiler->opts.compStackCheckOnCall && call->gtCallType == CT_USER_FUNC)
+ {
+ noway_assert(compiler->lvaCallSpCheck != 0xCCCCCCCC &&
+ compiler->lvaTable[compiler->lvaCallSpCheck].lvDoNotEnregister &&
+ compiler->lvaTable[compiler->lvaCallSpCheck].lvOnFrame);
+ getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaCallSpCheck, 0);
+ }
+#endif // defined(DEBUG) && defined(_TARGET_X86_)
+
bool fPossibleSyncHelperCall = false;
CorInfoHelpFunc helperNum = CORINFO_HELP_UNDEF;
@@ -5526,6 +5524,33 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
gcInfo.gcMarkRegSetNpt(RBM_INTRET);
}
+#if defined(DEBUG) && defined(_TARGET_X86_)
+ if (compiler->opts.compStackCheckOnCall && call->gtCallType == CT_USER_FUNC)
+ {
+ noway_assert(compiler->lvaCallSpCheck != 0xCCCCCCCC &&
+ compiler->lvaTable[compiler->lvaCallSpCheck].lvDoNotEnregister &&
+ compiler->lvaTable[compiler->lvaCallSpCheck].lvOnFrame);
+ if (!fCallerPop && (stackArgBytes != 0))
+ {
+ // ECX is trashed, so can be used to compute the expected SP. We saved the value of SP
+ // after pushing all the stack arguments, but the caller popped the arguments, so we need
+ // to do some math to figure a good comparison.
+ getEmitter()->emitIns_R_R(INS_mov, EA_4BYTE, REG_ARG_0, REG_SPBASE);
+ getEmitter()->emitIns_R_I(INS_sub, EA_4BYTE, REG_ARG_0, stackArgBytes);
+ getEmitter()->emitIns_S_R(INS_cmp, EA_4BYTE, REG_ARG_0, compiler->lvaCallSpCheck, 0);
+ }
+ else
+ {
+ getEmitter()->emitIns_S_R(INS_cmp, EA_4BYTE, REG_SPBASE, compiler->lvaCallSpCheck, 0);
+ }
+
+ BasicBlock* sp_check = genCreateTempLabel();
+ getEmitter()->emitIns_J(INS_je, sp_check);
+ instGen(INS_BREAKPOINT);
+ genDefineTempLabel(sp_check);
+ }
+#endif // defined(DEBUG) && defined(_TARGET_X86_)
+
#if !FEATURE_EH_FUNCLETS
//-------------------------------------------------------------------------
// Create a label for tracking of region protected by the monitor in synchronized methods.
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 6d7079d271..67465f7ad0 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -3486,12 +3486,14 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
#ifdef DEBUG
assert(!codeGen->isGCTypeFixed());
opts.compGcChecks = (JitConfig.JitGCChecks() != 0) || compStressCompile(STRESS_GENERIC_VARN, 5);
+#endif
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
enum
{
STACK_CHECK_ON_RETURN = 0x1,
STACK_CHECK_ON_CALL = 0x2,
- STACK_CHECK_ALL = 0x3,
+ STACK_CHECK_ALL = 0x3
};
DWORD dwJitStackChecks = JitConfig.JitStackChecks();
@@ -3499,9 +3501,11 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
{
dwJitStackChecks = STACK_CHECK_ALL;
}
- opts.compStackCheckOnRet = (dwJitStackChecks & DWORD(STACK_CHECK_ON_RETURN)) != 0;
+ opts.compStackCheckOnRet = (dwJitStackChecks & DWORD(STACK_CHECK_ON_RETURN)) != 0;
+#if defined(_TARGET_X86_)
opts.compStackCheckOnCall = (dwJitStackChecks & DWORD(STACK_CHECK_ON_CALL)) != 0;
-#endif
+#endif // defined(_TARGET_X86_)
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
#if MEASURE_MEM_ALLOC
s_dspMemStats = (JitConfig.DisplayMemStats() != 0);
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 8f8083a9fe..3d57380e96 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -2856,10 +2856,17 @@ public:
unsigned lvaPromotedStructAssemblyScratchVar;
#endif // _TARGET_ARM_
-#ifdef DEBUG
- unsigned lvaReturnEspCheck; // confirms ESP not corrupted on return
- unsigned lvaCallEspCheck; // confirms ESP not corrupted after a call
-#endif
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
+
+ unsigned lvaReturnSpCheck; // Stores SP to confirm it is not corrupted on return.
+
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
+
+#if defined(DEBUG) && defined(_TARGET_X86_)
+
+ unsigned lvaCallSpCheck; // Stores SP to confirm it is not corrupted after every call.
+
+#endif // defined(DEBUG) && defined(_TARGET_X86_)
unsigned lvaGenericsContextUseCount;
@@ -8264,12 +8271,21 @@ public:
#endif
#ifdef DEBUG
- bool compGcChecks; // Check arguments and return values to ensure they are sane
- bool compStackCheckOnRet; // Check ESP on return to ensure it is correct
- bool compStackCheckOnCall; // Check ESP after every call to ensure it is correct
-
+ bool compGcChecks; // Check arguments and return values to ensure they are sane
#endif
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
+
+ bool compStackCheckOnRet; // Check stack pointer on return to ensure it is correct.
+
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
+
+#if defined(DEBUG) && defined(_TARGET_X86_)
+
+ bool compStackCheckOnCall; // Check stack pointer after call to ensure it is correct. Only for x86.
+
+#endif // defined(DEBUG) && defined(_TARGET_X86_)
+
bool compNeedSecurityCheck; // This flag really means where or not a security object needs
// to be allocated on the stack.
// It will be set to true in the following cases:
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 6bd251a3ce..0e345a0847 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -16694,19 +16694,23 @@ void Compiler::fgMorph()
}
}
}
+#endif // DEBUG
+#if defined(DEBUG) && defined(_TARGET_XARCH_)
if (opts.compStackCheckOnRet)
{
- lvaReturnEspCheck = lvaGrabTempWithImplicitUse(false DEBUGARG("ReturnEspCheck"));
- lvaTable[lvaReturnEspCheck].lvType = TYP_INT;
+ lvaReturnSpCheck = lvaGrabTempWithImplicitUse(false DEBUGARG("ReturnSpCheck"));
+ lvaTable[lvaReturnSpCheck].lvType = TYP_I_IMPL;
}
+#endif // defined(DEBUG) && defined(_TARGET_XARCH_)
+#if defined(DEBUG) && defined(_TARGET_X86_)
if (opts.compStackCheckOnCall)
{
- lvaCallEspCheck = lvaGrabTempWithImplicitUse(false DEBUGARG("CallEspCheck"));
- lvaTable[lvaCallEspCheck].lvType = TYP_INT;
+ lvaCallSpCheck = lvaGrabTempWithImplicitUse(false DEBUGARG("CallSpCheck"));
+ lvaTable[lvaCallSpCheck].lvType = TYP_I_IMPL;
}
-#endif // DEBUG
+#endif // defined(DEBUG) && defined(_TARGET_X86_)
/* Filter out unimported BBs */
diff --git a/tests/src/Interop/SizeConst/SizeConstTest.cs b/tests/src/Interop/SizeConst/SizeConstTest.cs
index bd081a6721..a4d85c898e 100644
--- a/tests/src/Interop/SizeConst/SizeConstTest.cs
+++ b/tests/src/Interop/SizeConst/SizeConstTest.cs
@@ -19,7 +19,7 @@ class Test
internal const int ARRAY_SIZE = 100;
//UnmanagedType.ByValTStr
- [DllImport("SizeConstNative",CharSet = CharSet.Ansi)]
+ [DllImport("SizeConstNative",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern bool TakeByValTStr(S_CHARArray_ByValTStr s, int size);
static bool SizeConstByValTStr()
diff --git a/tests/src/JIT/Directed/pinvoke/pinvoke-bug.cs b/tests/src/JIT/Directed/pinvoke/pinvoke-bug.cs
index 2d4b5f6aea..35f75ab3bc 100644
--- a/tests/src/JIT/Directed/pinvoke/pinvoke-bug.cs
+++ b/tests/src/JIT/Directed/pinvoke/pinvoke-bug.cs
@@ -12,7 +12,7 @@ namespace PInvokeTest
{
internal class Test
{
- [DllImport("msvcrt", EntryPoint = "sin")]
+ [DllImport("msvcrt", EntryPoint = "sin", CallingConvention = CallingConvention.Cdecl)]
private static extern double sin(double x);
private static double g;
diff --git a/tests/src/JIT/Directed/pinvoke/sin.cs b/tests/src/JIT/Directed/pinvoke/sin.cs
index 3173cb823b..2ad75e4105 100644
--- a/tests/src/JIT/Directed/pinvoke/sin.cs
+++ b/tests/src/JIT/Directed/pinvoke/sin.cs
@@ -10,10 +10,10 @@ namespace JitTest
internal class Test
{
- [DllImport("msvcrt", EntryPoint = "sin")]
+ [DllImport("msvcrt", EntryPoint = "sin", CallingConvention = CallingConvention.Cdecl)]
private static extern double sin(double x);
- [DllImport("msvcrt", EntryPoint = "acos")]
+ [DllImport("msvcrt", EntryPoint = "acos", CallingConvention = CallingConvention.Cdecl)]
private static extern double acos(double x);
private static int Main()