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
170
171
172
173
174
175
|
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef RCC_CODEGEN_GENERICCONSTANT_H
#define RCC_CODEGEN_GENERICCONSTANT_H
#include "rcc/CodeGen/LowLevelType.h"
#include "rcc/CodeGen/MachineOperand.h"
#include "rcc/Support/Error.h"
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace rcc {
enum class GenericConstantTypeKind : std::uint8_t {
Invalid,
Void,
Label,
Token,
Metadata,
Integer,
Byte,
Floating,
Pointer,
Array,
Vector,
Struct,
Function,
Named,
};
struct GenericConstantType final {
GenericConstantTypeKind Kind = GenericConstantTypeKind::Invalid;
std::uint32_t BitWidth = 0;
FloatSemantics Semantics = FloatSemantics::IEEEHalf;
std::uint32_t AddressSpace = 0;
std::uint64_t ElementCount = 0;
bool Scalable = false;
bool Packed = false;
bool VarArg = false;
bool NumericName = false;
std::string Name;
std::vector<GenericConstantType> Elements;
[[nodiscard]] static Expected<GenericConstantType> integer(std::uint32_t BitWidth);
[[nodiscard]] static GenericConstantType primitive(GenericConstantTypeKind Kind) noexcept;
[[nodiscard]] static GenericConstantType byte() noexcept;
[[nodiscard]] static Expected<GenericConstantType> floating(FloatSemantics Semantics);
[[nodiscard]] static GenericConstantType pointer(std::uint32_t AddressSpace = 0) noexcept;
[[nodiscard]] static Expected<GenericConstantType> array(std::uint64_t ElementCount,
GenericConstantType Element);
[[nodiscard]] static Expected<GenericConstantType>
vector(std::uint64_t ElementCount, GenericConstantType Element, bool Scalable = false);
[[nodiscard]] static Expected<GenericConstantType>
structure(std::vector<GenericConstantType> Elements, bool Packed = false);
[[nodiscard]] static Expected<GenericConstantType>
function(GenericConstantType Return, std::vector<GenericConstantType> Parameters,
bool VarArg = false);
[[nodiscard]] static Expected<GenericConstantType> named(std::string Name,
bool NumericName = false);
[[nodiscard]] Expected<void> verify() const;
friend bool operator==(const GenericConstantType &Left,
const GenericConstantType &Right) = default;
};
enum class GenericConstantKind : std::uint8_t {
Invalid,
Integer,
Floating,
NullPointer,
ZeroInitializer,
Undef,
Poison,
Aggregate,
ByteString,
GlobalAddress,
BlockAddress,
DSOLocalEquivalent,
NoCFI,
PointerAuth,
Expression,
};
enum class GenericConstantExpressionOpcode : std::uint8_t {
Invalid,
Trunc,
BitCast,
AddressSpaceCast,
IntToPtr,
PtrToAddr,
PtrToInt,
Add,
Sub,
Xor,
GetElementPtr,
ShuffleVector,
InsertElement,
ExtractElement,
Splat,
};
enum class GenericConstantExpressionFlag : std::uint8_t {
NoUnsignedWrap,
NoSignedWrap,
InBounds,
NoUnsignedSignedWrap,
GEPNoUnsignedWrap,
Count,
};
class GenericConstantExpressionFlags final {
public:
constexpr GenericConstantExpressionFlags() noexcept = default;
[[nodiscard]] constexpr bool has(GenericConstantExpressionFlag Flag) const noexcept {
const auto Index = static_cast<std::uint8_t>(Flag);
if (Index >= static_cast<std::uint8_t>(GenericConstantExpressionFlag::Count))
return false;
return (Mask & (std::uint8_t{1} << Index)) != 0;
}
constexpr void set(GenericConstantExpressionFlag Flag) noexcept {
const auto Index = static_cast<std::uint8_t>(Flag);
if (Index < static_cast<std::uint8_t>(GenericConstantExpressionFlag::Count))
Mask |= std::uint8_t{1} << Index;
}
[[nodiscard]] constexpr std::uint8_t rawValue() const noexcept {
return Mask;
}
friend constexpr bool operator==(GenericConstantExpressionFlags Left,
GenericConstantExpressionFlags Right) noexcept = default;
private:
std::uint8_t Mask = 0;
};
struct GenericConstantData final {
GenericConstantType Type;
GenericConstantKind Kind = GenericConstantKind::Invalid;
std::optional<IntegerImmediate> IntegerValue;
std::optional<FloatingPointBits> FloatingValue;
std::vector<std::byte> ByteValue;
std::vector<GenericConstantData> Elements;
std::string Symbol;
std::string Block;
bool NumericSymbol = false;
bool NumericBlock = false;
GenericConstantExpressionOpcode ExpressionOpcode = GenericConstantExpressionOpcode::Invalid;
GenericConstantExpressionFlags ExpressionFlags;
std::optional<GenericConstantType> SourceElementType;
std::optional<IntegerImmediate> InRangeStart;
std::optional<IntegerImmediate> InRangeEnd;
[[nodiscard]] static Expected<GenericConstantData> integer(IntegerImmediate Value);
[[nodiscard]] static Expected<GenericConstantData> floating(FloatingPointBits Value);
[[nodiscard]] static Expected<GenericConstantData> byteString(GenericConstantType Type,
std::vector<std::byte> Bytes);
[[nodiscard]] Expected<void> verify() const;
[[nodiscard]] bool referencesSymbol() const noexcept;
friend bool operator==(const GenericConstantData &Left,
const GenericConstantData &Right) = default;
};
} // namespace rcc
#endif // RCC_CODEGEN_GENERICCONSTANT_H
|