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 Float : Type;
29def Ptr : Type;
30def FnPtr : Type;
31
32//===----------------------------------------------------------------------===//
33// Types transferred to the interpreter.
34//===----------------------------------------------------------------------===//
35
36class ArgType { string Name = ?; }
37def ArgSint8 : ArgType { let Name = "int8_t"; }
38def ArgUint8 : ArgType { let Name = "uint8_t"; }
39def ArgSint16 : ArgType { let Name = "int16_t"; }
40def ArgUint16 : ArgType { let Name = "uint16_t"; }
41def ArgSint32 : ArgType { let Name = "int32_t"; }
42def ArgUint32 : ArgType { let Name = "uint32_t"; }
43def ArgSint64 : ArgType { let Name = "int64_t"; }
44def ArgUint64 : ArgType { let Name = "uint64_t"; }
45def ArgFloat : ArgType { let Name = "Floating"; }
46def ArgBool : ArgType { let Name = "bool"; }
47
48def ArgFunction : ArgType { let Name = "const Function *"; }
49def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; }
50def ArgRecordField : ArgType { let Name = "const Record::Field *"; }
51def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; }
52def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; }
53def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; }
54
55//===----------------------------------------------------------------------===//
56// Classes of types instructions operate on.
57//===----------------------------------------------------------------------===//
58
59class TypeClass {
60  list<Type> Types;
61}
62
63def IntegerTypeClass : TypeClass {
64  let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
65               Uint32, Sint64, Uint64];
66}
67
68def NumberTypeClass : TypeClass {
69  let Types = !listconcat(IntegerTypeClass.Types, [Float]);
70}
71
72def FloatTypeClass : TypeClass {
73  let Types = [Float];
74}
75
76def AluTypeClass : TypeClass {
77  let Types = !listconcat(IntegerTypeClass.Types, [Bool]);
78}
79
80def PtrTypeClass : TypeClass {
81  let Types = [Ptr, FnPtr];
82}
83
84def BoolTypeClass : TypeClass {
85  let Types = [Bool];
86}
87
88def NonPtrTypeClass : TypeClass {
89  let Types = !listconcat(IntegerTypeClass.Types, [Bool], [Float]);
90}
91
92def AllTypeClass : TypeClass {
93  let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types);
94}
95
96def ComparableTypeClass : TypeClass {
97  let Types = !listconcat(AluTypeClass.Types, [Ptr], [Float], [FnPtr]);
98}
99
100class SingletonTypeClass<Type Ty> : TypeClass {
101  let Types = [Ty];
102}
103
104//===----------------------------------------------------------------------===//
105// Record describing all opcodes.
106//===----------------------------------------------------------------------===//
107
108class Opcode {
109  list<TypeClass> Types = [];
110  list<ArgType> Args = [];
111  string Name = "";
112  bit CanReturn = 0;
113  bit ChangesPC = 0;
114  bit HasCustomLink = 0;
115  bit HasCustomEval = 0;
116  bit HasGroup = 0;
117}
118
119class AluOpcode : Opcode {
120  let Types = [AluTypeClass];
121  let HasGroup = 1;
122}
123
124class FloatOpcode : Opcode {
125  let Types = [];
126  let Args = [ArgRoundingMode];
127}
128
129class IntegerOpcode : Opcode {
130  let Types = [IntegerTypeClass];
131  let HasGroup = 1;
132}
133
134//===----------------------------------------------------------------------===//
135// Jump opcodes
136//===----------------------------------------------------------------------===//
137
138class JumpOpcode : Opcode {
139  let Args = [ArgSint32];
140  let ChangesPC = 1;
141  let HasCustomEval = 1;
142}
143
144// [] -> []
145def Jmp : JumpOpcode;
146// [Bool] -> [], jumps if true.
147def Jt : JumpOpcode;
148// [Bool] -> [], jumps if false.
149def Jf : JumpOpcode;
150
151//===----------------------------------------------------------------------===//
152// Returns
153//===----------------------------------------------------------------------===//
154
155// [Value] -> []
156def Ret : Opcode {
157  let Types = [AllTypeClass];
158  let ChangesPC = 1;
159  let CanReturn = 1;
160  let HasGroup = 1;
161  let HasCustomEval = 1;
162}
163// [] -> []
164def RetVoid : Opcode {
165  let CanReturn = 1;
166  let ChangesPC = 1;
167  let HasCustomEval = 1;
168}
169// [Value] -> []
170def RetValue : Opcode {
171  let CanReturn = 1;
172  let ChangesPC = 1;
173  let HasCustomEval = 1;
174}
175// [] -> EXIT
176def NoRet : Opcode {}
177
178
179def Call : Opcode {
180  let Args = [ArgFunction];
181  let Types = [];
182}
183
184def CallVirt : Opcode {
185  let Args = [ArgFunction];
186  let Types = [];
187}
188
189def CallBI : Opcode {
190  let Args = [ArgFunction];
191  let Types = [];
192}
193
194def CallPtr : Opcode {
195  let Args = [];
196  let Types = [];
197}
198
199//===----------------------------------------------------------------------===//
200// Frame management
201//===----------------------------------------------------------------------===//
202
203// [] -> []
204def Destroy : Opcode {
205  let Args = [ArgUint32];
206  let HasCustomEval = 1;
207}
208
209//===----------------------------------------------------------------------===//
210// Constants
211//===----------------------------------------------------------------------===//
212
213class ConstOpcode<Type Ty, ArgType ArgTy> : Opcode {
214  let Types = [SingletonTypeClass<Ty>];
215  let Args = [ArgTy];
216  let Name = "Const";
217}
218
219// [] -> [Integer]
220def ConstSint8 : ConstOpcode<Sint8, ArgSint8>;
221def ConstUint8 : ConstOpcode<Uint8, ArgUint8>;
222def ConstSint16 : ConstOpcode<Sint16, ArgSint16>;
223def ConstUint16 : ConstOpcode<Uint16, ArgUint16>;
224def ConstSint32 : ConstOpcode<Sint32, ArgSint32>;
225def ConstUint32 : ConstOpcode<Uint32, ArgUint32>;
226def ConstSint64 : ConstOpcode<Sint64, ArgSint64>;
227def ConstUint64 : ConstOpcode<Uint64, ArgUint64>;
228def ConstFloat : ConstOpcode<Float, ArgFloat>;
229def ConstBool : ConstOpcode<Bool, ArgBool>;
230
231// [] -> [Integer]
232def Zero : Opcode {
233  let Types = [AluTypeClass];
234  let HasGroup = 1;
235}
236
237// [] -> [Pointer]
238def Null : Opcode {
239  let Types = [PtrTypeClass];
240  let HasGroup = 1;
241}
242
243//===----------------------------------------------------------------------===//
244// Pointer generation
245//===----------------------------------------------------------------------===//
246
247// [] -> [Pointer]
248def GetPtrLocal : Opcode {
249  // Offset of local.
250  let Args = [ArgUint32];
251  bit HasCustomEval = 1;
252}
253// [] -> [Pointer]
254def GetPtrParam : Opcode {
255  // Offset of parameter.
256  let Args = [ArgUint32];
257}
258// [] -> [Pointer]
259def GetPtrGlobal : Opcode {
260  // Index of global.
261  let Args = [ArgUint32];
262}
263// [Pointer] -> [Pointer]
264def GetPtrField : Opcode {
265  // Offset of field.
266  let Args = [ArgUint32];
267}
268// [Pointer] -> [Pointer]
269def GetPtrActiveField : Opcode {
270  // Offset of field.
271  let Args = [ArgUint32];
272}
273// [] -> [Pointer]
274def GetPtrActiveThisField : Opcode {
275  // Offset of field.
276  let Args = [ArgUint32];
277}
278// [] -> [Pointer]
279def GetPtrThisField : Opcode {
280  // Offset of field.
281  let Args = [ArgUint32];
282}
283// [Pointer] -> [Pointer]
284def GetPtrBase : Opcode {
285  // Offset of field, which is a base.
286  let Args = [ArgUint32];
287}
288// [Pointer] -> [Pointer]
289def GetPtrBasePop : Opcode {
290  // Offset of field, which is a base.
291  let Args = [ArgUint32];
292}
293
294// [Pointer] -> [Pointer]
295def GetPtrVirtBase : Opcode {
296  // RecordDecl of base class.
297  let Args = [ArgRecordDecl];
298}
299// [] -> [Pointer]
300def GetPtrThisBase : Opcode {
301  // Offset of field, which is a base.
302  let Args = [ArgUint32];
303}
304// [] -> [Pointer]
305def GetPtrThisVirtBase : Opcode {
306  // RecordDecl of base class.
307  let Args = [ArgRecordDecl];
308}
309// [] -> [Pointer]
310def This : Opcode;
311
312// [] -> [Pointer]
313def RVOPtr : Opcode;
314
315// [Pointer] -> [Pointer]
316def NarrowPtr : Opcode;
317// [Pointer] -> [Pointer]
318def ExpandPtr : Opcode;
319// [Pointer, Offset] -> [Pointer]
320def ArrayElemPtr : AluOpcode;
321def ArrayElemPtrPop : AluOpcode;
322
323//===----------------------------------------------------------------------===//
324// Direct field accessors
325//===----------------------------------------------------------------------===//
326
327class AccessOpcode : Opcode {
328  let Types = [AllTypeClass];
329  let Args = [ArgUint32];
330  let HasGroup = 1;
331}
332
333class BitFieldOpcode : Opcode {
334  let Types = [AluTypeClass];
335  let Args = [ArgRecordField];
336  let HasGroup = 1;
337}
338
339// [] -> [Pointer]
340def GetLocal : AccessOpcode { let HasCustomEval = 1; }
341// [] -> [Pointer]
342def SetLocal : AccessOpcode { let HasCustomEval = 1; }
343
344def CheckGlobalCtor : Opcode {}
345
346// [] -> [Value]
347def GetGlobal : AccessOpcode;
348// [Value] -> []
349def InitGlobal : AccessOpcode;
350// [Value] -> []
351def InitGlobalTemp : AccessOpcode {
352  let Args = [ArgUint32, ArgLETD];
353}
354// [Value] -> []
355def SetGlobal : AccessOpcode;
356
357// [] -> [Value]
358def GetParam : AccessOpcode;
359// [Value] -> []
360def SetParam : AccessOpcode;
361
362// [Pointer] -> [Pointer, Value]
363def GetField : AccessOpcode;
364// [Pointer] -> [Value]
365def GetFieldPop : AccessOpcode;
366// [] -> [Value]
367def GetThisField : AccessOpcode;
368
369// [Pointer, Value] -> [Pointer]
370def SetField : AccessOpcode;
371// [Value] -> []
372def SetThisField : AccessOpcode;
373
374// [Value] -> []
375def InitThisField : AccessOpcode;
376// [Value] -> []
377def InitThisFieldActive : AccessOpcode;
378// [Value] -> []
379def InitThisBitField : BitFieldOpcode;
380// [Pointer, Value] -> []
381def InitField : AccessOpcode;
382// [Pointer, Value] -> []
383def InitBitField : BitFieldOpcode;
384// [Pointer, Value] -> []
385def InitFieldActive : AccessOpcode;
386
387//===----------------------------------------------------------------------===//
388// Pointer access
389//===----------------------------------------------------------------------===//
390
391class LoadOpcode : Opcode {
392  let Types = [AllTypeClass];
393  let HasGroup = 1;
394}
395
396// [Pointer] -> [Pointer, Value]
397def Load : LoadOpcode {}
398// [Pointer] -> [Value]
399def LoadPop : LoadOpcode {}
400
401class StoreOpcode : Opcode {
402  let Types = [AllTypeClass];
403  let HasGroup = 1;
404}
405
406class StoreBitFieldOpcode : Opcode {
407  let Types = [AluTypeClass];
408  let HasGroup = 1;
409}
410
411// [Pointer, Value] -> [Pointer]
412def Store : StoreOpcode {}
413// [Pointer, Value] -> []
414def StorePop : StoreOpcode {}
415
416// [Pointer, Value] -> [Pointer]
417def StoreBitField : StoreBitFieldOpcode {}
418// [Pointer, Value] -> []
419def StoreBitFieldPop : StoreBitFieldOpcode {}
420
421// [Pointer, Value] -> []
422def InitPop : StoreOpcode {}
423// [Pointer, Value] -> [Pointer]
424def InitElem : Opcode {
425  let Types = [AllTypeClass];
426  let Args = [ArgUint32];
427  let HasGroup = 1;
428}
429// [Pointer, Value] -> []
430def InitElemPop : Opcode {
431  let Types = [AllTypeClass];
432  let Args = [ArgUint32];
433  let HasGroup = 1;
434}
435
436//===----------------------------------------------------------------------===//
437// Pointer arithmetic.
438//===----------------------------------------------------------------------===//
439
440// [Pointer, Integral] -> [Pointer]
441def AddOffset : AluOpcode;
442// [Pointer, Integral] -> [Pointer]
443def SubOffset : AluOpcode;
444
445// [Pointer, Pointer] -> [Integral]
446def SubPtr : Opcode {
447  let Types = [IntegerTypeClass];
448  let HasGroup = 1;
449}
450
451// [Pointer] -> [Pointer]
452def IncPtr : Opcode {
453  let HasGroup = 0;
454}
455// [Pointer] -> [Pointer]
456def DecPtr : Opcode {
457  let HasGroup = 0;
458}
459
460//===----------------------------------------------------------------------===//
461// Function pointers.
462//===----------------------------------------------------------------------===//
463def GetFnPtr : Opcode {
464  let Args = [ArgFunction];
465}
466
467
468//===----------------------------------------------------------------------===//
469// Binary operators.
470//===----------------------------------------------------------------------===//
471
472// [Real, Real] -> [Real]
473def Add  : AluOpcode;
474def Addf : FloatOpcode;
475def Sub  : AluOpcode;
476def Subf : FloatOpcode;
477def Mul  : AluOpcode;
478def Mulf : FloatOpcode;
479def Rem  : IntegerOpcode;
480def Div  : IntegerOpcode;
481def Divf : FloatOpcode;
482
483def BitAnd : IntegerOpcode;
484def BitOr : IntegerOpcode;
485def BitXor : IntegerOpcode;
486
487def Shl : Opcode {
488  let Types = [IntegerTypeClass, IntegerTypeClass];
489  let HasGroup = 1;
490}
491
492def Shr : Opcode {
493  let Types = [IntegerTypeClass, IntegerTypeClass];
494  let HasGroup = 1;
495}
496
497//===----------------------------------------------------------------------===//
498// Unary operators.
499//===----------------------------------------------------------------------===//
500
501// [Real] -> [Real]
502def Inv: Opcode {
503  let Types = [BoolTypeClass];
504  let HasGroup = 1;
505}
506
507// Increment and decrement.
508def Inc: IntegerOpcode;
509def IncPop : IntegerOpcode;
510def Dec: IntegerOpcode;
511def DecPop: IntegerOpcode;
512
513// Float increment and decrement.
514def Incf: FloatOpcode;
515def IncfPop : FloatOpcode;
516def Decf: FloatOpcode;
517def DecfPop : FloatOpcode;
518
519// [Real] -> [Real]
520def Neg: Opcode {
521  let Types = [NonPtrTypeClass];
522  let HasGroup = 1;
523}
524
525// [Real] -> [Real]
526def Comp: Opcode {
527  let Types = [IntegerTypeClass];
528  let HasGroup = 1;
529}
530
531//===----------------------------------------------------------------------===//
532// Cast, CastFP.
533//===----------------------------------------------------------------------===//
534
535def FromCastTypeClass : TypeClass {
536  let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
537}
538
539def ToCastTypeClass : TypeClass {
540  let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
541}
542
543def Cast: Opcode {
544  let Types = [FromCastTypeClass, ToCastTypeClass];
545  let HasGroup = 1;
546}
547
548def CastFP : Opcode {
549  let Types = [];
550  let Args = [ArgFltSemantics, ArgRoundingMode];
551}
552
553// Cast an integer to a floating type
554def CastIntegralFloating : Opcode {
555  let Types = [AluTypeClass];
556  let Args = [ArgFltSemantics, ArgRoundingMode];
557  let HasGroup = 1;
558}
559
560// Cast a floating to an integer type
561def CastFloatingIntegral : Opcode {
562  let Types = [AluTypeClass];
563  let Args = [];
564  let HasGroup = 1;
565}
566
567//===----------------------------------------------------------------------===//
568// Comparison opcodes.
569//===----------------------------------------------------------------------===//
570
571class EqualityOpcode : Opcode {
572  let Types = [AllTypeClass];
573  let HasGroup = 1;
574}
575
576def EQ : EqualityOpcode;
577def NE : EqualityOpcode;
578
579class ComparisonOpcode : Opcode {
580  let Types = [ComparableTypeClass];
581  let HasGroup = 1;
582}
583
584def LT : ComparisonOpcode;
585def LE : ComparisonOpcode;
586def GT : ComparisonOpcode;
587def GE : ComparisonOpcode;
588
589//===----------------------------------------------------------------------===//
590// Stack management.
591//===----------------------------------------------------------------------===//
592
593// [Value] -> []
594def Pop : Opcode {
595  let Types = [AllTypeClass];
596  let HasGroup = 1;
597}
598
599// [Value] -> [Value, Value]
600def Dup : Opcode {
601  let Types = [AllTypeClass];
602  let HasGroup = 1;
603}
604