blob: d58a2e8b615128a1a22e63d177d3fbd8c97beaba (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
// 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.
//
// File: CLRVarArgs.cpp
//
//
// Variant-specific marshalling.
#include "common.h"
#include "clrvarargs.h"
DWORD VARARGS::CalcVaListSize(VARARGS *data)
{
LIMITED_METHOD_CONTRACT;
// Calculate how much space we need for the marshaled stack.
// This assumes that the vararg managed and unmanaged calling conventions are similar-enough,
// so we can simply use the size stored in the VASigCookie. This actually overestimates
// the value since it counts the fixed args as well as the varargs. But that's harmless.
DWORD dwVaListSize = data->ArgCookie->sizeOfArgs;
#ifndef _TARGET_X86_
dwVaListSize += ARGUMENTREGISTERS_SIZE;
#endif
return dwVaListSize;
}
void VARARGS::MarshalToManagedVaList(va_list va, VARARGS *dataout)
{
WRAPPER_NO_CONTRACT
#ifndef PLATFORM_UNIX
_ASSERTE(dataout != NULL);
dataout->SigPtr = SigPointer(NULL, 0);
dataout->ArgCookie = NULL;
dataout->ArgPtr = (BYTE*)va;
#else
PORTABILITY_ASSERT("Implement for Unix");
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Marshal a ArgIterator to a pre-allocated va_list
////////////////////////////////////////////////////////////////////////////////
void
VARARGS::MarshalToUnmanagedVaList(
va_list va, DWORD cbVaListSize, const VARARGS * data)
{
#ifndef PLATFORM_UNIX
BYTE * pdstbuffer = (BYTE *)va;
int remainingArgs = data->RemainingArgs;
BYTE * psrc = (BYTE *)(data->ArgPtr);
BYTE * pdst = pdstbuffer;
SigPointer sp = data->SigPtr;
SigTypeContext typeContext; // This is an empty type context. This is OK because the vararg methods may not be generic
while (remainingArgs--)
{
CorElementType elemType = sp.PeekElemTypeClosed(data->ArgCookie->pModule, &typeContext);
switch (elemType)
{
case ELEMENT_TYPE_I1:
case ELEMENT_TYPE_U1:
case ELEMENT_TYPE_I2:
case ELEMENT_TYPE_U2:
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_U4:
case ELEMENT_TYPE_I8:
case ELEMENT_TYPE_U8:
case ELEMENT_TYPE_R4:
case ELEMENT_TYPE_R8:
case ELEMENT_TYPE_I:
case ELEMENT_TYPE_U:
case ELEMENT_TYPE_PTR:
{
DWORD cbSize = StackElemSize(CorTypeInfo::Size(elemType));
#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
if (cbSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
cbSize = sizeof(void*);
#endif
#ifdef _TARGET_ARM_
if (cbSize == 8)
{
// 64-bit primitives come from and must be copied to 64-bit aligned locations.
psrc = (BYTE*)ALIGN_UP(psrc, 8);
pdst = (BYTE*)ALIGN_UP(pdst, 8);
}
#endif // _TARGET_ARM_
#ifdef STACK_GROWS_DOWN_ON_ARGS_WALK
psrc -= cbSize;
#endif // STACK_GROWS_DOWN_ON_ARGS_WALK
if (pdst + cbSize > pdstbuffer + cbVaListSize)
COMPlusThrow(kArgumentException);
CopyMemory(pdst, psrc, cbSize);
#ifdef STACK_GROWS_UP_ON_ARGS_WALK
psrc += cbSize;
#endif // STACK_GROWS_UP_ON_ARGS_WALK
pdst += cbSize;
IfFailThrow(sp.SkipExactlyOne());
}
break;
default:
// non-IJW data type - we don't support marshaling these inside a va_list.
COMPlusThrow(kNotSupportedException);
}
}
#else
PORTABILITY_ASSERT("Implement for Unix");
#endif
} // VARARGS::MarshalToUnmanagedVaList
|