-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
targetx86.cpp
123 lines (111 loc) · 3.83 KB
/
targetx86.cpp
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
123
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/*****************************************************************************/
#include "jitpch.h"
#ifdef _MSC_VER
#pragma hdrstop
#endif
#if defined(TARGET_X86)
#include "target.h"
const char* Target::g_tgtCPUName = "x86";
const Target::ArgOrder Target::g_tgtArgOrder = ARG_ORDER_L2R;
const Target::ArgOrder Target::g_tgtUnmanagedArgOrder = ARG_ORDER_R2L;
// clang-format off
const regNumber intArgRegs [] = {REG_ECX, REG_EDX};
const regMaskTP intArgMasks[] = {RBM_ECX, RBM_EDX};
// clang-format on
//-----------------------------------------------------------------------------
// X86Classifier:
// Construct a new instance of the x86 ABI classifier.
//
// Parameters:
// info - Info about the method being classified.
//
X86Classifier::X86Classifier(const ClassifierInfo& info)
: m_regs(nullptr, 0)
{
switch (info.CallConv)
{
case CorInfoCallConvExtension::Thiscall:
{
static const regNumber thiscallRegs[] = {REG_ECX};
m_regs = RegisterQueue(thiscallRegs, ArrLen(thiscallRegs));
break;
}
case CorInfoCallConvExtension::C:
case CorInfoCallConvExtension::Stdcall:
case CorInfoCallConvExtension::CMemberFunction:
case CorInfoCallConvExtension::StdcallMemberFunction:
{
break;
}
default:
{
unsigned numRegs = ArrLen(intArgRegs);
if (info.IsVarArgs)
{
// In varargs methods we only enregister the this pointer or retbuff.
numRegs = info.HasThis || info.HasRetBuff ? 1 : 0;
}
m_regs = RegisterQueue(intArgRegs, numRegs);
break;
}
}
}
//-----------------------------------------------------------------------------
// Classify:
// Classify a parameter for the x86 ABI.
//
// Parameters:
// comp - Compiler instance
// type - The type of the parameter
// structLayout - The layout of the struct. Expected to be non-null if
// varTypeIsStruct(type) is true.
// wellKnownParam - Well known type of the parameter (if it may affect its ABI classification)
//
// Returns:
// Classification information for the parameter.
//
ABIPassingInformation X86Classifier::Classify(Compiler* comp,
var_types type,
ClassLayout* structLayout,
WellKnownArg wellKnownParam)
{
unsigned size = type == TYP_STRUCT ? structLayout->GetSize() : genTypeSize(type);
unsigned numSlots = (size + TARGET_POINTER_SIZE - 1) / TARGET_POINTER_SIZE;
bool canEnreg = false;
if (m_regs.Count() >= numSlots)
{
switch (type)
{
case TYP_BYTE:
case TYP_UBYTE:
case TYP_SHORT:
case TYP_USHORT:
case TYP_INT:
case TYP_REF:
case TYP_BYREF:
canEnreg = true;
break;
case TYP_STRUCT:
canEnreg = comp->isTrivialPointerSizedStruct(structLayout->GetClassHandle());
break;
default:
break;
}
}
ABIPassingSegment segment;
if (canEnreg)
{
assert(numSlots == 1);
segment = ABIPassingSegment::InRegister(m_regs.Dequeue(), 0, size);
}
else
{
assert((m_stackArgSize % TARGET_POINTER_SIZE) == 0);
m_stackArgSize += roundUp(size, TARGET_POINTER_SIZE);
segment = ABIPassingSegment::OnStack(m_stackArgSize, 0, size);
}
return ABIPassingInformation::FromSegment(comp, segment);
}
#endif // TARGET_X86