void CodeGen::genLclHeap(GenTree* tree)
{
assert(tree->OperGet() == GT_LCLHEAP);
+ assert(compiler->compLocallocUsed);
GenTree* size = tree->gtOp.gtOp1;
noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
// Also it used as temporary register in code generation
// for storing allocation size
regNumber regCnt = tree->gtRegNum;
- 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
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())
}
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
- pspSymReg = tree->ExtractTempReg();
- 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)
inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE);
stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
}
-#endif
// Put aligned allocation size to regCnt
if (size->IsCnsIntOrI())
}
else if (!compiler->info.compInitMem && (amount < compiler->eeGetPageSize())) // must be < not <=
{
- // Since the size is a page or less, simply adjust the SP value
+ // Since the size is less than a page, 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);
// 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
+ // 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 the stack pointer is always valid
// by tickling the pages, we will just push 0's on the stack.
regNumber regTmp = tree->ExtractTempReg();
}
ALLOC_DONE:
- // Re-adjust SP to allocate PSPSym and out-going arg area
+ // Re-adjust SP to allocate 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);
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);
+ getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
}
#endif
void CodeGen::genLclHeap(GenTree* tree)
{
assert(tree->OperGet() == GT_LCLHEAP);
+ assert(compiler->compLocallocUsed);
GenTree* size = tree->gtOp.gtOp1;
noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
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
-
// compute the amount of memory to allocate to properly STACK_ALIGN.
size_t amount = 0;
if (size->IsCnsIntOrI())
inst_JMP(jmpEqual, endLabel);
// Compute the size of the block to allocate and perform alignment.
- // If the method has no PSPSym and compInitMem=true, we can reuse targetReg as regcnt,
+ // If compInitMem=true, we can reuse targetReg as regcnt,
// since we don't need any internal registers.
- if (!hasPspSym && compiler->info.compInitMem)
+ if (compiler->info.compInitMem)
{
assert(tree->AvailableTempRegCount() == 0);
regCnt = targetReg;
}
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
- pspSymReg = tree->ExtractTempReg();
- 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.
//
- // Localloc is supposed to return stack space that is STACK_ALIGN'ed. The following
- // are the cases that needs to be handled:
- // i) Method has PSPSym + out-going arg area.
- // It is guaranteed that size of out-going arg area is STACK_ALIGNED (see fgMorphArgs).
- // Therefore, we will pop-off RSP upto out-going arg area before locallocating.
- // We need to add padding to ensure RSP is STACK_ALIGN'ed while re-locating PSPSym + arg area.
- // ii) Method has no PSPSym but out-going arg area.
- // Almost same case as above without the requirement to pad for the final RSP to be STACK_ALIGN'ed.
- // iii) Method has PSPSym but no out-going arg area.
- // Nothing to pop-off from the stack but needs to relocate PSPSym with SP padded.
- // iv) Method has neither PSPSym nor out-going arg area.
- // Nothing needs to popped off from stack nor relocated.
+ // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following
+ // are the cases that need to be handled:
+ // i) Method has out-going arg area.
+ // It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs).
+ // Therefore, we will pop off the out-going arg area from the stack pointer before allocating the localloc
+ // space.
+ // ii) Method has no out-going arg area.
+ // Nothing to pop off from the stack.
if (compiler->lvaOutgoingArgSpaceSize > 0)
{
assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain
inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE);
stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
}
-#endif
if (size->IsCnsIntOrI())
{
}
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
+ // Since the size is less than a page, simply adjust the SP value.
+ // The SP might already be in the guard page, so we must touch it BEFORE
// the alloc, not after.
+
// ldr wz, [SP, #0]
getEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, REG_ZR, REG_SP, 0);
}
// else, "mov regCnt, amount"
- // If the method has no PSPSym and compInitMem=true, we can reuse targetReg as regcnt.
+ // If compInitMem=true, we can reuse targetReg as regcnt.
// Since size is a constant, regCnt is not yet initialized.
assert(regCnt == REG_NA);
- if (!hasPspSym && compiler->info.compInitMem)
+ if (compiler->info.compInitMem)
{
assert(tree->AvailableTempRegCount() == 0);
regCnt = targetReg;
BasicBlock* loop = genCreateTempLabel();
// 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
+ // Since we have to zero out the allocated memory AND ensure that the stack pointer is always valid
// by tickling the pages, we will just push 0's on the stack.
//
// Note: regCnt is guaranteed to be even on Amd64 since STACK_ALIGN/TARGET_POINTER_SIZE = 2
}
else
{
- // At this point 'regCnt' is set to the total number of bytes to locAlloc.
+ // 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
}
ALLOC_DONE:
- // Re-adjust SP to allocate PSPSym and out-going arg area
+ // Re-adjust SP to allocate 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.
- // TargetReg = RSP + stackAdjustment.
+ // TargetReg = SP + stackAdjustment.
//
getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, targetReg, REG_SPBASE, (int)stackAdjustment);
}
{
GenTreeIntConCommon* intConstTree = divisorOp->AsIntConCommon();
ssize_t intConstValue = intConstTree->IconValue();
- assert(intConstValue != 0); // already checked above by IsIntegralConst(0))
+ assert(intConstValue != 0); // already checked above by IsIntegralConst(0)
if (intConstValue != -1)
{
checkDividend = false; // We statically know that the dividend is not -1
//
// Size? Init Memory? # temp regs
// 0 - 0
- // const and <=4 str instr - 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
+ // const and <=4 str instr - 0
+ // const and <PageSize No 0
+ // >4 ptr words Yes 1
+ // Non-const Yes 1
+ // Non-const No 1
GenTree* size = tree->gtGetOp1();
int internalIntCount;
{
internalIntCount = 1;
}
-
- if (hasPspSym)
- {
- internalIntCount++;
- }
}
}
else
{
- // target (regCnt) + tmp + [psp]
+ // target (regCnt) + tmp
srcCount = 1;
- internalIntCount = hasPspSym ? 2 : 1;
+ internalIntCount = 1;
BuildUse(size);
}
// 0 - 0
// const and <=6 ptr words - 0
// const and <PageSize No 0
- // >6 ptr words Yes hasPspSym ? 1 : 0
- // Non-const Yes hasPspSym ? 1 : 0
+ // >6 ptr words Yes 0
+ // Non-const Yes 0
// Non-const No 2
//
- // PSPSym - If the method has PSPSym increment internalIntCount by 1.
- //
- bool hasPspSym;
-#if FEATURE_EH_FUNCLETS
- hasPspSym = (compiler->lvaPSPSym != BAD_VAR_NUM);
-#else
- hasPspSym = false;
-#endif
GenTree* size = tree->gtGetOp1();
if (size->IsCnsIntOrI())
buildInternalIntRegisterDefForNode(tree);
}
}
- else if (hasPspSym)
- {
- // greater than 4 and need to zero initialize allocated stack space.
- // If the method has PSPSym, we need an internal register to hold regCnt
- // since targetReg allocated to GT_LCLHEAP node could be the same as one of
- // the the internal registers.
- buildInternalIntRegisterDefForNode(tree);
- }
}
}
else
buildInternalIntRegisterDefForNode(tree);
buildInternalIntRegisterDefForNode(tree);
}
- else if (hasPspSym)
- {
- // If the method has PSPSym, we need an internal register to hold regCnt
- // since targetReg allocated to GT_LCLHEAP node could be the same as one of
- // the the internal registers.
- buildInternalIntRegisterDefForNode(tree);
- }
}
- // If the method has PSPSym, we need an additional register to relocate it on stack.
- if (hasPspSym)
- {
- // Exclude const size 0
- if (!size->IsCnsIntOrI() || (size->gtIntCon.gtIconVal > 0))
- {
- buildInternalIntRegisterDefForNode(tree);
- }
- }
if (!size->isContained())
{
BuildUse(size);
--- /dev/null
+// 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.
+
+/*
+ * Test reading localloc variable from catch block.
+ */
+
+using System;
+using LocallocTesting;
+using System.Runtime.CompilerServices;
+
+internal class LocallocTest
+{
+ // Create a non-inlined call that will be made from Main with some arguments,
+ // so fixed-out-args platforms will need to move the outgoing argument space
+ // along with the localloc.
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ public static int FunctionWithLotsOfArguments(int a, int b, int c, int d, int e, int f, int g, int h, int j, int k, int l, int m)
+ {
+ return a + b + c + d + e + f + g + h + j + k + l + m;
+ }
+
+ public static unsafe int Main()
+ {
+ ulong local1 = Global.INITIAL_VALUE;
+ ulong local2 = local1 + 1;
+ int size = 0;
+#if LOCALLOC_SMALL
+ Int32* intArray1 = stackalloc Int32[1];
+ Int32* intArray2 = stackalloc Int32[1];
+ size = 1;
+#elif LOCALLOC_LARGE
+ Int32* intArray1 = stackalloc Int32[0x1000];
+ Int32* intArray2 = stackalloc Int32[0x1000];
+ size = 0x1000;
+#else
+ Int32* intArray1 = stackalloc Int32[Global.stackAllocSize];
+ Int32* intArray2 = stackalloc Int32[Global.stackAllocSize];
+ size = Global.stackAllocSize;
+#endif
+ try
+ {
+ Global.initializeStack(intArray1, size, 1000);
+ Global.initializeStack(intArray2, size, 2000);
+ throw new Exception("Test Exception");
+ }
+ catch
+ {
+ if (!Global.verifyStack("intArray1", intArray1, size, 1000))
+ {
+ return 1;
+ }
+ if (!Global.verifyStack("intArray2", intArray2, size, 2000))
+ {
+ return 1;
+ }
+ if (FunctionWithLotsOfArguments(1,2,3,4,5,1,2,3,4,5,1,2) != 33)
+ {
+ return 1;
+ }
+ }
+
+
+ if (!Global.verifyStack("intArray1", intArray1, size, 1000))
+ {
+ return 1;
+ }
+ if (!Global.verifyStack("intArray2", intArray2, size, 2000))
+ {
+ return 1;
+ }
+ if (!Global.verifyLocal("local1", local1, Global.INITIAL_VALUE))
+ {
+ return 1;
+ }
+ if (!Global.verifyLocal("local2", local2, Global.INITIAL_VALUE + 1))
+ {
+ return 1;
+ }
+
+ if (FunctionWithLotsOfArguments(0,2,3,4,5,1,2,3,4,5,1,2) != 32)
+ {
+ return 1;
+ }
+
+ Console.WriteLine("Passed\n");
+ return 100;
+ }
+}
--- /dev/null
+<?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>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <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>
+ <!-- Set to 'Full' if the Debug? column is marked in the spreadsheet. Leave blank otherwise. -->
+ <DebugType>PdbOnly</DebugType>
+ <NoLogo>True</NoLogo>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);DESKTOP;LOCALLOC_DYNAMIC</DefineConstants>
+ <NoWarn>$(NoWarn),8002</NoWarn>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="eh05.cs" />
+ <ProjectReference Include="..\common\common.ilproj" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
--- /dev/null
+<?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>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <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>
+ <!-- Set to 'Full' if the Debug? column is marked in the spreadsheet. Leave blank otherwise. -->
+ <DebugType>PdbOnly</DebugType>
+ <NoLogo>True</NoLogo>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);DESKTOP;LOCALLOC_LARGE</DefineConstants>
+ <NoWarn>$(NoWarn),8002</NoWarn>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="eh05.cs" />
+ <ProjectReference Include="..\common\common.ilproj" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
--- /dev/null
+<?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>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <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>
+ <!-- Set to 'Full' if the Debug? column is marked in the spreadsheet. Leave blank otherwise. -->
+ <DebugType>PdbOnly</DebugType>
+ <NoLogo>True</NoLogo>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);DESKTOP;LOCALLOC_SMALL</DefineConstants>
+ <NoWarn>$(NoWarn),8002</NoWarn>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="eh05.cs" />
+ <ProjectReference Include="..\common\common.ilproj" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>