forked from sqlc-dev/sqlc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwasm.go
More file actions
130 lines (106 loc) · 3.09 KB
/
wasm.go
File metadata and controls
130 lines (106 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package cmd
import (
"context"
_ "embed"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime/trace"
wasmtime "github.com/bytecodealliance/wasmtime-go"
"github.com/kyleconroy/sqlc/internal/plugin"
)
//go:embed sqlc-codegen-python.wasm
var pythonCodeGen []byte
//go:embed sqlc-codegen-python.module
var pythonModule []byte
var engine *wasmtime.Engine
var linker *wasmtime.Linker
var module *wasmtime.Module
func init() {
var err error
engine = wasmtime.NewEngine()
module, err = wasmtime.NewModuleDeserialize(engine, pythonModule)
if err != nil {
panic(err)
}
// out, err := module.Serialize()
// if err != nil {
// panic(err)
// }
// err = os.WriteFile("sqlc-codegen-python.module", out, 0644)
// if err != nil {
// panic(err)
// }
linker = wasmtime.NewLinker(engine)
if err := linker.DefineWasi(); err != nil {
panic(err)
}
}
func pythonGenerate(cctx context.Context, req *plugin.CodeGenRequest) (*plugin.CodeGenResponse, error) {
stdinBlob, err := req.MarshalVT()
if err != nil {
return nil, err
}
ctx, task := trace.NewTask(cctx, "pythonGenerate")
defer task.End()
dir, err := ioutil.TempDir("", "out")
if err != nil {
return nil, fmt.Errorf("temp dir: %w", err)
}
defer os.RemoveAll(dir)
stdinPath := filepath.Join(dir, "stdin")
stderrPath := filepath.Join(dir, "stderr")
stdoutPath := filepath.Join(dir, "stdout")
if err := os.WriteFile(stdinPath, stdinBlob, 0755); err != nil {
return nil, fmt.Errorf("write file: %w", err)
}
// Configure WASI imports to write stdout into a file.
wasiConfig := wasmtime.NewWasiConfig()
wasiConfig.SetStdinFile(stdinPath)
wasiConfig.SetStdoutFile(stdoutPath)
wasiConfig.SetStderrFile(stderrPath)
store := wasmtime.NewStore(engine)
store.SetWasi(wasiConfig)
// Set the version to the same as in the WAT.
// wasi, err := wasmtime.NewWasiInstance(store, wasiConfig, "wasi_snapshot_preview1")
// if err != nil {
// return fmt.Errorf("new wasi instances: %w", err)
// }
// Create our module
//
// Compiling modules requires WebAssembly binary input, but the wasmtime
// package also supports converting the WebAssembly text format to the
// binary format.
// wasm, err := os.ReadFile("plugin.wasm")
// if err != nil {
// return fmt.Errorf("read file: %w", err)
// }
// moduRegion := trace.StartRegion(ctx, "wasmtime.NewModule")
// module, err := wasmtime.NewModule(store.Engine, pythonCodeGen)
// moduRegion.End()
// if err != nil {
// return nil, fmt.Errorf("define wasi: %w", err)
// }
linkRegion := trace.StartRegion(ctx, "linker.Instantiate")
instance, err := linker.Instantiate(store, module)
linkRegion.End()
if err != nil {
return nil, fmt.Errorf("define wasi: %w", err)
}
// Run the function
callRegion := trace.StartRegion(ctx, "call _start")
nom := instance.GetExport(store, "_start").Func()
_, err = nom.Call(store)
callRegion.End()
if err != nil {
return nil, fmt.Errorf("call: %w", err)
}
// Print WASM stdout
stdoutBlob, err := os.ReadFile(stdoutPath)
if err != nil {
return nil, fmt.Errorf("read file: %w", err)
}
var resp plugin.CodeGenResponse
return &resp, resp.UnmarshalVT(stdoutBlob)
}