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