//===--- Opcodes.td - Opcode defitions for the constexpr VM -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Helper file used to generate opcodes, the interpreter and the disassembler. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Types evaluated by the interpreter. //===----------------------------------------------------------------------===// class Type; def Bool : Type; def Sint8 : Type; def Uint8 : Type; def Sint16 : Type; def Uint16 : Type; def Sint32 : Type; def Uint32 : Type; def Sint64 : Type; def Uint64 : Type; def Ptr : Type; //===----------------------------------------------------------------------===// // Types transferred to the interpreter. //===----------------------------------------------------------------------===// class ArgType { string Name = ?; } def ArgSint8 : ArgType { let Name = "int8_t"; } def ArgUint8 : ArgType { let Name = "uint8_t"; } def ArgSint16 : ArgType { let Name = "int16_t"; } def ArgUint16 : ArgType { let Name = "uint16_t"; } def ArgSint32 : ArgType { let Name = "int32_t"; } def ArgUint32 : ArgType { let Name = "uint32_t"; } def ArgSint64 : ArgType { let Name = "int64_t"; } def ArgUint64 : ArgType { let Name = "uint64_t"; } def ArgBool : ArgType { let Name = "bool"; } def ArgFunction : ArgType { let Name = "Function *"; } def ArgRecord : ArgType { let Name = "Record *"; } def ArgSema : ArgType { let Name = "const fltSemantics *"; } def ArgExpr : ArgType { let Name = "const Expr *"; } def ArgFloatingLiteral : ArgType { let Name = "const FloatingLiteral *"; } def ArgCXXMethodDecl : ArgType { let Name = "const CXXMethodDecl *"; } def ArgFunctionDecl : ArgType { let Name = "const FunctionDecl *"; } def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; } def ArgCXXRecordDecl : ArgType { let Name = "const CXXRecordDecl *"; } def ArgValueDecl : ArgType { let Name = "const ValueDecl *"; } def ArgRecordField : ArgType { let Name = "const Record::Field *"; } //===----------------------------------------------------------------------===// // Classes of types instructions operate on. //===----------------------------------------------------------------------===// class TypeClass { list<Type> Types; } def AluTypeClass : TypeClass { let Types = [Sint8, Uint8, Sint16, Uint16, Sint32, Uint32, Sint64, Uint64, Bool]; } def PtrTypeClass : TypeClass { let Types = [Ptr]; } def AllTypeClass : TypeClass { let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types); } def ComparableTypeClass : TypeClass { let Types = !listconcat(AluTypeClass.Types, [Ptr]); } class SingletonTypeClass<Type Ty> : TypeClass { let Types = [Ty]; } //===----------------------------------------------------------------------===// // Record describing all opcodes. //===----------------------------------------------------------------------===// class Opcode { list<TypeClass> Types = []; list<ArgType> Args = []; string Name = ""; bit CanReturn = 0; bit ChangesPC = 0; bit HasCustomLink = 0; bit HasCustomEval = 0; bit HasGroup = 0; } class AluOpcode : Opcode { let Types = [AluTypeClass]; let HasGroup = 1; } //===----------------------------------------------------------------------===// // Jump opcodes //===----------------------------------------------------------------------===// class JumpOpcode : Opcode { let Args = [ArgSint32]; let ChangesPC = 1; let HasCustomEval = 1; } // [] -> [] def Jmp : JumpOpcode; // [Bool] -> [], jumps if true. def Jt : JumpOpcode; // [Bool] -> [], jumps if false. def Jf : JumpOpcode; //===----------------------------------------------------------------------===// // Returns //===----------------------------------------------------------------------===// // [Value] -> [] def Ret : Opcode { let Types = [AllTypeClass]; let ChangesPC = 1; let CanReturn = 1; let HasGroup = 1; let HasCustomEval = 1; } // [] -> [] def RetVoid : Opcode { let CanReturn = 1; let ChangesPC = 1; let HasCustomEval = 1; } // [Value] -> [] def RetValue : Opcode { let CanReturn = 1; let ChangesPC = 1; let HasCustomEval = 1; } // [] -> EXIT def NoRet : Opcode {} //===----------------------------------------------------------------------===// // Frame management //===----------------------------------------------------------------------===// // [] -> [] def Destroy : Opcode { let Args = [ArgUint32]; let HasCustomEval = 1; } //===----------------------------------------------------------------------===// // Constants //===----------------------------------------------------------------------===// class ConstOpcode<Type Ty, ArgType ArgTy> : Opcode { let Types = [SingletonTypeClass<Ty>]; let Args = [ArgTy]; let Name = "Const"; } // [] -> [Integer] def ConstSint8 : ConstOpcode<Sint8, ArgSint8>; def ConstUint8 : ConstOpcode<Uint8, ArgUint8>; def ConstSint16 : ConstOpcode<Sint16, ArgSint16>; def ConstUint16 : ConstOpcode<Uint16, ArgUint16>; def ConstSint32 : ConstOpcode<Sint32, ArgSint32>; def ConstUint32 : ConstOpcode<Uint32, ArgUint32>; def ConstSint64 : ConstOpcode<Sint64, ArgSint64>; def ConstUint64 : ConstOpcode<Uint64, ArgUint64>; def ConstBool : ConstOpcode<Bool, ArgBool>; // [] -> [Integer] def Zero : Opcode { let Types = [AluTypeClass]; } // [] -> [Pointer] def Null : Opcode { let Types = [PtrTypeClass]; } //===----------------------------------------------------------------------===// // Pointer generation //===----------------------------------------------------------------------===// // [] -> [Pointer] def GetPtrLocal : Opcode { // Offset of local. let Args = [ArgUint32]; bit HasCustomEval = 1; } // [] -> [Pointer] def GetPtrParam : Opcode { // Offset of parameter. let Args = [ArgUint32]; } // [] -> [Pointer] def GetPtrGlobal : Opcode { // Index of global. let Args = [ArgUint32]; } // [Pointer] -> [Pointer] def GetPtrField : Opcode { // Offset of field. let Args = [ArgUint32]; } // [Pointer] -> [Pointer] def GetPtrActiveField : Opcode { // Offset of field. let Args = [ArgUint32]; } // [] -> [Pointer] def GetPtrActiveThisField : Opcode { // Offset of field. let Args = [ArgUint32]; } // [] -> [Pointer] def GetPtrThisField : Opcode { // Offset of field. let Args = [ArgUint32]; } // [Pointer] -> [Pointer] def GetPtrBase : Opcode { // Offset of field, which is a base. let Args = [ArgUint32]; } // [Pointer] -> [Pointer] def GetPtrVirtBase : Opcode { // RecordDecl of base class. let Args = [ArgRecordDecl]; } // [] -> [Pointer] def GetPtrThisBase : Opcode { // Offset of field, which is a base. let Args = [ArgUint32]; } // [] -> [Pointer] def GetPtrThisVirtBase : Opcode { // RecordDecl of base class. let Args = [ArgRecordDecl]; } // [] -> [Pointer] def This : Opcode; // [Pointer] -> [Pointer] def NarrowPtr : Opcode; // [Pointer] -> [Pointer] def ExpandPtr : Opcode; //===----------------------------------------------------------------------===// // Direct field accessors //===----------------------------------------------------------------------===// class AccessOpcode : Opcode { let Types = [AllTypeClass]; let Args = [ArgUint32]; let HasGroup = 1; } class BitFieldOpcode : Opcode { let Types = [AluTypeClass]; let Args = [ArgRecordField]; let HasGroup = 1; } // [] -> [Pointer] def GetLocal : AccessOpcode { let HasCustomEval = 1; } // [] -> [Pointer] def SetLocal : AccessOpcode { let HasCustomEval = 1; } // [] -> [Value] def GetGlobal : AccessOpcode; // [Value] -> [] def InitGlobal : AccessOpcode; // [Value] -> [] def SetGlobal : AccessOpcode; // [] -> [Value] def GetParam : AccessOpcode; // [Value] -> [] def SetParam : AccessOpcode; // [Pointer] -> [Pointer, Value] def GetField : AccessOpcode; // [Pointer] -> [Value] def GetFieldPop : AccessOpcode; // [] -> [Value] def GetThisField : AccessOpcode; // [Pointer, Value] -> [Pointer] def SetField : AccessOpcode; // [Value] -> [] def SetThisField : AccessOpcode; // [Value] -> [] def InitThisField : AccessOpcode; // [Value] -> [] def InitThisFieldActive : AccessOpcode; // [Value] -> [] def InitThisBitField : BitFieldOpcode; // [Pointer, Value] -> [] def InitField : AccessOpcode; // [Pointer, Value] -> [] def InitBitField : BitFieldOpcode; // [Pointer, Value] -> [] def InitFieldActive : AccessOpcode; //===----------------------------------------------------------------------===// // Pointer access //===----------------------------------------------------------------------===// class LoadOpcode : Opcode { let Types = [AllTypeClass]; let HasGroup = 1; } // [Pointer] -> [Pointer, Value] def Load : LoadOpcode {} // [Pointer] -> [Value] def LoadPop : LoadOpcode {} class StoreOpcode : Opcode { let Types = [AllTypeClass]; let HasGroup = 1; } class StoreBitFieldOpcode : Opcode { let Types = [AluTypeClass]; let HasGroup = 1; } // [Pointer, Value] -> [Pointer] def Store : StoreOpcode {} // [Pointer, Value] -> [] def StorePop : StoreOpcode {} // [Pointer, Value] -> [Pointer] def StoreBitField : StoreBitFieldOpcode {} // [Pointer, Value] -> [] def StoreBitFieldPop : StoreBitFieldOpcode {} // [Pointer, Value] -> [] def InitPop : StoreOpcode {} // [Pointer, Value] -> [Pointer] def InitElem : Opcode { let Types = [AllTypeClass]; let Args = [ArgUint32]; let HasGroup = 1; } // [Pointer, Value] -> [] def InitElemPop : Opcode { let Types = [AllTypeClass]; let Args = [ArgUint32]; let HasGroup = 1; } //===----------------------------------------------------------------------===// // Pointer arithmetic. //===----------------------------------------------------------------------===// // [Pointer, Integral] -> [Pointer] def AddOffset : AluOpcode; // [Pointer, Integral] -> [Pointer] def SubOffset : AluOpcode; //===----------------------------------------------------------------------===// // Binary operators. //===----------------------------------------------------------------------===// // [Real, Real] -> [Real] def Sub : AluOpcode; def Add : AluOpcode; def Mul : AluOpcode; //===----------------------------------------------------------------------===// // Comparison opcodes. //===----------------------------------------------------------------------===// class EqualityOpcode : Opcode { let Types = [AllTypeClass]; let HasGroup = 1; } def EQ : EqualityOpcode; def NE : EqualityOpcode; class ComparisonOpcode : Opcode { let Types = [ComparableTypeClass]; let HasGroup = 1; } def LT : ComparisonOpcode; def LE : ComparisonOpcode; def GT : ComparisonOpcode; def GE : ComparisonOpcode; //===----------------------------------------------------------------------===// // Stack management. //===----------------------------------------------------------------------===// // [Value] -> [] def Pop : Opcode { let Types = [AllTypeClass]; let HasGroup = 1; } // [Value] -> [Value, Value] def Dup : Opcode { let Types = [AllTypeClass]; let HasGroup = 1; }