Skip to content

Add a compiler flag to override the start function #566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dcodeIO opened this issue Mar 29, 2019 · 10 comments
Closed

Add a compiler flag to override the start function #566

dcodeIO opened this issue Mar 29, 2019 · 10 comments

Comments

@dcodeIO
Copy link
Member

dcodeIO commented Mar 29, 2019

Currently, execution of top level statements can be delayed until a custom start function is called with

@start export function myStart(): void {}

It has recently been suggested to also provide a compiler flag doing this, essentially marking a function as the entry function using the command line. This could look like:

asc ... --start myLib/myStart

with either

// myLib.ts
function myStart(): void {}

becoming the function kicking off top-level statements, or alternatively generating a function of that name if it isn't present.

@jtenner
Copy link
Contributor

jtenner commented Mar 29, 2019

Is it possible to make the compiler run all of the @start annotated functions?

Use case: Library developers who need custom glue code.

@dcodeIO
Copy link
Member Author

dcodeIO commented Mar 29, 2019

Could you explain your scenario? Asking because something like this happens under the hood: Each file's top-level statements become wrapped in a start function for this exact file. Each such function is called whenever the file is imported. The entry file's function becomes the module's start entry (which can be worked around if necessary with the @start decorator, and calls other imported files start functions in correct order). So, for library developers, their code executes when imported and they shouldn't use the start mechanism.

This issue also made me think that the @start decorator isn't ideal because doing this in code leads to confusion. Maybe it should be a compiler flag exclusively.

@jtenner
Copy link
Contributor

jtenner commented Mar 29, 2019

Scenario: A developer wants to call a web assembly imported function when someone consumes their library.

// inside "./node_modules/my_library/assembly/index.ts"
@external("env", "alert") declare function alert(value: string): void;

@start
function main() {
  alert("Hello World!");
}

Now I understand that there's an ambient context where statements are compiled and executed before the module is exported completely without a @start function already. I make extensive use of this in as2d with absolutely no problems.

I, however, think this makes the developer's intention way clearer if used to organize startup code.

In short: @start decorators could simply compile the function to call instructions in the ambient "startup" function call.

Thanks for letting me voice my opinion. 👍

@dcodeIO
Copy link
Member Author

dcodeIO commented Mar 29, 2019

A developer wants to call a web assembly imported function when someone consumes their library

Why wouldn't this work for you?

// inside "./node_modules/my_library/assembly/index.ts"
@external("env", "alert") declare function alert(value: string): void;

alert("Hello World!");

@jtenner
Copy link
Contributor

jtenner commented Mar 29, 2019

Now I understand that there's an ambient context where statements are compiled and executed before the module is exported completely without a @start function already. I make extensive use of this in as2d with absolutely no problems.

I admitted this already.

I was only stating that it might make code look clearer.

@dcodeIO
Copy link
Member Author

dcodeIO commented Mar 29, 2019

Thanks for the clarification, wasn't sure what was meant. Going to think about this a bit more, but my immediate feeling is that we should keep this as straight-forward as possible, as @start is already relatively unintuitive and, as mentioned above, might be better suited as a compiler flag.

@dcodeIO dcodeIO mentioned this issue Apr 7, 2019
@mpapierski
Copy link

@dcodeIO Would it be also possible to disable generation of start function at all in the output WASM? After upgrading asc to 0.9.1 I noticed start function is always generated. My use case is that I want to export a special function which I'll run based on its names - something like a library which exports functions with no additional start code. Is it possible?

@dcodeIO
Copy link
Member Author

dcodeIO commented Feb 3, 2020

If the start function exists in the binary, it is most likely necessary for some parts of top-level code. Likewise, if there is no top-level code that needs to execute any instructions, there won't be a start function. One mechanism in place so far is --explicitStart that forces an exported _start function one must call, instead of the module calling it implicitly. Does that help?

@mpapierski
Copy link

mpapierski commented Feb 4, 2020

If the start function exists in the binary, it is most likely necessary for some parts of top-level code. Likewise, if there is no top-level code that needs to execute any instructions, there won't be a start function. One mechanism in place so far is --explicitStart that forces an exported _start function one must call, instead of the module calling it implicitly. Does that help?

@dcodeIO Understood. I mitigated generating a "start" node by marking my global for variables of basic types (i.e. i32) a @lazy which worked fine.

Anyway, there's still something strange that I don't understand about initializing code that's part of start node. As suggested in #1069 I now have an enum:

export enum Error {
    Ok = 0,
    EarlyEndOfStream = 1,
}

@lazy
let lastError = Error.Ok;

export function GetLastError(): Error {
    return lastError;
}

export function SetLastError(error: Error): void {
    lastError = error;
}

Now, no matter what, a start node is generated for this variable. Which is surprising, as the values of enum are i32s. My question is, how are enums actually represented and is initializer for it in start is actually necessary? Would it be possible to somehow force enum to be a "const" without initializing code?

@dcodeIO
Copy link
Member Author

dcodeIO commented May 27, 2020

Closing this issue as part of 2020 vacuum because it has been superseded by a new mechanism, --explicitStart, meanwhile, that closely aligns with WASI. The @start decorator has been removed.

@dcodeIO dcodeIO closed this as completed May 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants