From 9245bc56f3962bc2616dfa6e883422f7b17d46ca Mon Sep 17 00:00:00 2001 From: hufeng Date: Mon, 28 Feb 2022 21:41:36 +0800 Subject: [PATCH] lowering memory consumption Signed-off-by: hufeng Change-Id: Ib5676540b565f14e2478626a9484cb317f7c0504 --- ts2panda/src/assemblyDumper.ts | 10 +- ts2panda/src/base/bcGenUtil.ts | 49 ++- ts2panda/src/cmdOptions.ts | 8 - ts2panda/src/compilerDriver.ts | 25 +- ts2panda/src/compilerStatistics.ts | 2 +- ts2panda/src/debuginfo.ts | 18 +- ts2panda/src/index.ts | 24 +- ts2panda/src/intrinsicExpander.ts | 192 ------------ ts2panda/src/pandagen.ts | 25 +- ts2panda/src/pass/ICPass.ts | 55 ---- ts2panda/src/regAllocator.ts | 18 +- ts2panda/src/ts2panda.ts | 59 ++-- ts2panda/templates/irnodes.ts.erb | 485 +++++++++++++---------------- 13 files changed, 306 insertions(+), 664 deletions(-) delete mode 100644 ts2panda/src/intrinsicExpander.ts delete mode 100644 ts2panda/src/pass/ICPass.ts diff --git a/ts2panda/src/assemblyDumper.ts b/ts2panda/src/assemblyDumper.ts index c425d876fd..c2de81cd02 100644 --- a/ts2panda/src/assemblyDumper.ts +++ b/ts2panda/src/assemblyDumper.ts @@ -82,7 +82,7 @@ export class AssemblyDumper { for (let i = 0; i < parametersCount; ++i) { let node = irNodes[i]; this.output += "\t"; - this.output += node.mnemonic + " v" + (node.operands[0]).num + ", a" + ((node.operands[0]).num) + "\n"; + this.output += node.getMnemonic() + " v" + (node.operands[0]).num + ", a" + ((node.operands[0]).num) + "\n"; } for (let i = parametersCount; i < irNodes.length; ++i) { @@ -96,16 +96,16 @@ export class AssemblyDumper { } this.output += "\t" - this.output += node.mnemonic + " "; + this.output += node.getMnemonic() + " "; let operands = node.operands; - let formats = node.formats; + let formats = node.getFormats(); var outputRangeVregNum = getRangeExplicitVregNums(node); for (let j = 0; j < operands.length; ++j) { if (outputRangeVregNum == 0) { break; } let format = formats[0]; - let kind = format[j].kind; + let kind = format[j][0]; let op = operands[j]; if (kind == OperandKind.Imm) { @@ -122,7 +122,7 @@ export class AssemblyDumper { || kind == OperandKind.SrcVReg) { let v = op; if (v.num < 0) { - throw Error("invalid register, please check your insn!\nRegister was allocated at:\n" + v.getStackTrace() + "\n"); + throw Error("invalid register, please check your insn!\n"); } this.output += "v" + v.num.toString(); // we don't need to print all the registers for range inst, just the first one diff --git a/ts2panda/src/base/bcGenUtil.ts b/ts2panda/src/base/bcGenUtil.ts index 4f19537799..04dd4d9de3 100755 --- a/ts2panda/src/base/bcGenUtil.ts +++ b/ts2panda/src/base/bcGenUtil.ts @@ -96,7 +96,6 @@ import { LdaiDyn, LdaStr, MovDyn, - ResultType, StaDyn, EcmaStclasstoglobalrecord, EcmaStconsttoglobalrecord, @@ -105,11 +104,11 @@ import { } from "../irnodes"; export function loadAccumulatorInt(value: number): IRNode { - return new LdaiDyn(new Imm(ResultType.Int, value)); + return new LdaiDyn(new Imm(value)); } export function loadAccumulatorFloat(value: number): IRNode { - return new FldaiDyn(new Imm(ResultType.Float, value)); + return new FldaiDyn(new Imm(value)); } export function loadAccumulatorString(value: string): IRNode { @@ -161,7 +160,7 @@ export function throwDeleteSuperProperty() { } export function newLexicalEnv(numVars: number) { - return new EcmaNewlexenvdyn(new Imm(ResultType.Int, numVars)); + return new EcmaNewlexenvdyn(new Imm(numVars)); } export function loadLexicalEnv() { @@ -173,11 +172,11 @@ export function popLexicalEnv() { } export function loadLexicalVar(level: number, slot: number) { - return new EcmaLdlexvardyn(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot)); + return new EcmaLdlexvardyn(new Imm(level), new Imm(slot)); } export function storeLexicalVar(level: number, slot: number, value: VReg) { - return new EcmaStlexvardyn(new Imm(ResultType.Int, level), new Imm(ResultType.Int, slot), value); + return new EcmaStlexvardyn(new Imm(level), new Imm(slot), value); } export function tryLoadGlobalByName(key: string) { @@ -205,11 +204,11 @@ export function storeObjByName(obj: VReg, key: string) { } export function loadObjByIndex(obj: VReg, index: number) { - return new EcmaLdobjbyindex(obj, new Imm(ResultType.Int, index)); + return new EcmaLdobjbyindex(obj, new Imm(index)); } export function storeObjByIndex(obj: VReg, index: number) { - return new EcmaStobjbyindex(obj, new Imm(ResultType.Int, index)); + return new EcmaStobjbyindex(obj, new Imm(index)); } export function loadObjByValue(obj: VReg, prop: VReg): IRNode { @@ -225,7 +224,7 @@ export function storeOwnByName(obj: VReg, key: string, nameSetting: boolean): IR } export function storeOwnByIndex(obj: VReg, index: number) { - return new EcmaStownbyindex(obj, new Imm(ResultType.Int, index)); + return new EcmaStownbyindex(obj, new Imm(index)); } export function storeOwnByValue(obj: VReg, value: VReg, nameSetting: boolean) { @@ -233,7 +232,7 @@ export function storeOwnByValue(obj: VReg, value: VReg, nameSetting: boolean) { } export function throwIfSuperNotCorrectCall(num: number) { - return new EcmaThrowifsupernotcorrectcall(new Imm(ResultType.Int, num)); + return new EcmaThrowifsupernotcorrectcall(new Imm(num)); } export function call(args: VReg[], passThis: boolean) { @@ -254,17 +253,17 @@ export function call(args: VReg[], passThis: boolean) { insn = new EcmaCallargs3dyn(args[0], args[1], args[2], args[3]); break; default: - insn = new EcmaCallirangedyn(new Imm(ResultType.Int, length - 1), args); + insn = new EcmaCallirangedyn(new Imm(length - 1), args); } } else { - insn = new EcmaCallithisrangedyn(new Imm(ResultType.Int, length - 1), args); + insn = new EcmaCallithisrangedyn(new Imm(length - 1), args); } return insn; } export function newObject(args: VReg[]) { - return new EcmaNewobjdynrange(new Imm(ResultType.Int, args.length), args); + return new EcmaNewobjdynrange(new Imm(args.length), args); } export function getPropIterator() { @@ -284,11 +283,11 @@ export function createEmptyObject() { } export function createObjectHavingMethod(idx: number) { - return new EcmaCreateobjecthavingmethod(new Imm(ResultType.Int, idx)); + return new EcmaCreateobjecthavingmethod(new Imm(idx)); } export function createObjectWithBuffer(idx: number) { - return new EcmaCreateobjectwithbuffer(new Imm(ResultType.Int, idx)); + return new EcmaCreateobjectwithbuffer(new Imm(idx)); } export function setObjectWithProto(proto: VReg, object: VReg) { @@ -308,7 +307,7 @@ export function createEmptyArray() { } export function createArrayWithBuffer(idx: number) { - return new EcmaCreatearraywithbuffer(new Imm(ResultType.Int, idx)); + return new EcmaCreatearraywithbuffer(new Imm(idx)); } export function storeArraySpread(array: VReg, index: VReg) { @@ -316,11 +315,11 @@ export function storeArraySpread(array: VReg, index: VReg) { } export function defineClassWithBuffer(id: string, idx: number, parameterLength: number, env: VReg, base: VReg) { - return new EcmaDefineclasswithbuffer(id, new Imm(ResultType.Int, idx), new Imm(ResultType.Int, parameterLength), env, base); + return new EcmaDefineclasswithbuffer(id, new Imm(idx), new Imm(parameterLength), env, base); } export function createObjectWithExcludedKeys(obj: VReg, args: VReg[]) { - return new EcmaCreateobjectwithexcludedkeys(new Imm(ResultType.Int, args.length - 1), obj, args); + return new EcmaCreateobjectwithexcludedkeys(new Imm(args.length - 1), obj, args); } export function throwObjectNonCoercible() { @@ -344,7 +343,7 @@ export function closeIterator(iter: VReg) { } export function superCall(num: number, start: VReg) { - return new EcmaSupercall(new Imm(ResultType.Int, num), start); + return new EcmaSupercall(new Imm(num), start); } export function superCallSpread(vs: VReg) { @@ -388,23 +387,23 @@ export function loadHomeObject() { } export function defineFunc(name: string, env: VReg, paramLength: number) { - return new EcmaDefinefuncdyn(name, new Imm(ResultType.Int, paramLength), env); + return new EcmaDefinefuncdyn(name, new Imm(paramLength), env); } export function defineAsyncFunc(name: string, env: VReg, paramLength: number) { - return new EcmaDefineasyncfunc(name, new Imm(ResultType.Int, paramLength), env); + return new EcmaDefineasyncfunc(name, new Imm(paramLength), env); } export function defineGeneratorFunc(name: string, env: VReg, paramLength: number) { - return new EcmaDefinegeneratorfunc(name, new Imm(ResultType.Int, paramLength), env); + return new EcmaDefinegeneratorfunc(name, new Imm(paramLength), env); } export function defineNCFunc(name: string, env: VReg, paramLength: number) { - return new EcmaDefinencfuncdyn(name, new Imm(ResultType.Int, paramLength), env); + return new EcmaDefinencfuncdyn(name, new Imm(paramLength), env); } export function defineMethod(name: string, env: VReg, paramLength: number) { - return new EcmaDefinemethod(name, new Imm(ResultType.Int, paramLength), env); + return new EcmaDefinemethod(name, new Imm(paramLength), env); } export function isTrue() { @@ -416,7 +415,7 @@ export function isFalse() { } export function createRegExpWithLiteral(pattern: string, flags: number) { - return new EcmaCreateregexpwithliteral(pattern, new Imm(ResultType.Int, flags)); + return new EcmaCreateregexpwithliteral(pattern, new Imm(flags)); } export function stLetToGlobalRecord (name: string) { diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 630e52c572..f802f1302f 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -22,7 +22,6 @@ import * as path from "path"; import { execute } from "./base/util"; const ts2pandaOptions = [ - { name: 'variant-bytecode', alias: 'r', type: Boolean, defaultValue: true, description: "emit 2nd bytecode to pandafile." }, { name: 'modules', alias: 'm', type: Boolean, defaultValue: false, description: "compile as module." }, { name: 'debug-log', alias: 'l', type: Boolean, defaultValue: false, description: "show info debug log and generate the json file."}, { name: 'dump-assembly', alias: 'a', type: Boolean, defaultValue: false, description: "dump assembly to file." }, @@ -79,13 +78,6 @@ export class CmdOptions { return this.options["modules"]; } - static isVariantBytecode(): boolean { - if (!this.options) { - return true; - } - return this.options["variant-bytecode"]; - } - static getOptLevel(): number { return this.options["opt-level"]; } diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index e4dd5dc0c6..99d7568ac9 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -25,7 +25,6 @@ import { import { CompilerStatistics } from "./compilerStatistics"; import { DebugInfo } from "./debuginfo"; import { hoisting } from "./hoisting"; -import { IntrinsicExpander } from "./intrinsicExpander"; import { LOGD } from "./log"; import { setExportBinding, setImport } from "./modules"; import { PandaGen } from "./pandagen"; @@ -59,13 +58,14 @@ export class PendingCompilationUnit { * It handles all dependencies and run passes. */ export class CompilerDriver { + static isTsFile: boolean = false; private fileName: string; - private passes: Pass[]; + private passes: Pass[] = []; private compilationUnits: PandaGen[]; pendingCompilationUnits: PendingCompilationUnit[]; private functionId: number = 1; // 0 reserved for main private funcIdMap: Map = new Map(); - private statistics: CompilerStatistics; + private statistics: CompilerStatistics | undefined; private needDumpHeader: boolean = true; private ts2abcProcess: any = undefined; @@ -74,12 +74,13 @@ export class CompilerDriver { // register passes here this.passes = [ new CacheExpander(), - new IntrinsicExpander(), new RegAlloc() ]; this.compilationUnits = []; this.pendingCompilationUnits = []; - this.statistics = new CompilerStatistics(); + if (CmdOptions.showHistogramStatistics() || CmdOptions.showHoistingStatistics()) { + this.statistics = new CompilerStatistics(); + } } initiateTs2abcChildProcess() { @@ -152,6 +153,7 @@ export class CompilerDriver { } compile(node: ts.SourceFile): void { + CompilerDriver.isTsFile = CompilerDriver.isTypeScriptSourceFile(node); if (CmdOptions.showASTStatistics()) { let statics: number[] = new Array(ts.SyntaxKind.Count).fill(0); @@ -240,7 +242,7 @@ export class CompilerDriver { } if (CmdOptions.showHistogramStatistics()) { - this.statistics.getInsHistogramStatistics(pandaGen); + this.statistics!.getInsHistogramStatistics(pandaGen); } } @@ -276,7 +278,7 @@ export class CompilerDriver { this.compilationUnits.push(pandaGen); } - private isTypeScriptSourceFile(node: ts.SourceFile) { + static isTypeScriptSourceFile(node: ts.SourceFile) { let fileName = node.fileName; if (fileName && fileName.endsWith(".ts")) { return true; @@ -293,12 +295,11 @@ export class CompilerDriver { topLevelScope = new GlobalScope(node); } - let isTsFile = this.isTypeScriptSourceFile(node); - let enableTypeRecord = recordType && CmdOptions.needRecordType() && isTsFile; + let enableTypeRecord = recordType && CmdOptions.needRecordType() && CompilerDriver.isTsFile; if (enableTypeRecord) { TypeRecorder.createInstance(); } - let recorder = new Recorder(node, topLevelScope, this, enableTypeRecord, isTsFile); + let recorder = new Recorder(node, topLevelScope, this, enableTypeRecord, CompilerDriver.isTsFile); recorder.record(); addVariableToScope(recorder, enableTypeRecord); @@ -313,11 +314,11 @@ export class CompilerDriver { showStatistics(): void { if (CmdOptions.showHistogramStatistics()) { - this.statistics.printHistogram(false); + this.statistics!.printHistogram(false); } if (CmdOptions.showHoistingStatistics()) { - this.statistics.printHoistStatistics(); + this.statistics!.printHoistStatistics(); } } diff --git a/ts2panda/src/compilerStatistics.ts b/ts2panda/src/compilerStatistics.ts index 42ded9dd94..5fd1d08069 100644 --- a/ts2panda/src/compilerStatistics.ts +++ b/ts2panda/src/compilerStatistics.ts @@ -129,7 +129,7 @@ class HistogramStatistics { let part = mnemonic.split('.'); return part[2]; } - return ins.mnemonic; + return ins.getMnemonic(); } unionStatistics(histogram: HistogramStatistics): void { diff --git a/ts2panda/src/debuginfo.ts b/ts2panda/src/debuginfo.ts index 9ec81d2618..0519b3ba20 100644 --- a/ts2panda/src/debuginfo.ts +++ b/ts2panda/src/debuginfo.ts @@ -254,10 +254,12 @@ export class DebugInfo { private static matchFormat(irnode: IRNode): number { let formatIndex = 0; - for (let i = 0; i < irnode.formats[0].length; i++) { + let formats = irnode.getFormats(); + for (let i = 0; i < formats[0].length; i++) { if (irnode.operands[i] instanceof VReg) { - for (let j = 0; j < irnode.formats.length; j++) { - if ((irnode.operands[i]).num < (1 << irnode.formats[j][i].bitwidth)) { + for (let j = 0; j < formats.length; j++) { + // formats[j][i][1] is vreg’s bitwidth + if ((irnode.operands[i]).num < (1 << formats[j][i][1])) { formatIndex = j > formatIndex ? j : formatIndex; continue; } @@ -272,20 +274,20 @@ export class DebugInfo { return 0; } let length = 1; - if (!irnode.formats[0]) { + if (!irnode.getFormats()[0]) { return 0; } let formatIndex = this.matchFormat(irnode); - let formats = irnode.formats[formatIndex]; + let formats = irnode.getFormats()[formatIndex]; // count operands length for (let i = 0; i < formats.length; i++) { if ((irnode instanceof CalliDynRange) || (irnode instanceof CallRange)) { - length += formats[0].bitwidth / 8; // 8 indicates that one byte is composed of 8 bits - length += formats[1].bitwidth / 8; + length += formats[0][1] / 8; // 8 indicates that one byte is composed of 8 bits + length += formats[1][1] / 8; break; } - length += (formats[i].bitwidth / 8); + length += (formats[i][1] / 8); } return length; diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 1605c75cd9..93f4886b35 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -20,11 +20,7 @@ import { CmdOptions } from "./cmdOptions"; import { CompilerDriver } from "./compilerDriver"; import * as diag from "./diagnostic"; import * as jshelpers from "./jshelpers"; -import { LOGD, LOGE } from "./log"; -import { Pass } from "./pass"; -import { CacheExpander } from "./pass/cacheExpander"; -import { ICPass } from "./pass/ICPass"; -import { RegAlloc } from "./regAllocator"; +import { LOGE } from "./log"; import { setGlobalDeclare, setGlobalStrict } from "./strictMode"; import { TypeChecker } from "./typeChecker"; import { setPos } from "./base/util"; @@ -50,15 +46,6 @@ function generateDTs(node: ts.SourceFile, options: ts.CompilerOptions) { let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); - if (CmdOptions.isVariantBytecode()) { - LOGD("variant bytecode dump"); - let passes: Pass[] = [ - new CacheExpander(), - new ICPass(), - new RegAlloc() - ]; - compilerDriver.setCustomPasses(passes); - } compilerDriver.compile(node); compilerDriver.showStatistics(); } @@ -115,15 +102,6 @@ function main(fileNames: string[], options: ts.CompilerOptions) { let outputBinName = getOutputBinName(node); let compilerDriver = new CompilerDriver(outputBinName); setGlobalStrict(jshelpers.isEffectiveStrictModeSourceFile(node, options)); - if (CmdOptions.isVariantBytecode()) { - LOGD("variant bytecode dump"); - let passes: Pass[] = [ - new CacheExpander(), - new ICPass(), - new RegAlloc() - ]; - compilerDriver.setCustomPasses(passes); - } compilerDriver.compile(node); compilerDriver.showStatistics(); return node; diff --git a/ts2panda/src/intrinsicExpander.ts b/ts2panda/src/intrinsicExpander.ts deleted file mode 100644 index cefb3c22b0..0000000000 --- a/ts2panda/src/intrinsicExpander.ts +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AssemblyDumper, IntrinsicInfo } from "./assemblyDumper"; -import { DebugInfo } from "./debuginfo"; -import { - Call, - CallRange, - CallShort, - FldaiDyn, - Imm, - Intrinsic, - IRNode, - LdaiDyn, - LdaStr, - OperandKind, - ResultDst, - ResultType, - StaDyn, - VReg -} from "./irnodes"; -import { PandaGen } from "./pandagen"; -import { Pass } from "./pass"; - -export class IntrinsicExpanderInternal { - private temps: VReg[] = []; - - getTemp(): VReg { - if (this.temps.length > 0) { - return this.temps.pop()!; - } else { - return new VReg(); - } - } - - freeTemps(temps: VReg[]) { - this.temps = this.temps.concat(temps); - } - - // this method records the intrinsic usage during the whole source code - // it can help dumper to write the intrinsic function declaration in the front of bytecode - intrinsicDeclRec(ins: Intrinsic) { - let intrinsicName = ins.mnemonic; - let argsNum = ins.operands.length; - let resultType: string = ""; - if (ins.resultIn() == ResultDst.None) { - resultType = "void"; - } else if (ins.resultIn() == ResultDst.Acc) { - resultType = "any"; - } else { - throw new Error("resultType of" + ins.resultIn() + "is not implement"); - } - let intrinsicInfo = new IntrinsicInfo(intrinsicName, argsNum, resultType); - AssemblyDumper.intrinsicRec.set(ins.mnemonic, intrinsicInfo); - } - - // Transforms a synthetic "intrinsic instruction" into an intrinsic function call. - // Returns an array of instructions forming intrinsic call and - // an array of temporary registers used for expansion. - expandInstruction(ins: Intrinsic): [IRNode[], VReg[]] { - let operands = ins.operands; - let formats = ins.formats; - let expansion: IRNode[] = []; - let callArgs: VReg[] = []; - let tempVregs: VReg[] = []; - - let intrinsicName = "Ecmascript.Intrinsics." + ins.mnemonic; - - // Walk the rest of the arguments. - for (let i = 0; i < operands.length; ++i) { - let format = formats[0]; - let kind: OperandKind; - kind = format[i].kind; - - let operand = operands[i]; - - if (kind === OperandKind.SrcVReg) { - callArgs.push(operand); - continue; - } - - // Imm has to be put into a vreg to be passed to intrinsic. - // for defineFuncDyn - if (kind === OperandKind.Imm) { - let tempImm: VReg = this.getTemp(); - let imm = operand; - let type = imm.resultType(); - if (type == ResultType.Int || type == ResultType.Long) { - expansion.push(new LdaiDyn(imm)); - } else if (type == ResultType.Float) { - expansion.push(new FldaiDyn(imm)); - } else { - throw new Error("Unexpected result type for an Imm"); - } - expansion.push(new StaDyn(tempImm)); - callArgs.push(tempImm); - tempVregs.push(tempImm); - continue; - } - - // Put id into vreg as a string object. - if (kind === OperandKind.Id) { - let tempId: VReg = this.getTemp(); - expansion.push(new LdaStr(operand)); - expansion.push(new StaDyn(tempId)); - callArgs.push(tempId); - tempVregs.push(tempId); - continue; - } - - // For simplicity, intrinsics shall not have destinations other than accumulator. - // Also, no labels are allowed as operands. - if (kind === OperandKind.DstVReg - || kind === OperandKind.SrcDstVReg - || ins.resultIn() === ResultDst.VReg) { - throw new Error("Intrinsic " + ins.mnemonic + " has unexpected operand kinds"); - } else { - throw new Error("Unknown operand kind for intrinsic " + ins.mnemonic); - } - } - - // Call the intrinsic. - switch (callArgs.length) { - case 0: - expansion.push(new CallShort(intrinsicName)); - break; - case 1: - expansion.push(new CallShort(intrinsicName, callArgs[0])); - break; - case 2: - expansion.push(new CallShort(intrinsicName, callArgs[0], callArgs[1])); - break; - case 3: - expansion.push(new Call(intrinsicName, callArgs[0], callArgs[1], callArgs[2])); - break; - case 4: - expansion.push(new Call(intrinsicName, callArgs[0], callArgs[1], callArgs[2], callArgs[3])); - break; - default: - expansion.push(new CallRange(intrinsicName, callArgs)); - } - return [expansion, tempVregs]; - } - - run(pg: PandaGen): void { - let insns: IRNode[] = pg.getInsns(); - let origTemps: VReg[] = pg.getTemps(); - - for (let i = 0; i < insns.length; ++i) { - let ins: IRNode = insns[i]; - if (ins instanceof Intrinsic) { - // record the intrinsic - if (!AssemblyDumper.intrinsicRec.has(ins.mnemonic)) { - this.intrinsicDeclRec(ins); - } - - let [expansion, temps] = this.expandInstruction(ins); - - // for debuginfo - DebugInfo.copyDebugInfo(insns[i], expansion); - - insns.splice(i, 1, ...expansion); - // Since we put something into the original array, its length changed. - // Skip what we've just added. - let step = expansion.length - 1; - i += step; - - this.freeTemps(temps); - } - } - // We need extra registers in the function. - origTemps.push(...this.temps); - } -} -export class IntrinsicExpander implements Pass { - run(pg: PandaGen): void { - let intrinsicExpanderInternal = new IntrinsicExpanderInternal(); - intrinsicExpanderInternal.run(pg); - } -} diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 11ab6c78d4..a40bbe240d 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -110,7 +110,6 @@ import { getVregisterCache, VregisterCache } from "./base/vregisterCache"; -import { CmdOptions } from "./cmdOptions"; import { DebugInfo, NodeKind, @@ -164,7 +163,6 @@ import { IRNode, Jeqz, Label, - ResultType, ReturnDyn, VReg } from "./irnodes"; @@ -203,7 +201,6 @@ export class PandaGen { private firstStmt: ts.Statement | undefined; private sourceFileDebugInfo: string = ""; private sourceCodeDebugInfo: string | undefined; - private icSize: number = 0; private callType: number = 0; private static literalArrayBuffer: Array = new Array(); @@ -277,14 +274,6 @@ export class PandaGen { } } - getICSize() { - return this.icSize; - } - - setICSize(total: number) { - this.icSize = total; - } - static appendTypeArrayBuffer(type: BaseType): number { let index = PandaGen.literalArrayBuffer.length; PandaGen.literalArrayBuffer.push(type.transfer2LiteralBuffer()); @@ -349,20 +338,10 @@ export class PandaGen { retval = new VReg(); } - if (CmdOptions.isEnableDebugLog()) { - if (retval.getStackTrace() !== undefined) { - throw new Error("stack trace of new temp register is not empty"); - } - retval.setStackTrace(); - } return retval; } freeTemps(...temps: VReg[]) { - if (CmdOptions.isEnableDebugLog()) - for (let value of temps) - value.setStackTrace(null); - this.temps.unshift(...temps); } @@ -1012,7 +991,7 @@ export class PandaGen { } copyRestArgs(node: ts.Node, index: number) { - this.add(node, new EcmaCopyrestargs(new Imm(ResultType.Int, index))); + this.add(node, new EcmaCopyrestargs(new Imm(index))); } getPropIterator(node: ts.Node) { @@ -1299,6 +1278,6 @@ export class PandaGen { // set pos debug info if debug mode DebugInfo.setDebuginfoForIns(node, ...insns); - this.insns = this.insns.concat(insns); + this.insns.push(...insns); } } diff --git a/ts2panda/src/pass/ICPass.ts b/ts2panda/src/pass/ICPass.ts deleted file mode 100644 index e05499f05c..0000000000 --- a/ts2panda/src/pass/ICPass.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - Intrinsic, IRNode -} from "../irnodes"; -import { LOGE } from "../log"; -import { PandaGen } from "../pandagen"; -import { Pass } from "../pass"; - -class ICPassImpl { - constructor() { } - - run(pg: PandaGen): void { - let insns: IRNode[] = pg.getInsns(); - let icSize: number = 0; - - for (let i = 0; i < insns.length; ++i) { - if (!(insns[i] instanceof Intrinsic)) { - continue; - } - - let ins: Intrinsic = (insns[i]); - if (!ins.hasIC()) { - continue; - } - - icSize = ins.updateICOffset(icSize); - } - - if (icSize >= 0xFFFF) { - LOGE("ICPass: <" + pg.internalName + "> slot size overflow! total:" + icSize); - } - pg.setICSize(icSize); - } -} - -export class ICPass implements Pass { - run(pg: PandaGen): void { - let icPass = new ICPassImpl(); - icPass.run(pg); - } -} \ No newline at end of file diff --git a/ts2panda/src/regAllocator.ts b/ts2panda/src/regAllocator.ts index 0b59d968dd..985262132e 100644 --- a/ts2panda/src/regAllocator.ts +++ b/ts2panda/src/regAllocator.ts @@ -107,7 +107,7 @@ class RegAllocator { let num = 0; for (let j = 0; j < operands.length; ++j) { if (operands[j] instanceof VReg) { - if ((operands[j]).num >= (1 << format[j].bitwidth)) { + if ((operands[j]).num >= (1 << format[j][1])) { num++; } } @@ -135,22 +135,22 @@ class RegAllocator { for (let j = 0; j < operands.length; ++j) { if (operands[j] instanceof VReg) { let vOrigin = operands[j]; - if (vOrigin.num >= (1 << format[j].bitwidth)) { + if (vOrigin.num >= (1 << format[j][1])) { let spill = this.allocSpill(); spills.push(spill); let vTmp; try { - vTmp = this.findTmpVreg(1 << format[j].bitwidth); + vTmp = this.findTmpVreg(1 << format[j][1]); } catch { throw Error("no available tmp vReg"); } head.push(new MovDyn(spill, vTmp)); operands[j] = vTmp; - if (format[j].kind == OperandKind.SrcVReg) { + if (format[j][0] == OperandKind.SrcVReg) { head.push(new MovDyn(vTmp, vOrigin)); - } else if (format[j].kind == OperandKind.DstVReg) { + } else if (format[j][0] == OperandKind.DstVReg) { tail.push(new MovDyn(vOrigin, vTmp)) - } else if (format[j].kind == OperandKind.SrcDstVReg) { + } else if (format[j][0] == OperandKind.SrcDstVReg) { head.push(new MovDyn(vTmp, vOrigin)); tail.push(new MovDyn(vOrigin, vTmp)) } else { @@ -178,7 +178,7 @@ class RegAllocator { checkDynRangeInstruction(irNodes: IRNode[], index: number): boolean { let operands = irNodes[index].operands; let rangeRegOffset = getRangeStartVregPos(irNodes[index]); - let level = 1 << irNodes[index].formats[0][rangeRegOffset].bitwidth; + let level = 1 << (irNodes[index].getFormats())[0][rangeRegOffset][1]; /* 1. "CalliDynRange 4, v255" is a valid insn, there is no need for all 4 registers numbers to be less than 255, @@ -221,7 +221,7 @@ class RegAllocator { let rangeRegOffset = getRangeStartVregPos(irNodes[index]); let regNums = operands.length - getRangeStartVregPos(irNodes[index]); - let level = 1 << irNodes[index].formats[0][rangeRegOffset].bitwidth; + let level = 1 << (irNodes[index].getFormats())[0][rangeRegOffset][1]; let tmp = this.findTmpVreg(level); for (let i = 0; i < regNums; i++) { @@ -252,7 +252,7 @@ class RegAllocator { adjustInstructionsIfNeeded(irNodes: IRNode[]): void { for (let i = 0; i < irNodes.length; ++i) { let operands = irNodes[i].operands; - let formats = irNodes[i].formats; + let formats = irNodes[i].getFormats(); if (isRangeInst(irNodes[i])) { if (this.checkDynRangeInstruction(irNodes, i)) { continue; diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 3793512593..34069c20e3 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -40,6 +40,7 @@ import { getRangeStartVregPos } from "./base/util"; import { LiteralBuffer } from "./base/literal"; +import { CompilerDriver } from "./compilerDriver"; const dollarSign: RegExp = /\$/g; @@ -204,33 +205,39 @@ export class Ts2Panda { let sourceFile = pg.getSourceFileDebugInfo(); let callType = pg.getCallType(); let typeRecord = pg.getLocals(); - let typeInfo = new Array(); - typeRecord.forEach((vreg) => { - typeInfo.push(vreg.getTypeIndex()); - if (CmdOptions.enableTypeLog()) { - console.log("---------------------------------------"); - console.log("- vreg name:", vreg.getVariableName()); - console.log("- vreg local num:", vreg.num); - console.log("- vreg type:", vreg.getTypeIndex()); - } - }); - - let exportedTypes = PandaGen.getExportedTypes(); - let exportedSymbol2Types = exportedTypes.size == 0 ? undefined : new Array(); - if (funcName == "func_main_0") { - exportedTypes.forEach((type: number, symbol: string) => { - let exportedSymbol2Type = new ExportedSymbol2Type(symbol, type); - exportedSymbol2Types!.push(exportedSymbol2Type); - }) - } + let typeInfo = undefined; + let exportedSymbol2Types: undefined | Array = undefined; + let declaredSymbol2Types: undefined | Array = undefined; + if (CmdOptions.needRecordType() && CompilerDriver.isTsFile) { + typeInfo = new Array(); + typeRecord.forEach((vreg) => { + typeInfo.push(vreg.getTypeIndex()); + if (CmdOptions.enableTypeLog()) { + console.log("---------------------------------------"); + console.log("- vreg name:", vreg.getVariableName()); + console.log("- vreg local num:", vreg.num); + console.log("- vreg type:", vreg.getTypeIndex()); + } + }); - let declareddTypes = PandaGen.getDeclaredTypes(); - let declaredSymbol2Types = declareddTypes.size == 0 ? undefined : new Array(); - if (funcName == "func_main_0") { - declareddTypes.forEach((type: number, symbol: string) => { - let declaredSymbol2Type = new DeclaredSymbol2Type(symbol, type); - declaredSymbol2Types!.push(declaredSymbol2Type); - }) + if (funcName == "func_main_0") { + let exportedTypes = PandaGen.getExportedTypes(); + let declareddTypes = PandaGen.getDeclaredTypes(); + if (exportedTypes.size != 0) { + exportedSymbol2Types = new Array(); + exportedTypes.forEach((type: number, symbol: string) => { + let exportedSymbol2Type = new ExportedSymbol2Type(symbol, type); + exportedSymbol2Types.push(exportedSymbol2Type); + }); + } + if (declareddTypes.size != 0) { + declaredSymbol2Types = new Array(); + declareddTypes.forEach((type: number, symbol: string) => { + let declaredSymbol2Type = new DeclaredSymbol2Type(symbol, type); + declaredSymbol2Types.push(declaredSymbol2Type); + }); + } + } } let variables, sourceCode; diff --git a/ts2panda/templates/irnodes.ts.erb b/ts2panda/templates/irnodes.ts.erb index 4ebb71f3c0..19b5f1029a 100755 --- a/ts2panda/templates/irnodes.ts.erb +++ b/ts2panda/templates/irnodes.ts.erb @@ -14,7 +14,159 @@ % def get_node_kind(mnemonic) % return "#{mnemonic.gsub('.', '_').upcase}" % end - +% +% def insn2node(insn) +% mnemonic = insn.mnemonic.split('.') +% return mnemonic.map{|el| el == '64' ? 'Wide' : el.capitalize}.join() +% end +% +% def get_result_type(insn) +% if insn.mnemonic.start_with? "call" +% return "ResultType.Unknown" +% end +% case insn.dtype +% when 'i32' +% return "ResultType.Int" +% when 'i64', 'b64' +% return "ResultType.Long" +% when 'f64' +% return "ResultType.Float" +% when 'obj' +% return "ResultType.Obj" +% else +% return "ResultType.None" +% end +% end +% +% def get_result_dst(insn) +% if insn.properties.include? "acc_write" +% return "ResultDst.Acc" +% end +% dst_operands = insn.operands.select { |op| op.dst? } +% if dst_operands.length > 0 and dst_operands[0].reg? +% return "ResultDst.VReg" +% end +% return "ResultDst.None" +% end +% +% def is_VReg(name) +% if name == :v +% return true +% end +% end +% +% def is_Acc(name) +% if name == :acc +% return true +% end +% end +% +% def is_Imm(name) +% if name == :imm +% return true +% end +% end +% +% def is_Id(name) +% if %i[method_id type_id field_id string_id literalarray_id callsite_id].include?(name) +% return true +% end +% end +% +% def is_Call(insn) +% if insn.mnemonic.start_with? "call" +% return true +% end +% return false +% end +% +% def is_CallRange(insn) +% if insn.mnemonic == "call.range" or insn.mnemonic == "calli.dyn.range" or insn.mnemonic == "ecma.callirangedyn" or insn.mnemonic == "ecma.callithisrangedyn" or insn.mnemonic == "ecma.createobjectwithexcludedkeys" or insn.mnemonic == "ecma.newobjdynrange" +% return true +% end +% return false +% end +% +% def get_operand_type(name, insn) +% if is_VReg(name) +% return "VReg" +% elsif is_Imm(name) +% is_jump = insn.properties.include? 'jump' +% return is_jump ? "Label" : "Imm" +% elsif is_Id(name) +% return "string" +% else +% return nil +% end +% end +% +% def get_operands(sig) +% return [] unless sig.include? ' ' +% _, operands = sig.match(/(\S+) (.+)/).captures +% operands = operands.split(', ') +% end +% +% def get_ctor_args(insn) +% operands = get_operands(insn.sig) +% ops = Array.new +% ctor_args = Array.new +% operands.map do |operand| +% operand_parts = operand.split(':') +% case operand_parts.size +% when 1 +% name = operand_parts[0] +% when 2 +% name, _ = operand_parts +% when 3 +% name, _, _ = operand_parts +% else +% raise 'Unexpected operand string' +% end +% ops.push(name) +% name_tmp = name.to_s.gsub(/[0-9]/, '').to_sym +% type = get_operand_type(name_tmp,insn) +% if is_Call(insn) and !is_CallRange(insn) and is_VReg(name_tmp) and !insn.mnemonic.include?('acc') +% ctor_args.push("#{name}?: #{type}") +% else +% ctor_args.push("#{name}: #{type}") +% end +% end +% return ops,ctor_args +% end +% +% def get_operand_kind(op, insn) +% if op.reg? +% if op.src? and op.dst? +% return 2 +% elsif op.src? +% return 0 +% elsif op.dst? +% return 1 +% end +% return nil +% elsif op.imm? +% is_jump = insn.properties.include? 'jump' +% return is_jump ? 6 : 3 +% elsif op.id? +% is_string_id = insn.properties.include? 'string_id' +% return is_string_id ? 5 : 4 +% else +% return nil +% end +% end +% +% def make_format(fmt, insn) +% operands = fmt.operands.map {|op| "[#{get_operand_kind(op, insn)}, #{op.width}]"} +% return "[" + operands.join(", ") + "]" +% end +% +% def get_parent_type(insn) +% if insn.prefix != nil and insn.prefix.name == "ecma" +% return "Intrinsic" +% else +% return "IRNode" +% end +% end // Autogenerated file -- DO NOT EDIT! import * as ts from "typescript"; import { @@ -88,7 +240,7 @@ export type OperandType = VReg | Imm | Label | string | number export enum OperandKind { // the least significant bit indicates vreg // the second bit indicates src or dst - SrcVReg, DstVReg, SrcDstVReg, Imm, Id, StringId, Label + SrcVReg = 0, DstVReg, SrcDstVReg, Imm, Id, StringId, Label } export namespace OperandKind { @@ -98,32 +250,52 @@ export namespace OperandKind { } } -export class FormatItem { - constructor( - readonly kind: OperandKind, - readonly bitwidth: number, - ) {} +export type Format = number[][] + +export function getInsnMnemonic(opcode: IRNodeKind): string { + switch(opcode) { +% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group| +% node_kind = get_node_kind(mnemonic) +% kind = "IRNodeKind." + node_kind + case <%= kind %>: + return "<%= mnemonic %>"; +% end + default: + return ''; + } } -export type Format = FormatItem[] +export function getInsnFormats(opcode: IRNodeKind) { + switch(opcode) { +% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group| +% insn = group.first +% formats = group.map {|i| make_format(i,insn) } +% node_kind = get_node_kind(mnemonic) +% kind = "IRNodeKind." + node_kind + case <%= kind %>: { + return [ + <%= formats.join(",\n ") %> + ]; + } +% end + default: + return []; + } +} export abstract class IRNode { private node: ts.Node | NodeKind = NodeKind.Normal; constructor( readonly kind: IRNodeKind, - readonly mnemonic: string, readonly operands: OperandType[], - readonly formats: Format[] ) {} // for debuginfo public debugPosInfo: DebugPosInfo = new DebugPosInfo(); - abstract resultType(): ResultType; - abstract resultIn(): ResultDst; - toString(): string { - let out = this.mnemonic + "\t"; - if (this.mnemonic.length < 8) { + let mnemonic = this.getMnemonic(); + let out = mnemonic + "\t"; + if (mnemonic.length < 8) { out += "\t"; } @@ -147,128 +319,64 @@ export abstract class IRNode { return "undefined"; } + + getMnemonic() { + return getInsnMnemonic(this.kind); + } + + getFormats() { + return getInsnFormats(this.kind); + } } export abstract class Intrinsic extends IRNode { - slotSize: number = 0; constructor( readonly kind: IRNodeKind, - readonly mnemonic: string, readonly operands: OperandType[], - readonly formats: Format[] ) { - super(kind, mnemonic, operands, formats); + super(kind, operands); } toString(): string { return super.toString() + " [i]"; } - - hasIC(): boolean { - return this.slotSize > 0; - } - - // @ts-ignore - updateICOffset(base: number): number {return 0}; - - validateIC(offset: number, slotSize: number): number { - let end = offset + slotSize; - if (end > 0xFFFF) { - return 0xFFFF; - } else { - return offset; - } - } } export class VReg { - private static global_id = 0; - private typeIndex: number = 0; - private variableName: string = ""; - readonly id: number; // used for debug purpose to distinguish one instance from another num: number = -1; - // for debug purposes - private stacktrace: (undefined | string); - toString(): string { - if (this.num != -1) { return "V" + this.num; - } else { - return "L" + this.id; - } } constructor() { - this.id = VReg.global_id++; - - // for debug purposes - this.setStackTrace(null); - } - - // for debug purposes - getStackTrace(): (undefined | string) { - return this.stacktrace; - } - - setStackTrace(stack?: null): void { - if (stack === undefined) { - let error = new Error(); - let trace = error.stack; - - this.stacktrace = trace; - return; - } - - if (stack === null) { - this.stacktrace = undefined; - return; - } } getTypeIndex() { - return this.typeIndex; + return 0; } + // @ts-ignore setTypeIndex(typeIndex: number) { - this.typeIndex = typeIndex; } getVariableName() { - return this.variableName; + return ''; } + // @ts-ignore setVariableName(variableName: string) { - this.variableName = variableName; } } export class Imm extends IRNode { - private type: ResultType; readonly value: number; - constructor(type: ResultType, value: number) { - super(IRNodeKind.IMM, "", [], []); - this.type = type; + constructor(value: number) { + super(IRNodeKind.IMM, []); this.value = value; } - static zero(): Imm { - return new Imm(ResultType.Int, 0); - } - - static one(): Imm { - return new Imm(ResultType.Int, 1); - } - - resultType(): ResultType { - return this.type; - } - - resultIn(): ResultDst { - return ResultDst.None; - } - toString(): string { return "#" + this.value; } @@ -276,21 +384,13 @@ export class Imm extends IRNode { export class Label extends IRNode { private static global_id = 0; - readonly id: number; // used for debug purpose to distinguish one instance from another + readonly id: number; constructor() { - super(IRNodeKind.LABEL, "", [], []); + super(IRNodeKind.LABEL, []); this.id = Label.global_id++; } - resultType(): ResultType { - return ResultType.None; - } - - resultIn(): ResultDst { - return ResultDst.None; - } - toString(): string { return "LABEL_" + this.id; } @@ -298,170 +398,10 @@ export class Label extends IRNode { export class DebugInsPlaceHolder extends IRNode { constructor() { - super(IRNodeKind.VIRTUALINS_DYN, "", [], []); - } - - resultType(): ResultType { - return ResultType.None; - } - - resultIn(): ResultDst { - return ResultDst.None; + super(IRNodeKind.VIRTUALINS_DYN, []); } } -% def insn2node(insn) -% mnemonic = insn.mnemonic.split('.') -% return mnemonic.map{|el| el == '64' ? 'Wide' : el.capitalize}.join() -% end -% -% def get_result_type(insn) -% if insn.mnemonic.start_with? "call" -% return "ResultType.Unknown" -% end -% case insn.dtype -% when 'i32' -% return "ResultType.Int" -% when 'i64', 'b64' -% return "ResultType.Long" -% when 'f64' -% return "ResultType.Float" -% when 'obj' -% return "ResultType.Obj" -% else -% return "ResultType.None" -% end -% end -% -% def get_result_dst(insn) -% if insn.properties.include? "acc_write" -% return "ResultDst.Acc" -% end -% dst_operands = insn.operands.select { |op| op.dst? } -% if dst_operands.length > 0 and dst_operands[0].reg? -% return "ResultDst.VReg" -% end -% return "ResultDst.None" -% end -% -% def is_VReg(name) -% if name == :v -% return true -% end -% end -% -% def is_Acc(name) -% if name == :acc -% return true -% end -% end -% -% def is_Imm(name) -% if name == :imm -% return true -% end -% end -% -% def is_Id(name) -% if %i[method_id type_id field_id string_id literalarray_id callsite_id].include?(name) -% return true -% end -% end -% -% def is_Call(insn) -% if insn.mnemonic.start_with? "call" -% return true -% end -% return false -% end -% -% def is_CallRange(insn) -% if insn.mnemonic == "call.range" or insn.mnemonic == "calli.dyn.range" or insn.mnemonic == "ecma.callirangedyn" or insn.mnemonic == "ecma.callithisrangedyn" or insn.mnemonic == "ecma.createobjectwithexcludedkeys" or insn.mnemonic == "ecma.newobjdynrange" -% return true -% end -% return false -% end -% -% def get_operand_type(name, insn) -% if is_VReg(name) -% return "VReg" -% elsif is_Imm(name) -% is_jump = insn.properties.include? 'jump' -% return is_jump ? "Label" : "Imm" -% elsif is_Id(name) -% return "string" -% else -% return nil -% end -% end -% -% def get_operands(sig) -% return [] unless sig.include? ' ' -% _, operands = sig.match(/(\S+) (.+)/).captures -% operands = operands.split(', ') -% end -% -% def get_ctor_args(insn) -% operands = get_operands(insn.sig) -% ops = Array.new -% ctor_args = Array.new -% operands.map do |operand| -% operand_parts = operand.split(':') -% case operand_parts.size -% when 1 -% name = operand_parts[0] -% when 2 -% name, _ = operand_parts -% when 3 -% name, _, _ = operand_parts -% else -% raise 'Unexpected operand string' -% end -% ops.push(name) -% name_tmp = name.to_s.gsub(/[0-9]/, '').to_sym -% type = get_operand_type(name_tmp,insn) -% if is_Call(insn) and !is_CallRange(insn) and is_VReg(name_tmp) and !insn.mnemonic.include?('acc') -% ctor_args.push("#{name}?: #{type}") -% else -% ctor_args.push("#{name}: #{type}") -% end -% end -% return ops,ctor_args -% end -% -% def get_operand_kind(op, insn) -% if op.reg? -% if op.src? and op.dst? -% return "OperandKind.SrcDstVReg" -% elsif op.src? -% return "OperandKind.SrcVReg" -% elsif op.dst? -% return "OperandKind.DstVReg" -% end -% return nil -% elsif op.imm? -% is_jump = insn.properties.include? 'jump' -% return is_jump ? "OperandKind.Label" : "OperandKind.Imm" -% elsif op.id? -% is_string_id = insn.properties.include? 'string_id' -% return is_string_id ? "OperandKind.StringId" : "OperandKind.Id" -% else -% return nil -% end -% end -% -% def make_format(fmt, insn) -% operands = fmt.operands.map {|op| "new FormatItem(#{get_operand_kind(op, insn)}, #{op.width})"} -% return "[" + operands.join(", ") + "]" -% end -% -% def get_parent_type(insn) -% if insn.prefix != nil and insn.prefix.name == "ecma" -% return "Intrinsic" -% else -% return "IRNode" -% end -% end % Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group| % insn = group.first % jump = insn.properties.include? 'jump' @@ -470,7 +410,6 @@ export class DebugInsPlaceHolder extends IRNode { % ops_list,ctor_arg_list = get_ctor_args(insn) % ctor_args = ctor_arg_list.map {|arg| "#{arg}"}.join(", ") % ops = ops_list.map { |op| "#{op}"}.join(", ") -% formats = group.map {|i| make_format(i,insn) } % result_type = get_result_type(insn) % result_dst = get_result_dst(insn); % is_call_op = is_Call(insn) @@ -511,28 +450,20 @@ export class <%= insn2node(insn) %> extends <%=parent_type %> { % end super( <%= kind %>, - "<%= insn.mnemonic %>", % if is_call_op or is_callrange_op or insn2node(insn) == "BuiltinR2i" operands, % else - [<%= ops %>], + [<%= ops %>] % end - [ - <%= formats.join(",\n ") %> - ] ); } - resultType(): ResultType { - return <%= result_type %>; - } - resultIn(): ResultDst { - return <%= result_dst %>; - } % if jump % target_index = insn.operands.index {|op| op.imm? } + getTarget(): Label { return