summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/typeutils.cpp
blob: 9b3ad4c88a0683c2bc2fe79921cbb4b39e6c4d1f (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

//----------------------------------------------------------
// TypeUtils.cpp - Utility code for working with managed types
//----------------------------------------------------------

#include "standardpch.h"
#include "typeutils.h"
#include "errorhandling.h"

// Returns a string representation of the given CorInfoType. The naming scheme is based on JITtype2varType
// in src/jit/ee_il_dll.hpp.
const char* TypeUtils::GetCorInfoTypeName(CorInfoType type)
{
    switch (type)
    {
        case CORINFO_TYPE_VOID:
            return "void";

        case CORINFO_TYPE_BOOL:
            return "bool";

        case CORINFO_TYPE_CHAR:
            return "char";

        case CORINFO_TYPE_BYTE:
            return "byte";

        case CORINFO_TYPE_UBYTE:
            return "ubyte";

        case CORINFO_TYPE_SHORT:
            return "short";

        case CORINFO_TYPE_USHORT:
            return "ushort";

        case CORINFO_TYPE_INT:
            return "int";

        case CORINFO_TYPE_UINT:
            return "uint";

        case CORINFO_TYPE_LONG:
            return "long";

        case CORINFO_TYPE_ULONG:
            return "ulong";

        case CORINFO_TYPE_FLOAT:
            return "float";

        case CORINFO_TYPE_DOUBLE:
            return "double";

        case CORINFO_TYPE_BYREF:
            return "byref";

        case CORINFO_TYPE_VALUECLASS:
        case CORINFO_TYPE_REFANY:
            return "struct";

        case CORINFO_TYPE_STRING:
        case CORINFO_TYPE_CLASS:
        case CORINFO_TYPE_VAR:
            return "ref";

        case CORINFO_TYPE_NATIVEINT:
        case CORINFO_TYPE_NATIVEUINT:
// Emulates the JIT's concept of TYP_I_IMPL
#if defined(_TARGET_AMD64_) // TODO: should be _TARGET_64BIT_
            return "long";
#else
            return "int";
#endif

        case CORINFO_TYPE_PTR:
            // The JIT just treats this as a TYP_I_IMPL because this isn't a GC root,
            // but we don't care about GC-ness: we care about pointer-sized.
            return "ptr";

        default:
            LogException(EXCEPTIONCODE_TYPEUTILS, "Unknown type passed into GetCorInfoTypeName (0x%x)", type);
            return "UNKNOWN";
    }
}

bool TypeUtils::IsFloatingPoint(CorInfoType type)
{
    return (type == CORINFO_TYPE_FLOAT || type == CORINFO_TYPE_DOUBLE);
}

bool TypeUtils::IsPointer(CorInfoType type)
{
    return (type == CORINFO_TYPE_STRING || type == CORINFO_TYPE_PTR || type == CORINFO_TYPE_BYREF ||
            type == CORINFO_TYPE_CLASS);
}

bool TypeUtils::IsValueClass(CorInfoType type)
{
    return (type == CORINFO_TYPE_VALUECLASS || type == CORINFO_TYPE_REFANY);
}

// Determines if a value class, represented by the given class handle, is required to be passed
// by reference (i.e. it cannot be stuffed as-is into a register or stack slot).
bool TypeUtils::ValueClassRequiresByref(MethodContext* mc, CORINFO_CLASS_HANDLE clsHnd)
{
#if defined(_TARGET_AMD64_)
    size_t size = mc->repGetClassSize(clsHnd);
    return ((size > sizeof(void*)) || ((size & (size - 1)) != 0));
#else
    LogException(EXCEPTIONCODE_TYPEUTILS, "unsupported architecture", "");
    return false;
#endif
}

// Returns the size of the given CorInfoType. If there is no applicable size (e.g. CORINFO_TYPE_VOID,
// CORINFO_TYPE_UNDEF), this throws an exception and returns -1. Taken largely from the MSDN documentation
// for managed sizeof.
size_t TypeUtils::SizeOfCorInfoType(CorInfoType type)
{
    switch (type)
    {
        case CORINFO_TYPE_BYTE:
        case CORINFO_TYPE_UBYTE:
        case CORINFO_TYPE_BOOL:
            return sizeof(BYTE);

        case CORINFO_TYPE_CHAR: // 2 bytes for Unicode
        case CORINFO_TYPE_SHORT:
        case CORINFO_TYPE_USHORT:
            return sizeof(WORD);

        case CORINFO_TYPE_INT:
        case CORINFO_TYPE_UINT:
        case CORINFO_TYPE_FLOAT:
            return sizeof(DWORD);

        case CORINFO_TYPE_LONG:
        case CORINFO_TYPE_ULONG:
        case CORINFO_TYPE_DOUBLE:
            return sizeof(DWORDLONG);

        case CORINFO_TYPE_NATIVEINT:
        case CORINFO_TYPE_NATIVEUINT:
        case CORINFO_TYPE_STRING:
        case CORINFO_TYPE_PTR:
        case CORINFO_TYPE_BYREF:
        case CORINFO_TYPE_CLASS:
            return sizeof(void*);

        // This should be obtained via repGetClassSize
        case CORINFO_TYPE_VALUECLASS:
        case CORINFO_TYPE_REFANY:
            LogException(EXCEPTIONCODE_TYPEUTILS,
                         "SizeOfCorInfoType does not support value types; use repGetClassSize instead (type: 0x%x)",
                         type);
            return 0;

        case CORINFO_TYPE_UNDEF:
        case CORINFO_TYPE_VOID:
        default:
            LogException(EXCEPTIONCODE_TYPEUTILS, "Unsupported type (0x%x) passed into SizeOfCorInfoType", type);
            return 0;
    }
}