Skip to content

Commit

Permalink
wasm: add //go:wasmexport support
Browse files Browse the repository at this point in the history
This adds support for the `//go:wasmexport` pragma as proposed here:
golang/go#65199

It is currently implemented only for wasip1 and wasm-unknown, but it is
certainly possible to extend it to other targets like GOOS=js and
wasip2.
  • Loading branch information
aykevl committed Oct 3, 2024
1 parent 52788e5 commit c79d817
Show file tree
Hide file tree
Showing 22 changed files with 765 additions and 67 deletions.
12 changes: 10 additions & 2 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
ABI: config.ABI(),
GOOS: config.GOOS(),
GOARCH: config.GOARCH(),
BuildMode: config.BuildMode(),
CodeModel: config.CodeModel(),
RelocationModel: config.RelocationModel(),
SizeLevel: sizeLevel,
Expand Down Expand Up @@ -649,6 +650,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
result.Binary = result.Executable // final file
ldflags := append(config.LDFlags(), "-o", result.Executable)

if config.Options.BuildMode == "c-shared" {
if !strings.HasPrefix(config.Triple(), "wasm32-") {
return result, fmt.Errorf("buildmode c-shared is only supported on wasm at the moment")
}
ldflags = append(ldflags, "--no-entry")
}

// Add compiler-rt dependency if needed. Usually this is a simple load from
// a cache.
if config.Target.RTLib == "compiler-rt" {
Expand Down Expand Up @@ -884,7 +892,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe

err := cmd.Run()
if err != nil {
return fmt.Errorf("wasm-tools failed: %w", err)
return fmt.Errorf("`wasm-tools component embed` failed: %w", err)
}

// wasm-tools component new embedded.wasm -o component.wasm
Expand All @@ -904,7 +912,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe

err = cmd.Run()
if err != nil {
return fmt.Errorf("wasm-tools failed: %w", err)
return fmt.Errorf("`wasm-tools component new` failed: %w", err)
}
}

Expand Down
11 changes: 11 additions & 0 deletions compileopts/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ func (c *Config) CPU() string {
return c.Target.CPU
}

// The current build mode (like the `-buildmode` command line flag).
func (c *Config) BuildMode() string {
if c.Options.BuildMode != "" {
return c.Options.BuildMode
}
if c.Target.BuildMode != "" {
return c.Target.BuildMode
}
return "default"
}

// Features returns a list of features this CPU supports. For example, for a
// RISC-V processor, that could be "+a,+c,+m". For many targets, an empty list
// will be returned.
Expand Down
10 changes: 10 additions & 0 deletions compileopts/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
)

var (
validBuildModeOptions = []string{"default", "c-shared"}
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
Expand All @@ -26,6 +27,7 @@ type Options struct {
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
Directory string // working dir, leave it unset to use the current working dir
Target string
BuildMode string // -buildmode flag
Opt string
GC string
PanicStrategy string
Expand Down Expand Up @@ -61,6 +63,14 @@ type Options struct {

// Verify performs a validation on the given options, raising an error if options are not valid.
func (o *Options) Verify() error {
if o.BuildMode != "" {
valid := isInArray(validBuildModeOptions, o.BuildMode)
if !valid {
return fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,
o.BuildMode,
strings.Join(validBuildModeOptions, ", "))
}
}
if o.GC != "" {
valid := isInArray(validGCOptions, o.GC)
if !valid {
Expand Down
1 change: 1 addition & 0 deletions compileopts/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type TargetSpec struct {
GOARCH string `json:"goarch,omitempty"`
SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc)
BuildTags []string `json:"build-tags,omitempty"`
BuildMode string `json:"buildmode,omitempty"` // default build mode (if nothing specified)
GC string `json:"gc,omitempty"`
Scheduler string `json:"scheduler,omitempty"`
Serial string `json:"serial,omitempty"` // which serial output to use (uart, usb, none)
Expand Down
6 changes: 6 additions & 0 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Config struct {
ABI string
GOOS string
GOARCH string
BuildMode string
CodeModel string
RelocationModel string
SizeLevel int
Expand Down Expand Up @@ -1384,6 +1385,11 @@ func (b *builder) createFunction() {
b.llvmFn.SetLinkage(llvm.InternalLinkage)
b.createFunction()
}

// Create wrapper function that can be called externally.
if b.info.wasmExport != "" {
b.createWasmExport()
}
}

// posser is an interface that's implemented by both ssa.Value and
Expand Down
Loading

0 comments on commit c79d817

Please sign in to comment.