diff --git a/src/compiler.ts b/src/compiler.ts index 04389f46..4a24b623 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -346,6 +346,8 @@ export class Compiler extends DiagnosticEmitter { this.startFunctionBody.push(this.module.createSetGlobal(internalName, initializer)); } else this.module.addGlobal(internalName, nativeType, element.isMutable, initializer); + // if (element.globalExportName != null && element.hasConstantValue && !initializeInStart) + // this.module.addGlobalExport(element.internalName, element.globalExportName); return element.isCompiled = true; } @@ -401,19 +403,21 @@ export class Compiler extends DiagnosticEmitter { const element: Element | null = this.program.elements.get(internalName); if (!element || element.kind != ElementKind.FUNCTION_PROTOTYPE) throw new Error("unexpected missing function"); - this.compileFunctionUsingTypeArguments(element, typeArguments, contextualTypeArguments, alternativeReportNode); + const instance: Function | null = this.compileFunctionUsingTypeArguments(element, typeArguments, contextualTypeArguments, alternativeReportNode); + if (instance && declaration.range.source.isEntry && declaration.parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers)) + this.module.addExport(instance.internalName, declaration.identifier.name); } - compileFunctionUsingTypeArguments(prototype: FunctionPrototype, typeArguments: TypeNode[], contextualTypeArguments: Map | null = null, alternativeReportNode: Node | null = null) { + compileFunctionUsingTypeArguments(prototype: FunctionPrototype, typeArguments: TypeNode[], contextualTypeArguments: Map | null = null, alternativeReportNode: Node | null = null): Function | null { const instance: Function | null = prototype.resolveInclTypeArguments(typeArguments, contextualTypeArguments, alternativeReportNode); // reports if (!instance) - return; - this.compileFunction(instance); + return null; + return this.compileFunction(instance) ? instance : null; } - compileFunction(instance: Function): void { + compileFunction(instance: Function): bool { if (instance.isCompiled) - return; + return true; const declaration: FunctionDeclaration | null = instance.template.declaration; if (!declaration) @@ -421,7 +425,7 @@ export class Compiler extends DiagnosticEmitter { if (!declaration.statements) { this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range); - return; + return false; } instance.isCompiled = true; @@ -446,8 +450,7 @@ export class Compiler extends DiagnosticEmitter { typeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes); const internalName: string = instance.internalName; this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, stmts, NativeType.None)); - if (instance.globalExportName != null) - this.module.addExport(internalName, instance.globalExportName); + return true; } // namespaces @@ -544,8 +547,11 @@ export class Compiler extends DiagnosticEmitter { break; case ElementKind.FUNCTION_PROTOTYPE: - if (!(element).isGeneric) - this.compileFunctionUsingTypeArguments(element, []); + if (!(element).isGeneric) { + const functionInstance: Function | null = this.compileFunctionUsingTypeArguments(element, []); + if (functionInstance && statement.range.source.isEntry) + this.module.addExport(functionInstance.internalName, member.externalIdentifier.name); + } break; case ElementKind.GLOBAL: diff --git a/src/program.ts b/src/program.ts index 94a833ae..f733ae04 100644 --- a/src/program.ts +++ b/src/program.ts @@ -686,7 +686,6 @@ export abstract class Element { kind: ElementKind; program: Program; internalName: string; - globalExportName: string | null = null; isCompiled: bool = false; isImport: bool = false; isBuiltin: bool = false; @@ -710,7 +709,6 @@ export class Namespace extends Element { } get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : false; } - get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't exports */ false; } } /** An enum. */ @@ -726,7 +724,6 @@ export class Enum extends Namespace { } get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; } - get isGlobalExport(): bool { return this.globalExportName != null; } get isConstant(): bool { return this.declaration ? hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are const */ true; } } @@ -763,7 +760,6 @@ export class Global extends Element { } get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't exports */ false; } - get isGlobalExport(): bool { return this.globalExportName != null; } get isMutable(): bool { return this.declaration ? !hasModifier(ModifierKind.CONST, this.declaration.modifiers) : /* internals are immutable */ false; } } @@ -812,7 +808,6 @@ export class FunctionPrototype extends Element { } get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; } - get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; } get isInstance(): bool { return this.classPrototype != null; } get isGetter(): bool { return this.declaration ? hasModifier(ModifierKind.GET, this.declaration.modifiers) : /* internals aren't getters */ false; } get isSetter(): bool { return this.declaration ? hasModifier(ModifierKind.SET, this.declaration.modifiers) : /* internals aren't setters */ false; } @@ -986,7 +981,6 @@ export class FieldPrototype extends Element { } get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; } - get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; } } /** A resolved instance field. */ @@ -1022,7 +1016,6 @@ export class ClassPrototype extends Namespace { } get isExport(): bool { return this.declaration ? hasModifier(ModifierKind.EXPORT, this.declaration.modifiers) : /* internals aren't file-level exports */ false; } - get isGlobalExport(): bool { return this.declaration ? this.globalExportName != null : /* internals aren't global exports */ false; } resolve(typeArguments: Type[], contextualTypeArguments: Map | null): Class { const key: string = typesToString(typeArguments, "", ""); diff --git a/tests/compiler/do.wast b/tests/compiler/do.wast index e6236a8c..e407c35e 100644 --- a/tests/compiler/do.wast +++ b/tests/compiler/do.wast @@ -2,6 +2,8 @@ (type $iv (func (param i32))) (memory $0 1) (data (i32.const 4) "\08\00\00\00") + (export "loopDo" (func $do/loopDo)) + (export "loopDoInDo" (func $do/loopDoInDo)) (export "memory" (memory $0)) (func $do/loopDo (; 0 ;) (type $iv) (param $0 i32) (block $break$1.1 diff --git a/tests/compiler/export.wast b/tests/compiler/export.wast index 6a2707a5..75b5b63b 100644 --- a/tests/compiler/export.wast +++ b/tests/compiler/export.wast @@ -4,6 +4,8 @@ (global $export/b (mut i32) (i32.const 2)) (memory $0 1) (data (i32.const 4) "\08\00\00\00") + (export "add" (func $export/add)) + (export "renamed_sub" (func $export/sub)) (export "memory" (memory $0)) (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (return diff --git a/tests/compiler/if.wast b/tests/compiler/if.wast index 908c6c47..c99452c6 100644 --- a/tests/compiler/if.wast +++ b/tests/compiler/if.wast @@ -2,6 +2,9 @@ (type $ii (func (param i32) (result i32))) (memory $0 1) (data (i32.const 4) "\08\00\00\00") + (export "ifThenElse" (func $if/ifThenElse)) + (export "ifThen" (func $if/ifThen)) + (export "ifThenElseBlock" (func $if/ifThenElseBlock)) (export "memory" (memory $0)) (func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32) (if diff --git a/tests/compiler/reexport.wast b/tests/compiler/reexport.wast index 5e51e50a..30b1b4b8 100644 --- a/tests/compiler/reexport.wast +++ b/tests/compiler/reexport.wast @@ -3,6 +3,10 @@ (type $v (func)) (memory $0 1) (data (i32.const 4) "\08\00\00\00") + (export "add" (func $export/add)) + (export "renamed_sub" (func $export/sub)) + (export "renamed_add" (func $export/add)) + (export "rerenamed_sub" (func $export/sub)) (export "memory" (memory $0)) (start $start) (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) diff --git a/tests/compiler/switch.wast b/tests/compiler/switch.wast index 9f8f96f8..16c5898f 100644 --- a/tests/compiler/switch.wast +++ b/tests/compiler/switch.wast @@ -2,6 +2,9 @@ (type $ii (func (param i32) (result i32))) (memory $0 1) (data (i32.const 4) "\08\00\00\00") + (export "doSwitch" (func $switch/doSwitch)) + (export "doSwitchDefaultFirst" (func $switch/doSwitchDefaultFirst)) + (export "doSwitchDefaultOmitted" (func $switch/doSwitchDefaultOmitted)) (export "memory" (memory $0)) (func $switch/doSwitch (; 0 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) diff --git a/tests/compiler/while.wast b/tests/compiler/while.wast index c99ce578..36dedb08 100644 --- a/tests/compiler/while.wast +++ b/tests/compiler/while.wast @@ -2,6 +2,8 @@ (type $iv (func (param i32))) (memory $0 1) (data (i32.const 4) "\08\00\00\00") + (export "loopWhile" (func $while/loopWhile)) + (export "loopWhileInWhile" (func $while/loopWhileInWhile)) (export "memory" (memory $0)) (func $while/loopWhile (; 0 ;) (type $iv) (param $0 i32) (block $break$1.1