1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { 17 Dynamicimport, 18 Callarg0, 19 Callarg1, 20 Callargs2, 21 Callargs3, 22 Callrange, 23 WideCallrange, 24 Callthis0, 25 Callthis1, 26 Callthis2, 27 Callthis3, 28 Callthisrange, 29 WideCallthisrange, 30 Closeiterator, 31 Copydataproperties, 32 Createarraywithbuffer, 33 Createemptyarray, 34 Createemptyobject, 35 Createobjectwithbuffer, 36 Createobjectwithexcludedkeys, 37 Createregexpwithliteral, 38 Debugger, 39 Defineclasswithbuffer, 40 Definefunc, 41 Definegettersetterbyvalue, 42 Definemethod, 43 Delobjprop, 44 Getiterator, 45 Getnextpropname, 46 Getpropiterator, 47 Getmodulenamespace, 48 Isfalse, 49 Istrue, 50 Ldglobalvar, 51 Ldlexvar, 52 Ldobjbyindex, 53 Ldobjbyname, 54 Ldobjbyvalue, 55 Ldsuperbyname, 56 Ldsuperbyvalue, 57 Newlexenv, 58 Newlexenvwithname, 59 Newobjrange, 60 Poplexenv, 61 Returnundefined, 62 Setobjectwithproto, 63 Starrayspread, 64 Stconsttoglobalrecord, 65 Stglobalvar, 66 Stlexvar, 67 Stmodulevar, 68 Stobjbyindex, 69 Stobjbyname, 70 Stobjbyvalue, 71 Stownbyindex, 72 Stownbyname, 73 Stownbynamewithnameset, 74 Stownbyvalue, 75 Stownbyvaluewithnameset, 76 Stsuperbyname, 77 Stsuperbyvalue, 78 Supercallthisrange, 79 Supercallspread, 80 ThrowConstassignment, 81 ThrowDeletesuperproperty, 82 Throw, 83 ThrowIfnotobject, 84 ThrowIfsupernotcorrectcall, 85 ThrowPatternnoncoercible, 86 ThrowNotexists, 87 ThrowUndefinedifholewithname, 88 Tryldglobalbyname, 89 Trystglobalbyname, 90 Fldai, 91 Imm, 92 IRNode, 93 Jmp, 94 Label, 95 Lda, 96 Ldai, 97 LdaStr, 98 Mov, 99 Sta, 100 Ldbigint, 101 VReg, 102 WideNewlexenv, 103 WideNewlexenvwithname, 104 WideLdlexvar, 105 WideStlexvar, 106 WideLdobjbyindex, 107 WideStobjbyindex, 108 WideStownbyindex, 109 WideNewobjrange, 110 WideCreateobjectwithexcludedkeys, 111 WideSupercallthisrange, 112 WideSupercallarrowrange, 113 Supercallarrowrange, 114 WideGetmodulenamespace, 115 Ldlocalmodulevar, 116 WideLdlocalmodulevar, 117 Ldexternalmodulevar, 118 WideLdexternalmodulevar, 119 WideStmodulevar, 120 Sttoglobalrecord 121} from "../irnodes"; 122import { MAX_INT16, MAX_INT8 } from "./util"; 123 124export function loadAccumulatorInt(value: number): IRNode { 125 return new Ldai(new Imm(value)); 126} 127 128export function loadAccumulatorFloat(value: number): IRNode { 129 return new Fldai(new Imm(value)); 130} 131 132export function loadAccumulatorString(value: string): IRNode { 133 return new LdaStr(value); 134} 135 136export function loadAccumulator(vreg: VReg): IRNode { 137 return new Lda(vreg); 138} 139 140export function storeAccumulator(vreg: VReg): IRNode { 141 return new Sta(vreg); 142} 143 144export function deleteObjProperty(obj: VReg): IRNode { 145 return new Delobjprop(obj); 146} 147 148export function moveVreg(vd: VReg, vs: VReg): IRNode { 149 return new Mov(vd, vs); 150} 151 152export function jumpTarget(target: Label): IRNode { 153 return new Jmp(target); 154} 155 156export function creatDebugger(): IRNode { 157 return new Debugger(); 158} 159 160export function throwException(): IRNode { 161 return new Throw(); 162} 163 164export function throwConstAssignment(name: VReg): IRNode { 165 return new ThrowConstassignment(name); 166} 167 168export function throwUndefinedIfHole(name: string): IRNode { 169 return new ThrowUndefinedifholewithname(name); 170} 171 172export function throwThrowNotExists(): IRNode { 173 return new ThrowNotexists(); 174} 175 176export function throwDeleteSuperProperty(): IRNode { 177 return new ThrowDeletesuperproperty(); 178} 179 180export function newLexicalEnv(numVars: number, scopeInfoId: string | undefined): IRNode { 181 if (scopeInfoId === undefined) { 182 return numVars <= MAX_INT8 ? new Newlexenv(new Imm(numVars)) : 183 new WideNewlexenv(new Imm(numVars)); 184 } 185 return numVars <= MAX_INT8 ? new Newlexenvwithname(new Imm(numVars), scopeInfoId) : 186 new WideNewlexenvwithname(new Imm(numVars), scopeInfoId); 187} 188 189export function popLexicalEnv(): IRNode { 190 return new Poplexenv(); 191} 192 193export function loadLexicalVar(level: number, slot: number): IRNode { 194 if ((level > MAX_INT8) || (slot > MAX_INT8)) { 195 return new WideLdlexvar(new Imm(level), new Imm(slot)); 196 } 197 return new Ldlexvar(new Imm(level), new Imm(slot)); 198} 199 200export function storeLexicalVar(level: number, slot: number): IRNode { 201 if ((level > MAX_INT8) || (slot > MAX_INT8)) { 202 return new WideStlexvar(new Imm(level), new Imm(slot)); 203 } 204 return new Stlexvar(new Imm(level), new Imm(slot)); 205} 206 207export function tryLoadGlobalByName(key: string): IRNode { 208 return new Tryldglobalbyname(new Imm(0), key); 209} 210 211export function tryStoreGlobalByName(key: string): IRNode { 212 return new Trystglobalbyname(new Imm(0), key); 213} 214 215export function loadGlobalVar(name: string): IRNode { 216 return new Ldglobalvar(new Imm(0), name); 217} 218 219export function storeGlobalVar(name: string): IRNode { 220 return new Stglobalvar(new Imm(0), name); 221} 222 223export function loadObjByName(key: string): IRNode { 224 return new Ldobjbyname(new Imm(0), key); 225} 226 227export function storeObjByName(obj: VReg, key: string): IRNode { 228 return new Stobjbyname(new Imm(0), key, obj); 229} 230 231export function loadObjByIndex(index: number): IRNode { 232 return index <= MAX_INT16 ? new Ldobjbyindex(new Imm(0), new Imm(index)) : 233 new WideLdobjbyindex(new Imm(index)); 234} 235 236export function storeObjByIndex(obj: VReg, index: number): IRNode { 237 return index <= MAX_INT16 ? new Stobjbyindex(new Imm(0), obj, new Imm(index)) : 238 new WideStobjbyindex(obj, new Imm(index)); 239} 240 241export function loadObjByValue(obj: VReg): IRNode { 242 return new Ldobjbyvalue(new Imm(0), obj); 243} 244 245export function storeObjByValue(obj: VReg, prop: VReg): IRNode { 246 return new Stobjbyvalue(new Imm(0), obj, prop); 247} 248 249export function storeOwnByName(obj: VReg, key: string, nameSetting: boolean): IRNode { 250 return nameSetting ? new Stownbynamewithnameset(new Imm(0), key, obj) : 251 new Stownbyname(new Imm(0), key, obj); 252} 253 254export function storeOwnByIndex(obj: VReg, index: number): IRNode { 255 return index <= MAX_INT16 ? new Stownbyindex(new Imm(0), obj, new Imm(index)) : 256 new WideStownbyindex(obj, new Imm(index)); 257} 258 259export function storeOwnByValue(obj: VReg, value: VReg, nameSetting: boolean): IRNode { 260 return nameSetting ? new Stownbyvaluewithnameset(new Imm(0), obj, value) : 261 new Stownbyvalue(new Imm(0), obj, value); 262} 263 264export function throwIfSuperNotCorrectCall(num: number): IRNode { 265 return new ThrowIfsupernotcorrectcall(new Imm(num)); 266} 267 268export function call(args: VReg[], passThis: boolean): IRNode { 269 let length = args.length; 270 let insn: IRNode; 271 if (!passThis) { 272 switch (length) { 273 case 0: 274 insn = new Callarg0(new Imm(0)); 275 break; 276 case 1: 277 insn = new Callarg1(new Imm(0), args[0]); 278 break; 279 case 2: 280 insn = new Callargs2(new Imm(0), args[0], args[1]); 281 break; 282 case 3: 283 insn = new Callargs3(new Imm(0), args[0], args[1], args[2]); 284 break; 285 default: 286 insn = length <= MAX_INT8 ? new Callrange(new Imm(0), new Imm(length), args) : 287 new WideCallrange(new Imm(length), args); 288 } 289 } else { 290 insn = callThis(args); 291 } 292 293 return insn; 294} 295 296function callThis(args: Array<VReg>): IRNode { 297 let insn: IRNode; 298 let thisReg: VReg = args[0]; 299 let length = args.length; 300 switch (length) { 301 case 1: { 302 insn = new Callthis0(new Imm(0), thisReg); 303 break; 304 } 305 case 2: { 306 insn = new Callthis1(new Imm(0), thisReg, args[1]); 307 break; 308 } 309 case 3: { 310 insn = new Callthis2(new Imm(0), thisReg, args[1], args[2]); 311 break; 312 } 313 case 4: { 314 insn = new Callthis3(new Imm(0), thisReg, args[1], args[2], args[3]); 315 break; 316 } 317 default: { 318 insn = (length - 1) <= MAX_INT8 ? new Callthisrange(new Imm(0), new Imm(length - 1), args) : 319 new WideCallthisrange(new Imm(length - 1), args); 320 break; 321 } 322 } 323 return insn; 324} 325 326export function newObject(args: VReg[]): IRNode { 327 let length = args.length; 328 return length <= MAX_INT8 ? new Newobjrange(new Imm(0), new Imm(length), args) : 329 new WideNewobjrange(new Imm(length), args); 330} 331 332export function getPropIterator(): IRNode { 333 return new Getpropiterator(); 334} 335 336export function getNextPropName(iter: VReg): IRNode { 337 return new Getnextpropname(iter); 338} 339 340export function returnUndefined(): IRNode { 341 return new Returnundefined(); 342} 343 344export function createEmptyObject(): IRNode { 345 return new Createemptyobject(); 346} 347 348export function createObjectWithBuffer(bufferId: string): IRNode { 349 return new Createobjectwithbuffer(new Imm(0), bufferId); 350} 351 352export function setObjectWithProto(proto: VReg): IRNode { 353 return new Setobjectwithproto(new Imm(0), proto); 354} 355 356export function copyDataProperties(dstObj: VReg): IRNode { 357 return new Copydataproperties(dstObj); 358} 359 360export function defineGetterSetterByValue(obj: VReg, name: VReg, getter: VReg, setter: VReg): IRNode { 361 return new Definegettersetterbyvalue(obj, name, getter, setter); 362} 363 364export function createEmptyArray(): IRNode { 365 return new Createemptyarray(new Imm(0)); 366} 367 368export function createArrayWithBuffer(bufferId: string): IRNode { 369 return new Createarraywithbuffer(new Imm(0), bufferId); 370} 371 372export function storeArraySpread(array: VReg, index: VReg): IRNode { 373 return new Starrayspread(array, index); 374} 375 376export function defineClassWithBuffer(id: string, litId: string, parameterLength: number, base: VReg): IRNode { 377 return new Defineclasswithbuffer(new Imm(0), id, litId, new Imm(parameterLength), base); 378} 379 380export function createObjectWithExcludedKeys(obj: VReg, args: VReg[]): IRNode { 381 let followedArgs = args.length - 1; 382 return followedArgs <= MAX_INT8 ? new Createobjectwithexcludedkeys(new Imm(followedArgs), obj, args) : 383 new WideCreateobjectwithexcludedkeys(new Imm(followedArgs), obj, args); 384} 385 386export function throwObjectNonCoercible(): IRNode { 387 return new ThrowPatternnoncoercible(); 388} 389 390export function throwIfNotObject(v: VReg): IRNode { 391 return new ThrowIfnotobject(v); 392} 393 394export function getIterator(): IRNode { 395 return new Getiterator(new Imm(0)); 396} 397 398export function closeIterator(iter: VReg): IRNode { 399 return new Closeiterator(new Imm(0), iter); 400} 401 402export function superCall(num: number, args: Array<VReg>): IRNode { 403 return num <= MAX_INT8 ? new Supercallthisrange(new Imm(0), new Imm(num), args) : 404 new WideSupercallthisrange(new Imm(num), args); 405} 406 407export function superCallInArrow(num: number, args: Array<VReg>): IRNode { 408 return num <= MAX_INT8 ? new Supercallarrowrange(new Imm(0), new Imm(num), args) : 409 new WideSupercallarrowrange(new Imm(num), args); 410} 411 412export function superCallSpread(vs: VReg): IRNode { 413 return new Supercallspread(new Imm(0), vs); 414} 415 416export function ldSuperByName(key: string): IRNode { 417 return new Ldsuperbyname(new Imm(0), key); // obj is in acc 418} 419 420export function stSuperByName(obj: VReg, key: string): IRNode { 421 return new Stsuperbyname(new Imm(0), key, obj); 422} 423 424export function stSuperByValue(obj: VReg, prop: VReg): IRNode { 425 return new Stsuperbyvalue(new Imm(0), obj, prop); 426} 427 428export function ldSuperByValue(obj: VReg): IRNode { 429 return new Ldsuperbyvalue(new Imm(0), obj); // prop is in acc 430} 431 432export function loadLocalModuleVariable(index: number): IRNode { 433 return index <= MAX_INT8 ? new Ldlocalmodulevar(new Imm(index)) : new WideLdlocalmodulevar(new Imm(index)); 434} 435 436export function loadExternalModuleVariable(index: number): IRNode { 437 return index <= MAX_INT8 ? new Ldexternalmodulevar(new Imm(index)) : new WideLdexternalmodulevar(new Imm(index)); 438} 439 440 441export function dynamicImport() { 442 return new Dynamicimport(); 443} 444 445export function storeModuleVariable(index: number): IRNode { 446 return index <= MAX_INT8 ? new Stmodulevar(new Imm(index)) : new WideStmodulevar(new Imm(index)); 447} 448 449export function getModuleNamespace(moduleRequestIdx: number): IRNode { 450 return moduleRequestIdx <= MAX_INT8 ? new Getmodulenamespace(new Imm(moduleRequestIdx)) : 451 new WideGetmodulenamespace(new Imm(moduleRequestIdx)); 452} 453 454export function defineFunc(name: string, paramLength: number): IRNode { 455 return new Definefunc(new Imm(0), name, new Imm(paramLength)); 456} 457 458export function defineMethod(name: string, paramLength: number): IRNode { 459 return new Definemethod(new Imm(0), name, new Imm(paramLength)); 460} 461 462export function isTrue(): IRNode { 463 return new Istrue(); 464} 465 466export function isFalse(): IRNode { 467 return new Isfalse(); 468} 469 470export function createRegExpWithLiteral(pattern: string, flags: number): IRNode { 471 return new Createregexpwithliteral(new Imm(0), pattern, new Imm(flags)); 472} 473 474export function stLetOrClassToGlobalRecord(name: string): IRNode { 475 return new Sttoglobalrecord(new Imm(0), name); 476} 477 478export function stConstToGlobalRecord(name: string): IRNode { 479 return new Stconsttoglobalrecord(new Imm(0), name); 480} 481 482export function loadAccumulatorBigInt(value: string): IRNode { 483 return new Ldbigint(value); 484}