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