1//===--- Opcodes.td - Opcode defitions for the constexpr VM -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Helper file used to generate opcodes, the interpreter and the disassembler.
10//
11//===----------------------------------------------------------------------===//
12
13
14//===----------------------------------------------------------------------===//
15// Types evaluated by the interpreter.
16//===----------------------------------------------------------------------===//
17
18class Type;
19def Bool : Type;
20def Sint8 : Type;
21def Uint8 : Type;
22def Sint16 : Type;
23def Uint16 : Type;
24def Sint32 : Type;
25def Uint32 : Type;
26def Sint64 : Type;
27def Uint64 : Type;
28def Ptr : Type;
29
30//===----------------------------------------------------------------------===//
31// Types transferred to the interpreter.
32//===----------------------------------------------------------------------===//
33
34class ArgType { string Name = ?; }
35def ArgSint8 : ArgType { let Name = "int8_t"; }
36def ArgUint8 : ArgType { let Name = "uint8_t"; }
37def ArgSint16 : ArgType { let Name = "int16_t"; }
38def ArgUint16 : ArgType { let Name = "uint16_t"; }
39def ArgSint32 : ArgType { let Name = "int32_t"; }
40def ArgUint32 : ArgType { let Name = "uint32_t"; }
41def ArgSint64 : ArgType { let Name = "int64_t"; }
42def ArgUint64 : ArgType { let Name = "uint64_t"; }
43def ArgBool : ArgType { let Name = "bool"; }
44
45def ArgFunction : ArgType { let Name = "Function *"; }
46def ArgRecord : ArgType { let Name = "Record *"; }
47
48def ArgSema : ArgType { let Name = "const fltSemantics *"; }
49
50def ArgExpr : ArgType { let Name = "const Expr *"; }
51def ArgFloatingLiteral : ArgType { let Name = "const FloatingLiteral *"; }
52def ArgCXXMethodDecl : ArgType { let Name = "const CXXMethodDecl *"; }
53def ArgFunctionDecl : ArgType { let Name = "const FunctionDecl *"; }
54def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; }
55def ArgCXXRecordDecl : ArgType { let Name = "const CXXRecordDecl *"; }
56def ArgValueDecl : ArgType { let Name = "const ValueDecl *"; }
57def ArgRecordField : ArgType { let Name = "const Record::Field *"; }
58
59//===----------------------------------------------------------------------===//
60// Classes of types intructions operate on.
61//===----------------------------------------------------------------------===//
62
63class TypeClass {
64  list<Type> Types;
65}
66
67def AluTypeClass : TypeClass {
68  let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
69               Uint32, Sint64, Uint64, Bool];
70}
71
72def PtrTypeClass : TypeClass {
73  let Types = [Ptr];
74}
75
76def AllTypeClass : TypeClass {
77  let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types);
78}
79
80def ComparableTypeClass : TypeClass {
81  let Types = !listconcat(AluTypeClass.Types, [Ptr]);
82}
83
84class SingletonTypeClass<Type Ty> : TypeClass {
85  let Types = [Ty];
86}
87
88//===----------------------------------------------------------------------===//
89// Record describing all opcodes.
90//===----------------------------------------------------------------------===//
91
92class Opcode {
93  list<TypeClass> Types = [];
94  list<ArgType> Args = [];
95  string Name = "";
96  bit CanReturn = 0;
97  bit ChangesPC = 0;
98  bit HasCustomLink = 0;
99  bit HasCustomEval = 0;
100  bit HasGroup = 0;
101}
102
103class AluOpcode : Opcode {
104  let Types = [AluTypeClass];
105  let HasGroup = 1;
106}
107
108//===----------------------------------------------------------------------===//
109// Jump opcodes
110//===----------------------------------------------------------------------===//
111
112class JumpOpcode : Opcode {
113  let Args = [ArgSint32];
114  let ChangesPC = 1;
115  let HasCustomEval = 1;
116}
117
118// [] -> []
119def Jmp : JumpOpcode;
120// [Bool] -> [], jumps if true.
121def Jt : JumpOpcode;
122// [Bool] -> [], jumps if false.
123def Jf : JumpOpcode;
124
125//===----------------------------------------------------------------------===//
126// Returns
127//===----------------------------------------------------------------------===//
128
129// [Value] -> []
130def Ret : Opcode {
131  let Types = [AllTypeClass];
132  let ChangesPC = 1;
133  let CanReturn = 1;
134  let HasGroup = 1;
135  let HasCustomEval = 1;
136}
137// [] -> []
138def RetVoid : Opcode {
139  let CanReturn = 1;
140  let ChangesPC = 1;
141  let HasCustomEval = 1;
142}
143// [Value] -> []
144def RetValue : Opcode {
145  let CanReturn = 1;
146  let ChangesPC = 1;
147  let HasCustomEval = 1;
148}
149// [] -> EXIT
150def NoRet : Opcode {}
151
152//===----------------------------------------------------------------------===//
153// Frame management
154//===----------------------------------------------------------------------===//
155
156// [] -> []
157def Destroy : Opcode {
158  let Args = [ArgUint32];
159  let HasCustomEval = 1;
160}
161
162//===----------------------------------------------------------------------===//
163// Constants
164//===----------------------------------------------------------------------===//
165
166class ConstOpcode<Type Ty, ArgType ArgTy> : Opcode {
167  let Types = [SingletonTypeClass<Ty>];
168  let Args = [ArgTy];
169  let Name = "Const";
170}
171
172// [] -> [Integer]
173def ConstSint8 : ConstOpcode<Sint8, ArgSint8>;
174def ConstUint8 : ConstOpcode<Uint8, ArgUint8>;
175def ConstSint16 : ConstOpcode<Sint16, ArgSint16>;
176def ConstUint16 : ConstOpcode<Uint16, ArgUint16>;
177def ConstSint32 : ConstOpcode<Sint32, ArgSint32>;
178def ConstUint32 : ConstOpcode<Uint32, ArgUint32>;
179def ConstSint64 : ConstOpcode<Sint64, ArgSint64>;
180def ConstUint64 : ConstOpcode<Uint64, ArgUint64>;
181def ConstBool : ConstOpcode<Bool, ArgBool>;
182
183// [] -> [Integer]
184def Zero : Opcode {
185  let Types = [AluTypeClass];
186}
187
188// [] -> [Pointer]
189def Null : Opcode {
190  let Types = [PtrTypeClass];
191}
192
193//===----------------------------------------------------------------------===//
194// Pointer generation
195//===----------------------------------------------------------------------===//
196
197// [] -> [Pointer]
198def GetPtrLocal : Opcode {
199  // Offset of local.
200  let Args = [ArgUint32];
201  bit HasCustomEval = 1;
202}
203// [] -> [Pointer]
204def GetPtrParam : Opcode {
205  // Offset of parameter.
206  let Args = [ArgUint32];
207}
208// [] -> [Pointer]
209def GetPtrGlobal : Opcode {
210  // Index of global.
211  let Args = [ArgUint32];
212}
213// [Pointer] -> [Pointer]
214def GetPtrField : Opcode {
215  // Offset of field.
216  let Args = [ArgUint32];
217}
218// [Pointer] -> [Pointer]
219def GetPtrActiveField : Opcode {
220  // Offset of field.
221  let Args = [ArgUint32];
222}
223// [] -> [Pointer]
224def GetPtrActiveThisField : Opcode {
225  // Offset of field.
226  let Args = [ArgUint32];
227}
228// [] -> [Pointer]
229def GetPtrThisField : Opcode {
230  // Offset of field.
231  let Args = [ArgUint32];
232}
233// [Pointer] -> [Pointer]
234def GetPtrBase : Opcode {
235  // Offset of field, which is a base.
236  let Args = [ArgUint32];
237}
238// [Pointer] -> [Pointer]
239def GetPtrVirtBase : Opcode {
240  // RecordDecl of base class.
241  let Args = [ArgRecordDecl];
242}
243// [] -> [Pointer]
244def GetPtrThisBase : Opcode {
245  // Offset of field, which is a base.
246  let Args = [ArgUint32];
247}
248// [] -> [Pointer]
249def GetPtrThisVirtBase : Opcode {
250  // RecordDecl of base class.
251  let Args = [ArgRecordDecl];
252}
253// [] -> [Pointer]
254def This : Opcode;
255
256// [Pointer] -> [Pointer]
257def NarrowPtr : Opcode;
258// [Pointer] -> [Pointer]
259def ExpandPtr : Opcode;
260
261//===----------------------------------------------------------------------===//
262// Direct field accessors
263//===----------------------------------------------------------------------===//
264
265class AccessOpcode : Opcode {
266  let Types = [AllTypeClass];
267  let Args = [ArgUint32];
268  let HasGroup = 1;
269}
270
271class BitFieldOpcode : Opcode {
272  let Types = [AluTypeClass];
273  let Args = [ArgRecordField];
274  let HasGroup = 1;
275}
276
277// [] -> [Pointer]
278def GetLocal : AccessOpcode { let HasCustomEval = 1; }
279// [] -> [Pointer]
280def SetLocal : AccessOpcode { let HasCustomEval = 1; }
281
282// [] -> [Value]
283def GetGlobal : AccessOpcode;
284// [Value] -> []
285def InitGlobal : AccessOpcode;
286// [Value] -> []
287def SetGlobal : AccessOpcode;
288
289// [] -> [Value]
290def GetParam : AccessOpcode;
291// [Value] -> []
292def SetParam : AccessOpcode;
293
294// [Pointer] -> [Pointer, Value]
295def GetField : AccessOpcode;
296// [Pointer] -> [Value]
297def GetFieldPop : AccessOpcode;
298// [] -> [Value]
299def GetThisField : AccessOpcode;
300
301// [Pointer, Value] -> [Pointer]
302def SetField : AccessOpcode;
303// [Value] -> []
304def SetThisField : AccessOpcode;
305
306// [Value] -> []
307def InitThisField : AccessOpcode;
308// [Value] -> []
309def InitThisFieldActive : AccessOpcode;
310// [Value] -> []
311def InitThisBitField : BitFieldOpcode;
312// [Pointer, Value] -> []
313def InitField : AccessOpcode;
314// [Pointer, Value] -> []
315def InitBitField : BitFieldOpcode;
316// [Pointer, Value] -> []
317def InitFieldActive : AccessOpcode;
318
319//===----------------------------------------------------------------------===//
320// Pointer access
321//===----------------------------------------------------------------------===//
322
323class LoadOpcode : Opcode {
324  let Types = [AllTypeClass];
325  let HasGroup = 1;
326}
327
328// [Pointer] -> [Pointer, Value]
329def Load : LoadOpcode {}
330// [Pointer] -> [Value]
331def LoadPop : LoadOpcode {}
332
333class StoreOpcode : Opcode {
334  let Types = [AllTypeClass];
335  let HasGroup = 1;
336}
337
338class StoreBitFieldOpcode : Opcode {
339  let Types = [AluTypeClass];
340  let HasGroup = 1;
341}
342
343// [Pointer, Value] -> [Pointer]
344def Store : StoreOpcode {}
345// [Pointer, Value] -> []
346def StorePop : StoreOpcode {}
347
348// [Pointer, Value] -> [Pointer]
349def StoreBitField : StoreBitFieldOpcode {}
350// [Pointer, Value] -> []
351def StoreBitFieldPop : StoreBitFieldOpcode {}
352
353// [Pointer, Value] -> []
354def InitPop : StoreOpcode {}
355// [Pointer, Value] -> [Pointer]
356def InitElem : Opcode {
357  let Types = [AllTypeClass];
358  let Args = [ArgUint32];
359  let HasGroup = 1;
360}
361// [Pointer, Value] -> []
362def InitElemPop : Opcode {
363  let Types = [AllTypeClass];
364  let Args = [ArgUint32];
365  let HasGroup = 1;
366}
367
368//===----------------------------------------------------------------------===//
369// Pointer arithmetic.
370//===----------------------------------------------------------------------===//
371
372// [Pointer, Integral] -> [Pointer]
373def AddOffset : AluOpcode;
374// [Pointer, Integral] -> [Pointer]
375def SubOffset : AluOpcode;
376
377//===----------------------------------------------------------------------===//
378// Binary operators.
379//===----------------------------------------------------------------------===//
380
381// [Real, Real] -> [Real]
382def Sub : AluOpcode;
383def Add : AluOpcode;
384def Mul : AluOpcode;
385
386//===----------------------------------------------------------------------===//
387// Comparison opcodes.
388//===----------------------------------------------------------------------===//
389
390class EqualityOpcode : Opcode {
391  let Types = [AllTypeClass];
392  let HasGroup = 1;
393}
394
395def EQ : EqualityOpcode;
396def NE : EqualityOpcode;
397
398class ComparisonOpcode : Opcode {
399  let Types = [ComparableTypeClass];
400  let HasGroup = 1;
401}
402
403def LT : ComparisonOpcode;
404def LE : ComparisonOpcode;
405def GT : ComparisonOpcode;
406def GE : ComparisonOpcode;
407
408//===----------------------------------------------------------------------===//
409// Stack management.
410//===----------------------------------------------------------------------===//
411
412// [Value] -> []
413def Pop : Opcode {
414  let Types = [AllTypeClass];
415  let HasGroup = 1;
416}
417
418// [Value] -> [Value, Value]
419def Dup : Opcode {
420  let Types = [AllTypeClass];
421  let HasGroup = 1;
422}
423