diff --git a/test262/config.py b/test262/config.py index c521b973dd530584ae87c384f91dde836def4731..f053ac961e47efc2a3a1a1632a4e29275f023327 100755 --- a/test262/config.py +++ b/test262/config.py @@ -78,6 +78,12 @@ ARK_FRONTEND_LIST = [ ] DEFAULT_ARK_FRONTEND = ARK_FRONTEND_LIST[0] +ARK_ARCH_LIST = [ + "x64", + "aarch64", + "arm" +] +DEFAULT_ARK_ARCH = ARK_ARCH_LIST[0] MODULE_FILES_LIST = [ "early-dup-export-decl.js", diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 97752ef074164566fb3186cad224d9c84d6cc53e..9d958b1c25be6d7a380cddf4e73e70ae81366187 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -41,6 +41,15 @@ def parse_args(): parser.add_argument('--ark-frontend', nargs='?', choices=ARK_FRONTEND_LIST, type=str, help="Choose one of them") + parser.add_argument('--ark-arch', + default=DEFAULT_ARK_ARCH, + required=False, + nargs='?', choices=ARK_ARCH_LIST, type=str, + help="Choose one of them") + parser.add_argument('--ark-arch-root', + default=DEFAULT_ARK_ARCH, + required=False, + help="the root path for qemu-aarch64 or qemu-arm") arguments = parser.parse_args() return arguments @@ -51,6 +60,7 @@ ARK_TOOL = DEFAULT_ARK_TOOL ARK_FRONTEND_TOOL = DEFAULT_ARK_FRONTEND_TOOL LIBS_DIR = DEFAULT_LIBS_DIR ARK_FRONTEND = DEFAULT_ARK_FRONTEND +ARK_ARCH = DEFAULT_ARK_ARCH def output(retcode, msg): @@ -59,6 +69,8 @@ def output(retcode, msg): print(str(msg)) elif retcode == -6: sys.stderr.write("Aborted (core dumped)") + elif retcode == -4: + sys.stderr.write("Aborted (core dumped)") elif retcode == -11: sys.stderr.write("Segmentation fault (core dumped)") elif msg != '': @@ -115,6 +127,8 @@ class ArkProgram(): self.libs_dir = LIBS_DIR self.ark_frontend = ARK_FRONTEND self.js_file = "" + self.arch = ARK_ARCH + self.arch_root = "" def proce_parameters(self): if self.args.ark_tool: @@ -131,6 +145,10 @@ class ArkProgram(): self.js_file = self.args.js_file + self.arch = self.args.ark_arch + + self.arch_root = self.args.ark_arch_root + def gen_abc(self): js_file = self.js_file file_name_pre = os.path.splitext(js_file)[0] @@ -158,9 +176,25 @@ class ArkProgram(): os.environ["LD_LIBRARY_PATH"] = self.libs_dir file_name_pre = os.path.splitext(self.js_file)[0] + cmd_args = [] + if self.arch == ARK_ARCH_LIST[1]: + qemu_tool = "qemu-aarch64" + qemu_arg1 = "-L" + qemu_arg2 = self.arch_root + cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool, + ARK_ARGS, ICU_PATH, + f'{file_name_pre}.abc'] + elif self.arch == ARK_ARCH_LIST[2]: + qemu_tool = "qemu-arm" + qemu_arg1 = "-L" + qemu_arg2 = self.arch_root + cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool, + ARK_ARGS, ICU_PATH, + f'{file_name_pre}.abc'] + elif self.arch == ARK_ARCH_LIST[0]: + cmd_args = [self.ark_tool, ARK_ARGS, ICU_PATH, + f'{file_name_pre}.abc'] - cmd_args = [self.ark_tool, ARK_ARGS, ICU_PATH, - f'{file_name_pre}.abc'] retcode = exec_command(cmd_args) return retcode diff --git a/test262/run_test262.py b/test262/run_test262.py index 663fca577e97703d42246a226f6e9cc3da241226..014c45062e97b564af32fd837e5b5a8c17303d27 100755 --- a/test262/run_test262.py +++ b/test262/run_test262.py @@ -72,6 +72,13 @@ def parse_args(): parser.add_argument('--ark-frontend', nargs='?', choices=ARK_FRONTEND_LIST, type=str, help="Choose one of them") + parser.add_argument('--ark-arch', + default=DEFAULT_ARK_ARCH, + nargs='?', choices=ARK_ARCH_LIST, type=str, + help="Choose one of them") + parser.add_argument('--ark-arch-root', + default=DEFAULT_ARK_ARCH, + help="the root path for qemu-aarch64 or qemu-arm") return parser.parse_args() @@ -388,6 +395,7 @@ def get_host_args(args, host_type): ark_frontend_tool = DEFAULT_ARK_FRONTEND_TOOL libs_dir = DEFAULT_LIBS_DIR ark_frontend = DEFAULT_ARK_FRONTEND + ark_arch = DEFAULT_ARK_ARCH if args.hostArgs: host_args = args.hostArgs @@ -411,6 +419,10 @@ def get_host_args(args, host_type): host_args += f"--libs-dir={libs_dir} " host_args += f"--ark-frontend={ark_frontend} " + if args.ark_arch != ark_arch: + host_args += f"--ark-arch={args.ark_arch} " + host_args += f"--ark-arch-root={args.ark_arch_root} " + return host_args diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index fcde4bc32fb482da88e9743670732de1d4acc77d..80e0055ff0c598e7bebd0a0ef46549a25449bf45 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -305,6 +305,11 @@ ohos_copy("panda_ts2abc_ets") { module_install_name = "" } +ohos_copy("ts2abc_js_file") { + sources = [ "${ts2abc_root}/scripts/ts2abc.js" ] + outputs = [ target_out_dir + "/{{source_file_part}}" ] +} + group("ark_ts2abc_build") { deps = [] if (host_os != "mac") { @@ -312,6 +317,11 @@ group("ark_ts2abc_build") { "${ts2abc_root}:ts2abc_build(${buildtool_linux})", "${ts2abc_root}:ts2abc_build_ets(${buildtool_linux})", ] + } else { + deps += [ + "${ts2abc_root}:ts2abc_build_mac(${buildtool_mac})", + "${ts2abc_root}:ts2abc_build_mac_ets(${buildtool_mac})", + ] } } diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index 8ecc7a1d3fcf59e2b3bad1383a79e4c53e8a7dd8..c9f59db1642319cf47242a3e007076d922141e05 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -25,8 +25,6 @@ import { FuncDecl, InitStatus, LetDecl, - ModDecl, - ModuleScope, Scope, VarDecl, VariableScope @@ -109,11 +107,6 @@ export function addVariableToScope(recorder: Recorder) { scope.add(decl.name, VarDeclarationKind.FUNCTION); } else if (decl instanceof CatchParameter) { scope.add(decl.name, VarDeclarationKind.LET); - } else if (decl instanceof ModDecl) { - if (!(scope instanceof ModuleScope)) { - throw new Error("ModuleVariable can't exist without ModuleScope"); - } - scope.add(decl.name, VarDeclarationKind.MODULE); } else if (decl instanceof ClassDecl) { let classNode = decl.node; if (ts.isClassDeclaration(classNode)) { diff --git a/ts2panda/src/base/builtIn.ts b/ts2panda/src/base/builtIn.ts index 61afcb3ecd16faeadb422b6b1fe6a0653bed2a15..160b5f9d2a961ffbc2ba182b0fc64dc61772ead9 100755 --- a/ts2panda/src/base/builtIn.ts +++ b/ts2panda/src/base/builtIn.ts @@ -25,7 +25,8 @@ import { EcmaLdsymbol, EcmaLdtrue, EcmaLdundefined, - StaDyn + StaDyn, + EcmaLdfunction } from "../irnodes"; import { CacheList, getVregisterCache } from "./vregisterCache"; @@ -99,4 +100,12 @@ export function expandFalse(pandaGen: PandaGen): IRNode[] { new EcmaLdfalse(), new StaDyn(vreg) ]; +} + +export function expandFunc(pandaGen: PandaGen): IRNode[] { + let vreg = getVregisterCache(pandaGen, CacheList.FUNC); + return [ + new EcmaLdfunction(), + new StaDyn(vreg) + ]; } \ No newline at end of file diff --git a/ts2panda/src/base/vregisterCache.ts b/ts2panda/src/base/vregisterCache.ts index a48db661b36fdb9646f6d38ffc9cfaf04dd8e5d2..e4b3082acf658539c8f00ab43d2599c4d3189263 100755 --- a/ts2panda/src/base/vregisterCache.ts +++ b/ts2panda/src/base/vregisterCache.ts @@ -33,13 +33,15 @@ import { // expandString, expandSymbol, expandTrue, - expandUndefined + expandUndefined, + expandFunc } from "./builtIn"; import { expandLexEnv } from "./lexEnv"; export enum CacheList { MIN, NaN = MIN, HOLE, + FUNC, // load function Infinity, undefined, // Boolean, @@ -55,7 +57,7 @@ export enum CacheList { LexEnv, // Lex Env must come before True and False, because LexEnv depends on True and False True, False, - MAX, + MAX } let cacheExpandHandlers = new Map([ [CacheList.HOLE, expandHole], @@ -75,6 +77,7 @@ let cacheExpandHandlers = new Map([ [CacheList.LexEnv, expandLexEnv], [CacheList.True, expandTrue], [CacheList.False, expandFalse], + [CacheList.FUNC, expandFunc], ]); class CacheItem { diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index b87ad4cc6a300f0aacccc882a40714e3d05e25dd..c9230ee088d2dcd083170848c66cb2eec6cf32b7 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -74,6 +74,7 @@ import { } from "./pandagen"; import { Recorder } from "./recorder"; import { + FunctionScope, GlobalScope, LoopScope, ModuleScope, @@ -109,7 +110,6 @@ import { isAssignmentOperator } from "./syntaxCheckHelper"; import { GlobalVariable, LocalVariable, - ModuleVariable, VarDeclarationKind, Variable } from "./variable"; @@ -155,6 +155,7 @@ export class Compiler { this.compileSourceFileOrBlock(this.rootNode); } else { this.compileFunctionLikeDeclaration(this.rootNode); + this.callOpt(); } } @@ -170,6 +171,52 @@ export class Compiler { return this.envUnion[this.envUnion.length - 1]; } + private callOpt() { + let CallMap: Map = new Map([ + ["this", 1], + ["4newTarget", 2], + ["0newTarget", 2], + ["argumentsOrRestargs", 4] + ]); + let callType = 0; + let scope = this.pandaGen.getScope(); + + if (scope instanceof FunctionScope) { + let tempLocals: VReg[] = []; + let tempNames: Set = new Set(); + let count = 0; + // 4funcObj/newTarget/this + for (let i = 0; i < 3; i++) { + if (scope.getCallOpt().has(scope.getParameters()[i].getName())) { + tempLocals.push(this.pandaGen.getLocals()[i]); + callType += CallMap.get(scope.getParameters()[i].getName()) ?? 0; + } else { + tempNames.add(scope.getParameters()[i].getName()); + count++; + } + } + // acutal parameters + for (let i = 3; i < this.pandaGen.getLocals().length; i++) { + tempLocals.push(this.pandaGen.getLocals()[i]); + } + let name2variable = scope.getName2variable(); + name2variable.forEach((value, key) => { + if (tempNames.has(key)) { + name2variable.delete(key) + } + }) + + this.pandaGen.setLocals(tempLocals); + this.pandaGen.setParametersCount(this.pandaGen.getParametersCount()-count); + + if (scope.getArgumentsOrRestargs()) { + callType += CallMap.get("argumentsOrRestargs") ?? 0; + } + + this.pandaGen.setCallType(callType); + } + } + private compileLexicalBindingForArrowFunction() { let rootNode = this.rootNode; @@ -204,8 +251,14 @@ export class Compiler { let v = variableInfo.v; if (v && v.isLexVar) { + if ((arg === "this" || arg === "4newTarget") && variableInfo.scope instanceof FunctionScope) { + variableInfo.scope.setCallOpt(arg); + } + if (arg === "arguments" && variableInfo.scope instanceof FunctionScope) { + variableInfo.scope.setArgumentsOrRestargs(); + } let pandaGen = this.pandaGen; - let vreg = pandaGen.getVregForVariable(variableInfo.v); + let vreg = "4funcObj" === arg ? getVregisterCache(pandaGen, CacheList.FUNC) : pandaGen.getVregForVariable(variableInfo.v); let slot = (variableInfo.v).idxLex; pandaGen.storeLexicalVar(this.rootNode, variableInfo.level, slot, vreg); } @@ -283,6 +336,10 @@ export class Compiler { let paramReg = pandaGen.getVregForVariable(variable!); if (param.dotDotDotToken) { + let scope = this.pandaGen.getScope(); + if (scope instanceof FunctionScope) { + scope.setArgumentsOrRestargs(); + } pandaGen.copyRestArgs(param, index); pandaGen.storeAccumulator(param, paramReg); } @@ -886,6 +943,9 @@ export class Compiler { checkValidUseSuperBeforeSuper(this, node); let { scope, level, v } = this.scope.find("this"); + + this.setCallOpt(scope, "this") + if (!v) { throw new Error("\"this\" not found"); } @@ -1293,6 +1353,9 @@ export class Compiler { let scope = thisInfo.scope; let level = thisInfo.level; let v = thisInfo.v; + + this.setCallOpt(scope, "this") + if (scope && level >= 0) { let needSetLexVar: boolean = false; while (curScope != scope) { @@ -1320,6 +1383,9 @@ export class Compiler { setThis(node: ts.Node) { let pandaGen = this.pandaGen; let thisInfo = this.getCurrentScope().find("this"); + + this.setCallOpt(thisInfo.scope, "this") + if (thisInfo.v!.isLexVar) { let slot = (thisInfo.v).idxLex; let value = pandaGen.getTemp(); @@ -1331,6 +1397,12 @@ export class Compiler { } } + setCallOpt(scope: Scope | undefined, callOptStr: String) { + if (scope instanceof FunctionScope) { + scope.setCallOpt(callOptStr); + } + } + getPandaGen() { return this.pandaGen; } @@ -1355,27 +1427,21 @@ export class Compiler { variable: { scope: Scope | undefined, level: number, v: Variable | undefined }, isDeclaration: boolean) { if (variable.v instanceof LocalVariable) { - if (isDeclaration) { - if (variable.v.isLet()) { - variable.v.initialize(); - if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { + if (isDeclaration && variable.v.isLetOrConst()) { + variable.v.initialize(); + if (variable.scope instanceof GlobalScope) { + if (variable.v.isLet()) { this.pandaGen.stLetToGlobalRecord(node, variable.v.getName()); - return; - } - } else if (variable.v.isConst()) { - variable.v.initialize(); - if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { + } else { this.pandaGen.stConstToGlobalRecord(node, variable.v.getName()); - return; } + return; } } - if (variable.v.isLetOrConst()) { - if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { - this.pandaGen.tryStoreGlobalByName(node, variable.v.getName()); - return; - } + if (variable.v.isLetOrConst() && variable.scope instanceof GlobalScope) { + this.pandaGen.tryStoreGlobalByName(node, variable.v.getName()); + return; } if (variable.scope && variable.level >= 0) { // inner most function will load outer env instead of new a lex env @@ -1407,11 +1473,9 @@ export class Compiler { } loadTarget(node: ts.Node, variable: { scope: Scope | undefined, level: number, v: Variable | undefined }) { - if (variable.v instanceof ModuleVariable) { - this.pandaGen.loadModuleVariable(node, variable.v.getModule(), variable.v.getExoticName()); - } else if (variable.v instanceof LocalVariable) { + if (variable.v instanceof LocalVariable) { if (variable.v.isLetOrConst() || variable.v.isClass()) { - if (variable.scope instanceof GlobalScope || variable.scope instanceof ModuleScope) { + if (variable.scope instanceof GlobalScope) { this.pandaGen.tryLoadGlobalByName(node, variable.v.getName()); return; } diff --git a/ts2panda/src/compilerDriver.ts b/ts2panda/src/compilerDriver.ts index e8fa59c59695974570ff6e896c80f7103e2c54b5..46a1533d016b162d758892d949a889b987677d64 100644 --- a/ts2panda/src/compilerDriver.ts +++ b/ts2panda/src/compilerDriver.ts @@ -206,7 +206,7 @@ export class CompilerDriver { let compiler = new Compiler(node, pandaGen, this, recorder); if (CmdOptions.isModules() && ts.isSourceFile(node) && scope instanceof ModuleScope) { - setImport(recorder.getImportStmts(), scope, pandaGen, compiler); + setImport(recorder.getImportStmts(), scope, pandaGen); setExportBinding(recorder.getExportStmts(), scope, pandaGen); } @@ -249,7 +249,7 @@ export class CompilerDriver { let compiler = new Compiler(node, pandaGen, this, recorder); if (CmdOptions.isModules() && ts.isSourceFile(node) && scope instanceof ModuleScope) { - setImport(recorder.getImportStmts(), scope, pandaGen, compiler); + setImport(recorder.getImportStmts(), scope, pandaGen); setExportBinding(recorder.getExportStmts(), scope, pandaGen); } diff --git a/ts2panda/src/expression/metaProperty.ts b/ts2panda/src/expression/metaProperty.ts index 103755473d514e01f1d1f349c3af135de8c4fd01..eadef5cdee62d84c92bf3ea6a4da410c4db6ecbd 100644 --- a/ts2panda/src/expression/metaProperty.ts +++ b/ts2panda/src/expression/metaProperty.ts @@ -22,6 +22,9 @@ export function compileMetaProperty(expr: ts.MetaProperty, compiler: Compiler) { let id = jshelpers.getTextOfIdentifierOrLiteral(expr.name); if (id == "target") { let { scope, level, v } = curScope.find("4newTarget"); + + compiler.setCallOpt(scope, "4newTarget"); + if (!v) { throw new Error("fail to access new.target"); } else { diff --git a/ts2panda/src/function/generatorFunctionBuilder.ts b/ts2panda/src/function/generatorFunctionBuilder.ts index 85d1d18c1999fdaa7ca73bc091f235cefbb7cf5a..73a26c6be44ff69a8472f50db41a2eea4feec2d8 100755 --- a/ts2panda/src/function/generatorFunctionBuilder.ts +++ b/ts2panda/src/function/generatorFunctionBuilder.ts @@ -48,9 +48,10 @@ export class GeneratorFunctionBuilder { prepare(node: ts.Node, recorder: Recorder) { let pandaGen = this.pandaGen; let scope = recorder.getScopeOfNode(node); - let funcObj = scope.getName2variable().get('4funcObj')!.getVreg(); + let funcObj = scope.getName2variable().get("4funcObj")!.getVreg(); - pandaGen.createGeneratorObj(node, funcObj); + // backend handle funcobj, frontend set undefined + pandaGen.createGeneratorObj(node, getVregisterCache(pandaGen, CacheList.FUNC)); pandaGen.storeAccumulator(node, this.genObj); pandaGen.suspendGenerator(node, this.genObj, getVregisterCache(pandaGen, CacheList.undefined)); pandaGen.resumeGenerator(node, this.genObj); diff --git a/ts2panda/src/lexenv.ts b/ts2panda/src/lexenv.ts index 3193042838a25f81ce0067cc1dbe716719d86ac2..d4c1cc77760c973702b96b8a651974effd2fb03f 100644 --- a/ts2panda/src/lexenv.ts +++ b/ts2panda/src/lexenv.ts @@ -35,7 +35,6 @@ import { PandaGen } from "./pandagen"; import { Scope } from "./scope"; import { LocalVariable, - ModuleVariable, Variable } from "./variable"; import jshelpers from "./jshelpers"; @@ -93,7 +92,11 @@ export class VariableAccessLoad extends VariableAccessBase { pandaGen.freeTemps(holeReg); return insns; } - insns.push(loadAccumulator(bindVreg)); + if (v.getName() === "4funcObj") { + insns.push(loadAccumulator(getVregisterCache(pandaGen, CacheList.FUNC))); + } else { + insns.push(loadAccumulator(bindVreg)); + } return insns; } @@ -161,7 +164,7 @@ export class VariableAcessStore extends VariableAccessBase { insns.push(storeAccumulator(bindVreg)); - if (v.isExportVar() && !(v instanceof ModuleVariable)) { + if (v.isExportVar()) { insns.push(storeModuleVariable(v.getExportedName())); } @@ -197,7 +200,7 @@ export class VariableAcessStore extends VariableAccessBase { insns.push(storeLexicalVar(this.level, slot, valueReg)); insns.push(loadAccumulator(valueReg)); - if (v.isExportVar() && !(v instanceof ModuleVariable)) { + if (v.isExportVar()) { insns.push(storeModuleVariable(v.getExportedName())); } pandaGen.freeTemps(valueReg); diff --git a/ts2panda/src/modules.ts b/ts2panda/src/modules.ts index 705cba7b642e6009c39a8908af94fc0a0a296769..a4a8aff21ebf4aed0b154446cfead353f0e91cef 100644 --- a/ts2panda/src/modules.ts +++ b/ts2panda/src/modules.ts @@ -16,10 +16,9 @@ import * as ts from "typescript"; import { PandaGen } from "./pandagen"; import jshelpers from "./jshelpers"; -import { LocalVariable, ModuleVariable } from "./variable"; +import { LocalVariable } from "./variable"; import { DiagnosticCode, DiagnosticError } from "./diagnostic"; import { ModuleScope } from "./scope"; -import { Compiler } from "./compiler"; export class ModuleStmt { private node: ts.Node @@ -69,23 +68,27 @@ export class ModuleStmt { } } -export function setImport(importStmts: Array, moduleScope: ModuleScope, pandagen: PandaGen, compiler: Compiler) { +export function setImport(importStmts: Array, moduleScope: ModuleScope, pandagen: PandaGen) { importStmts.forEach((importStmt) => { pandagen.importModule(importStmt.getNode(), importStmt.getModuleRequest()); - let moduleReg = pandagen.allocLocalVreg(); - pandagen.storeAccumulator(importStmt.getNode(), moduleReg); - + // import * as xxx from "a.js" if (importStmt.getNameSpace()) { let v = moduleScope.findLocal(importStmt.getNameSpace())!; pandagen.storeAccToLexEnv(importStmt.getNode(), moduleScope, 0, v, true); (v).initialize(); } + // import { ... } from "a.js" + // import defaultExport, * as a from "a.js" + let moduleReg = pandagen.allocLocalVreg(); + pandagen.storeAccumulator(importStmt.getNode(), moduleReg); + let bindingNameMap = importStmt.getBindingNameMap(); bindingNameMap.forEach((value: string, key: string) => { - let v = moduleScope.findLocal(key)!; - v.bindModuleVreg(moduleReg); - v.setExoticName(value); + let v = moduleScope.findLocal(key)!; + pandagen.loadModuleVariable(importStmt.getNode(), moduleReg, value); + pandagen.storeAccToLexEnv(importStmt.getNode(), moduleScope, 0, v, true); + (v).initialize(); }); }) } @@ -118,13 +121,8 @@ export function setExportBinding(exportStmts: Array, moduleScope: Mo throw new DiagnosticError(exportStmt.getNode(), DiagnosticCode.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, jshelpers.getSourceFileOfNode(exportStmt.getNode()), [value]); } - if (v instanceof ModuleVariable) { - pandagen.loadModuleVariable(exportStmt.getNode(), v.getModule(), v.getName()); - pandagen.storeModuleVar(exportStmt.getNode(), key); - } else { - (v).setExport(); - (v).setExportedName(key); - } + (v).setExport(); + (v).setExportedName(key); }); } }) diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index e823a721742aab76baff208acd0fb57a56475554..1b56905a963a65d309e517acdcae69fce351f6db 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -201,6 +201,7 @@ export class PandaGen { private sourceFileDebugInfo: string = ""; private sourceCodeDebugInfo: string | undefined; private icSize: number = 0; + private callType: number = 0; private static literalArrayBuffer: Array = []; @@ -211,6 +212,14 @@ export class PandaGen { this.vregisterCache = new VregisterCache(); } + public setCallType(callType: number) { + this.callType = callType; + } + + public getCallType(): number { + return this.callType; + } + public getSourceCodeDebugInfo() { return this.sourceCodeDebugInfo; } @@ -348,10 +357,18 @@ export class PandaGen { return this.totalRegsNum; } + setParametersCount(count: number) { + this.parametersCount = count; + } + getParametersCount(): number { return this.parametersCount; } + setLocals(locals: VReg[]) { + this.locals = locals; + } + getLocals(): VReg[] { return this.locals; } @@ -367,6 +384,9 @@ export class PandaGen { loadAccFromArgs(node: ts.Node) { if ((this.scope).getUseArgs()) { let v = this.scope!.findLocal("arguments"); + if (this.scope instanceof FunctionScope) { + this.scope.setArgumentsOrRestargs(); + } if (v) { let paramVreg = this.getVregForVariable(v); this.getUnmappedArgs(node); diff --git a/ts2panda/src/pandasm.ts b/ts2panda/src/pandasm.ts index f4ca2651ae12ef281ecff503794687a19fa6ae0f..c523f7fa8707ad2171b26d4a696213eafb198090 100644 --- a/ts2panda/src/pandasm.ts +++ b/ts2panda/src/pandasm.ts @@ -72,6 +72,7 @@ export class Function { public variables: Array | undefined; public sourceFile: string; public sourceCode: string | undefined; + public callType: number; constructor( name: string, @@ -82,6 +83,7 @@ export class Function { variables: Array | undefined = undefined, sourceFile: string = "", sourceCode: string | undefined = undefined, + callType: number = 0 ) { this.name = name; this.signature = signature; @@ -93,6 +95,7 @@ export class Function { this.variables = variables; this.sourceFile = sourceFile; this.sourceCode = sourceCode; + this.callType = callType; } } diff --git a/ts2panda/src/recorder.ts b/ts2panda/src/recorder.ts index d74afb9d1c3378feb0bff1e318a1e1610b83215a..387ddf83d12d1fd0dbc5304ec45c1e65db0a581b 100644 --- a/ts2panda/src/recorder.ts +++ b/ts2panda/src/recorder.ts @@ -35,7 +35,6 @@ import { LetDecl, LocalScope, LoopScope, - ModDecl, ModuleScope, Scope, VarDecl, @@ -292,7 +291,7 @@ export class Recorder { // import defaultExport from "a.js" if (importClause.name) { let name = jshelpers.getTextOfIdentifierOrLiteral(importClause.name); - scope.setDecls(new ModDecl(name, importClause.name)); + scope.setDecls(new ConstDecl(name, importClause.name)); importStmt.addLocalName(name, "default"); } @@ -313,7 +312,7 @@ export class Recorder { namedBindings.elements.forEach((element) => { let name: string = jshelpers.getTextOfIdentifierOrLiteral(element.name); let exoticName: string = element.propertyName ? jshelpers.getTextOfIdentifierOrLiteral(element.propertyName) : name; - scope.setDecls(new ModDecl(name, element)); + scope.setDecls(new ConstDecl(name, element)); importStmt.addLocalName(name, exoticName); }); } diff --git a/ts2panda/src/scope.ts b/ts2panda/src/scope.ts index e2aa29a06262b379970d0abd4e2ca518590cdc75..44cde853d8c9229b20f1454825f981c25bed048b 100644 --- a/ts2panda/src/scope.ts +++ b/ts2panda/src/scope.ts @@ -19,7 +19,6 @@ import { LOGD, LOGE } from "./log"; import { GlobalVariable, LocalVariable, - ModuleVariable, VarDeclarationKind, Variable } from "./variable"; @@ -55,12 +54,6 @@ export class ConstDecl extends Decl { } } -export class ModDecl extends Decl { - constructor(localName: string, node: ts.Node) { - super(localName, node); - } -} - export class FuncDecl extends Decl { readonly index: number; constructor(funcName: string, node: ts.Node, index: number) { @@ -393,9 +386,6 @@ export class ModuleScope extends VariableScope { } else if (declKind == VarDeclarationKind.VAR || declKind == VarDeclarationKind.FUNCTION) { v = new LocalVariable(declKind, name); this.locals.push(v); - } else if (declKind == VarDeclarationKind.MODULE) { - v = new ModuleVariable(VarDeclarationKind.CONST, name, InitStatus.INITIALIZED); - this.locals.push(v); } else { v = new LocalVariable(declKind, name, status); this.locals.push(v); @@ -408,6 +398,8 @@ export class ModuleScope extends VariableScope { export class FunctionScope extends VariableScope { private parameterLength: number = 0; private funcName: string = ""; + private callOpt: Set = new Set(); + private isArgumentsOrRestargs: boolean = false; constructor(parent?: Scope, node?: ts.FunctionLikeDeclaration) { super(); this.parent = parent ? parent : undefined; @@ -430,6 +422,22 @@ export class FunctionScope extends VariableScope { return this.funcName; } + public getCallOpt() { + return this.callOpt; + } + + public setCallOpt(key: String) { + this.callOpt.add(key); + } + + public setArgumentsOrRestargs() { + this.isArgumentsOrRestargs = true; + } + + public getArgumentsOrRestargs() { + return this.isArgumentsOrRestargs; + } + getParent(): Scope | undefined { return this.parent; } diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index 1163c9e0b86aadac244721c152ca0e0f6375d031..d346350f80ccf7e56dc9ad3caa2ea1da3f0c5cea 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -40,7 +40,6 @@ import { FunctionScope, GlobalScope, LocalScope, - ModuleScope, Scope, VariableScope } from "../scope"; @@ -117,7 +116,7 @@ export function compileClassDeclaration(compiler: Compiler, stmt: ts.ClassLikeDe if (stmt.name) { let className = jshelpers.getTextOfIdentifierOrLiteral(stmt.name); let classScope = compiler.getRecorder().getScopeOfNode(stmt); - if (!ts.isClassExpression(stmt) && (classScope.getParent() instanceof GlobalScope || classScope.getParent() instanceof ModuleScope)) { + if (!ts.isClassExpression(stmt) && classScope.getParent() instanceof GlobalScope) { pandaGen.stClassToGlobalRecord(stmt, className); } else { let classInfo = classScope.find(className); @@ -282,6 +281,9 @@ export function compileSuperCall(compiler: Compiler, node: ts.CallExpression, ar let curScope = compiler.getCurrentScope(); let { scope, level, v } = curScope.find("this"); + compiler.setCallOpt(scope, "this"); + compiler.setCallOpt(scope, "4newTarget"); + if (scope && level >= 0) { let tmpScope = curScope; let needSetLexVar: boolean = false; @@ -296,6 +298,9 @@ export function compileSuperCall(compiler: Compiler, node: ts.CallExpression, ar if (needSetLexVar) { scope.setLexVar(v, curScope); } + if (needSetLexVar && curScope instanceof FunctionScope) { + curScope.setCallOpt("0newTarget"); + } } if (hasSpread) { @@ -330,7 +335,7 @@ function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { if (ts.isConstructorDeclaration(nearestFunc)) { let funcObj = nearestFuncScope.findLocal("4funcObj"); - pandaGen.loadAccumulator(node, pandaGen.getVregForVariable(funcObj)); + pandaGen.loadAccumulator(node, getVregisterCache(pandaGen, CacheList.FUNC)); } else { let outerFunc = jshelpers.getContainingFunction(nearestFunc); let outerFuncScope = recorder.getScopeOfNode(outerFunc); diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 58e7765b7952b67007b31d14407726cd213460d0..e3b60b281e5f4d09892ef2c70a3b5ad98a1893fa 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -170,6 +170,7 @@ export class Ts2Panda { let funcSignature = Ts2Panda.getFuncSignature(pg); let funcInsnsAndRegsNum = Ts2Panda.getFuncInsnsAndRegsNum(pg); let sourceFile = pg.getSourceFileDebugInfo(); + let callType = pg.getCallType(); let variables, sourceCode; if (CmdOptions.isDebugMode()) { @@ -189,6 +190,7 @@ export class Ts2Panda { variables, sourceFile, sourceCode, + callType ); let catchTables = generateCatchTables(pg.getCatchMap()); catchTables.forEach((catchTable) => { diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 966cb9191bab1bad699eff7fa377ce18dccad5d9..eba622a9ea94d46218f7addbd89a14a644339723 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -140,37 +140,6 @@ export class LocalVariable extends Variable { } } -export class ModuleVariable extends LocalVariable { - private module: VReg | undefined; - private exoticName: string = ""; - - constructor(declKind: VarDeclarationKind, name: string, status: InitStatus) { - super(declKind, name, status); - } - - bindModuleVreg(vreg: VReg) { - this.module = vreg; - } - - setExoticName(exoticName: string) { - this.exoticName = exoticName; - } - - getExoticName() { - if (this.exoticName == "") { - throw new Error("Variable doesn't have exotic name"); - } - return this.exoticName; - } - - getModule() { - if (!this.module) { - throw new Error("Variable's module has not been binded"); - } - return this.module; - } -} - export class GlobalVariable extends Variable { constructor(declKind: VarDeclarationKind, name: string) { super(declKind, name); diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 8f131798fb1334cc8f335f1a0881c63b052004d8..0e72bf4f5e2a78fea7daadd96d2a1a05c8211bc5 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -594,6 +594,30 @@ static void ParseFunctionCatchTables(const Json::Value &function, panda::pandasm } } +static void ParseFunctionCallType(const Json::Value &function, panda::pandasm::Function &pandaFunc) +{ + std::string funcName = ""; + if (function.isMember("name") && function["name"].isString()) { + funcName = function["name"].asString(); + } + if (funcName == "func_main_0") { + return ; + } + + uint32_t callType = 0; + if (function.isMember("callType") && function["callType"].isInt()) { + callType = function["callType"].asUInt(); + } + panda::pandasm::AnnotationData callTypeAnnotation("_ESCallTypeAnnotation"); + std::string annotationName = "callType"; + panda::pandasm::AnnotationElement callTypeAnnotationElement(annotationName, + std::make_unique( + panda::pandasm::ScalarValue::Create(callType))); + callTypeAnnotation.AddElement(std::move(callTypeAnnotationElement)); + const_cast&>(pandaFunc.metadata->GetAnnotations()).push_back( + std::move(callTypeAnnotation)); +} + static panda::pandasm::Function ParseFunction(const Json::Value &function) { auto pandaFunc = GetFunctionDefintion(function); @@ -607,10 +631,20 @@ static panda::pandasm::Function ParseFunction(const Json::Value &function) ParseFunctionLabels(function, pandaFunc); // parsing catch blocks ParseFunctionCatchTables(function, pandaFunc); + // parsing call opt type + ParseFunctionCallType(function, pandaFunc); return pandaFunc; } +static void GenerateESCallTypeAnnotationRecord(panda::pandasm::Program &prog) +{ + auto callTypeAnnotationRecord = panda::pandasm::Record("_ESCallTypeAnnotation", LANG_EXT); + callTypeAnnotationRecord.metadata->SetAttribute("external"); + callTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION); + prog.record_table.emplace(callTypeAnnotationRecord.name, std::move(callTypeAnnotationRecord)); +} + static void GenrateESModuleModeRecord(panda::pandasm::Program &prog, bool moduleMode) { auto ecmaModuleModeRecord = panda::pandasm::Record("_ESModuleMode", LANG_EXT); @@ -705,6 +739,7 @@ static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, co static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program &prog) { + GenerateESCallTypeAnnotationRecord(prog); ParseModuleMode(rootValue, prog); ParseLogEnable(rootValue); ParseDebugMode(rootValue);