wasm: do not allow undefined symbols
--allow-undefined can be a problem: it allows compiling code that will
fail when loaded. This change makes sure that if some symbols are
undefined, they are reported as an error by the linker.
Previously, people could get away with importing a function that was not
defined, like this:
    func add(int a, int b) int
    func test() {
        println(add(3, 5))
    }
This was always unintended but mostly worked. With this change, it isn't
possible anymore. Now every function needs to be marked with //export
explicitly:
    //export add
    func add(int a, int b) int
    func test() {
        println(add(3, 5))
    }
As before, functions will be placed in the `env` module with the name
set from the `//export` tag. This can be overridden with
`//go:import-module`:
    //go:import-module math
    //export add
    func add(int a, int b) int
    func test() {
        println(add(3, 5))
    }
For the syscall/js package, I needed to give a list of symbols that are
undefined. This list is based on the JavaScript functions defined in
targets/wasm_exec.js.
			
			
Этот коммит содержится в:
		
							родитель
							
								
									07cdcc61f7
								
							
						
					
					
						коммит
						8bbfb1ee68
					
				
					 6 изменённых файлов: 35 добавлений и 14 удалений
				
			
		| 
						 | 
				
			
			@ -163,18 +163,20 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
 | 
			
		|||
	// External/exported functions may not retain pointer values.
 | 
			
		||||
	// https://golang.org/cmd/cgo/#hdr-Passing_pointers
 | 
			
		||||
	if info.exported {
 | 
			
		||||
		// Set the wasm-import-module attribute if the function's module is set.
 | 
			
		||||
		if info.module != "" {
 | 
			
		||||
 | 
			
		||||
		if c.archFamily() == "wasm32" {
 | 
			
		||||
			// We need to add the wasm-import-module and the wasm-import-name
 | 
			
		||||
			wasmImportModuleAttr := c.ctx.CreateStringAttribute("wasm-import-module", info.module)
 | 
			
		||||
			llvmFn.AddFunctionAttr(wasmImportModuleAttr)
 | 
			
		||||
 | 
			
		||||
			// Add the Wasm Import Name, if we are a named wasm import
 | 
			
		||||
			if info.importName != "" {
 | 
			
		||||
				wasmImportNameAttr := c.ctx.CreateStringAttribute("wasm-import-name", info.importName)
 | 
			
		||||
				llvmFn.AddFunctionAttr(wasmImportNameAttr)
 | 
			
		||||
			// attributes.
 | 
			
		||||
			module := info.module
 | 
			
		||||
			if module == "" {
 | 
			
		||||
				module = "env"
 | 
			
		||||
			}
 | 
			
		||||
			llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-module", module))
 | 
			
		||||
 | 
			
		||||
			name := info.importName
 | 
			
		||||
			if name == "" {
 | 
			
		||||
				name = info.linkName
 | 
			
		||||
			}
 | 
			
		||||
			llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-name", name))
 | 
			
		||||
		}
 | 
			
		||||
		nocaptureKind := llvm.AttributeKindID("nocapture")
 | 
			
		||||
		nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								compiler/testdata/pragma.ll
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										4
									
								
								compiler/testdata/pragma.ll
									
										
									
									
										предоставленный
									
									
								
							| 
						 | 
				
			
			@ -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" }
 | 
			
		||||
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 #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" }
 | 
			
		||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,12 +2,16 @@
 | 
			
		|||
 | 
			
		||||
.functype start_unwind (i32) -> ()
 | 
			
		||||
.import_module start_unwind, asyncify
 | 
			
		||||
.import_name start_unwind, start_unwind
 | 
			
		||||
.functype stop_unwind () -> ()
 | 
			
		||||
.import_module stop_unwind, asyncify
 | 
			
		||||
.import_name stop_unwind, stop_unwind
 | 
			
		||||
.functype start_rewind (i32) -> ()
 | 
			
		||||
.import_module start_rewind, asyncify
 | 
			
		||||
.import_name start_rewind, start_rewind
 | 
			
		||||
.functype stop_rewind () -> ()
 | 
			
		||||
.import_module stop_rewind, asyncify
 | 
			
		||||
.import_name stop_rewind, stop_rewind
 | 
			
		||||
 | 
			
		||||
.global  tinygo_unwind
 | 
			
		||||
.hidden  tinygo_unwind
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,6 @@
 | 
			
		|||
		"-msign-ext"
 | 
			
		||||
	],
 | 
			
		||||
	"ldflags": [
 | 
			
		||||
		"--allow-undefined",
 | 
			
		||||
		"--stack-first",
 | 
			
		||||
		"--no-demangle"
 | 
			
		||||
	],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								targets/wasm-undefined.txt
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										16
									
								
								targets/wasm-undefined.txt
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
syscall/js.copyBytesToGo
 | 
			
		||||
syscall/js.copyBytesToJS
 | 
			
		||||
syscall/js.finalizeRef
 | 
			
		||||
syscall/js.stringVal
 | 
			
		||||
syscall/js.valueCall
 | 
			
		||||
syscall/js.valueDelete
 | 
			
		||||
syscall/js.valueGet
 | 
			
		||||
syscall/js.valueIndex
 | 
			
		||||
syscall/js.valueInstanceOf
 | 
			
		||||
syscall/js.valueInvoke
 | 
			
		||||
syscall/js.valueLength
 | 
			
		||||
syscall/js.valueLoadString
 | 
			
		||||
syscall/js.valueNew
 | 
			
		||||
syscall/js.valuePrepareString
 | 
			
		||||
syscall/js.valueSet
 | 
			
		||||
syscall/js.valueSetIndex
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@
 | 
			
		|||
		"-msign-ext"
 | 
			
		||||
	],
 | 
			
		||||
	"ldflags": [
 | 
			
		||||
		"--allow-undefined",
 | 
			
		||||
		"--allow-undefined-file={root}/targets/wasm-undefined.txt",
 | 
			
		||||
		"--stack-first",
 | 
			
		||||
		"--no-demangle"
 | 
			
		||||
	],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче