Skip to content

wasm: do not export malloc, calloc, realloc, free #3142

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

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cgo/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ var validLinkerFlags = []*regexp.Regexp{
re(`-L([^@\-].*)`),
re(`-O`),
re(`-O([^@\-].*)`),
re(`--export=(.+)`), // for wasm-ld
re(`-f(no-)?(pic|PIC|pie|PIE)`),
re(`-f(no-)?openmp(-simd)?`),
re(`-fsanitize=([^@\-].*)`),
Expand Down
7 changes: 4 additions & 3 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1059,11 +1059,12 @@ func (b *builder) createFunctionStart(intrinsic bool) {
if b.info.section != "" {
b.llvmFn.SetSection(b.info.section)
}
if b.info.exported && strings.HasPrefix(b.Triple, "wasm") {
if b.info.exported && b.info.module != "" && strings.HasPrefix(b.Triple, "wasm") {
// Set the exported name. This is necessary for WebAssembly because
// otherwise the function is not exported.
functionAttr := b.ctx.CreateStringAttribute("wasm-export-name", b.info.linkName)
b.llvmFn.AddFunctionAttr(functionAttr)
b.llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute("wasm-export-name", b.info.linkName))
// Set the export module.
b.llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute("wasm-export-module", b.info.module))
}

// Some functions have a pragma controlling the inlining level.
Expand Down
32 changes: 11 additions & 21 deletions compiler/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,9 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
// exported.
func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
info := functionInfo{
// Pick the default linkName.
linkName: f.RelString(nil),
module: "env",
importName: f.Name(),
linkName: f.RelString(nil), // pick the default linkName
}
// Check for //go: pragmas, which may change the link name (among others).
info.parsePragmas(f)
Expand All @@ -225,10 +226,6 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
return
}
if decl, ok := f.Syntax().(*ast.FuncDecl); ok && decl.Doc != nil {

// Our importName for a wasm module (if we are compiling to wasm), or llvm link name
var importName string

for _, comment := range decl.Doc.List {
text := comment.Text
if strings.HasPrefix(text, "//export ") {
Expand All @@ -246,18 +243,22 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
continue
}

importName = parts[1]
info.importName = parts[1]
info.linkName = parts[1]
info.exported = true
case "//go:interrupt":
if hasUnsafeImport(f.Pkg.Pkg) {
info.interrupt = true
}
case "//go:wasm-module":
// Alternative comment for setting the import module.
if len(parts) != 2 {
continue
if len(parts) == 1 {
// Function must not be exported outside of the WebAssembly
// module (but only be made available for linking).
info.module = ""
} else if len(parts) == 2 {
info.module = parts[1]
}
info.module = parts[1]
case "//go:inline":
info.inline = inlineHint
case "//go:noinline":
Expand Down Expand Up @@ -297,17 +298,6 @@ func (info *functionInfo) parsePragmas(f *ssa.Function) {
}
}
}

// Set the importName for our exported function if we have one
if importName != "" {
if info.module == "" {
info.linkName = importName
} else {
// WebAssembly import
info.importName = importName
}
}

}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/testdata/pragma.ll
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ declare void @main.undefinedFunctionNotInSection(i8*) #0

attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-name"="extern_func" }
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-module"="env" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-name"="extern_func" }
attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-module"="env" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
4 changes: 4 additions & 0 deletions src/runtime/arch_tinygowasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func growHeap() bool {
var allocs = make(map[uintptr][]byte)

//export malloc
//go:wasm-module
func libc_malloc(size uintptr) unsafe.Pointer {
buf := make([]byte, size)
ptr := unsafe.Pointer(&buf[0])
Expand All @@ -76,6 +77,7 @@ func libc_malloc(size uintptr) unsafe.Pointer {
}

//export free
//go:wasm-module
func libc_free(ptr unsafe.Pointer) {
if ptr == nil {
return
Expand All @@ -88,12 +90,14 @@ func libc_free(ptr unsafe.Pointer) {
}

//export calloc
//go:wasm-module
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
// No difference between calloc and malloc.
return libc_malloc(nmemb * size)
}

//export realloc
//go:wasm-module
func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
// It's hard to optimize this to expand the current buffer with our GC, but
// it is theoretically possible. For now, just always allocate fresh.
Expand Down