提交 ee381daf 编写于 作者: 3 3dgen

Merge branch 'master' of https://github.com/wa-lang/wa

name: Deploy
on:
push:
branches:
- master
pull_request:
branches:
- master
types:
- closed
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- run: make -C internal/app/wawasm
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{ secrets.WA_DEPLOY }}
publish_dir: docs
publish_branch: gh-pages
force_orphan: true
user_name: "github-actions[bot]"
user_email: "github-actions[bot]@users.noreply.github.com"
......@@ -14,5 +14,6 @@ wat2wasm.exe
*.ll
*.s
*.out*
*.wasm
_target
<div align="center">
<h1>🇨🇳 凹语言™</h1>
[主页](https://wa-lang.org) | [Playground](https://wa-lang.org/playground) | [目标](https://wa-lang.org/goals.html) | [路线](https://wa-lang.org/smalltalk/st0002.html) | [社区](https://wa-lang.org/community) | [日志](https://wa-lang.org/changelog.html) | [论坛](https://github.com/wa-lang/wa/discussions)
</div>
<div align="center">
[![Build Status](https://github.com/wa-lang/wa/actions/workflows/wa.yml/badge.svg)](https://github.com/wa-lang/wa/actions/workflows/wa.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/wa-lang/wa)](https://goreportcard.com/report/github.com/wa-lang/wa)
[![Coverage Status](https://coveralls.io/repos/github/wa-lang/wa/badge.svg)](https://coveralls.io/github/wa-lang/wa)
[![GitHub release](https://img.shields.io/github/v/tag/wa-lang/wa.svg?label=release)](https://github.com/wa-lang/wa/releases)
[![Go Reference](https://pkg.go.dev/badge/github.com/wa-lang/wa.svg)](https://pkg.go.dev/github.com/wa-lang/wa)
[![license](https://img.shields.io/github/license/wa-lang/wa.svg)](https://github.com/wa-lang/wa/blob/master/LICENSE)
</div>
凹语言™(凹读音“Wa”)是 针对 WASM 平台设计的通用编程语言,同时支持 Linux、macOS 和 Windows 等主流操作系统和 Chrome 等浏览器环境,同时也支持作为独立Shell脚本和被嵌入脚本模式执行。
![](docs/images/logo/logo-animate1-blue.svg)
- 主页: [https://wa-lang.org](https://wa-lang.org)
- 代码仓库 (Gitee): [https://gitee.com/wa-lang/wa](https://gitee.com/wa-lang/wa)
- 代码仓库 (Github): [https://github.com/wa-lang/wa](https://github.com/wa-lang/wa)
- Go 参考文档: [https://pkg.go.dev/github.com/wa-lang/wa](https://pkg.go.dev/github.com/wa-lang/wa)
- 开发工具: [Playground](https://wa-lang.org/playground), [VSCode 插件](https://marketplace.visualstudio.com/items?itemName=xxxDeveloper.vscode-wa), [Fleet 插件](https://github.com/wa-lang/fleet-wa), [Vim 插件](https://github.com/wa-lang/vim-wa)
- 开发组: [柴树杉(chai2010)](https://github.com/chai2010)[丁尔男(Ending)](https://github.com/3dgen)[史斌(Benshi)](https://github.com/benshi001)[扈梦明(xxxDeveloper)](https://github.com/xxxDeveloper)[刘云峰(leaftree)](https://github.com/leaftree)[宋汝阳(ShiinaOrez)](https://github.com/ShiinaOrez)
## Playground 在线预览
[https://wa-lang.org/playground](https://wa-lang.org/playground)
![[![](https://wa-lang.org/smalltalk/images/st0011-01.png)](https://wa-lang.org/playground)](https://wa-lang.org/static/images/playground.gif)
## 本地安装和测试:
1. `go install github.com/wa-lang/wa@latest`
2. `wa init -name=_examples/hi`
3. `wa run _examples/hi`
> 项目尚处于原型开源阶段,如果有共建和PR需求请参考 [如何贡献代码](https://wa-lang.org/community/contribute.html)。
## 例子: 凹语言
打印字符和调用函数:
```wa
import "fmt"
fn main {
println("你好,凹语言!")
println(add(40, 2))
fmt.Println(1+1)
}
fn add(a: i32, b: i32) => i32 {
return a+b
}
```
运行并输出结果:
```
$ go run main.go hello.wa
你好,凹语言!
42
2
```
## 例子: 打印素数
打印 30 以内的素数:
```
# 版权 @2021 凹语言™ 作者。保留所有权利。
fn main {
for n := 2; n <= 30; n = n + 1 {
var isPrime int = 1
for i := 2; i*i <= n; i = i + 1 {
if x := n % i; x == 0 {
isPrime = 0
}
}
if isPrime != 0 {
println(n)
}
}
}
```
运行并输出结果:
```
$ go run main.go run _examples/prime
2
3
5
7
11
13
17
19
23
29
```
更多例子 [_examples](_examples)
## 作为脚本执行
凹语言本身也可以像 Lua 语言被嵌入 Go 宿主语言环境执行:
```
package main
import (
"fmt"
"github.com/wa-lang/wa/api"
)
func main() {
# TODO: fix example
output, err := api.RunCode("hello.wa", "fn main() { println(40+2) }")
fmt.Print(string(output), err)
}
```
注:作为脚本执行目前只支持本地环境。
## 版权(License)
版权 @2019-2022 凹语言™ 作者。保留所有权利。
<div align="center">
<h1>🇨🇳 凹语言™ The Wa Programming Language</h1>
[主页](https://wa-lang.org) | [Playground](https://wa-lang.org/playground) | [目标](https://wa-lang.org/goals.html) | [路线](https://wa-lang.org/smalltalk/st0002.html) | [社区](https://wa-lang.org/community) | [日志](https://wa-lang.org/changelog.html) | [论坛](https://github.com/wa-lang/wa/discussions)
<h1>🇨🇳 The Wa Programming Language</h1>
[Document](https://wa-lang.org) | [Playground](https://wa-lang.org/playground) | [Goals](https://wa-lang.org/goals.html) | [Roadmap](https://wa-lang.org/smalltalk/st0002.html) | [Community](https://wa-lang.org/community) | [Changelog](https://wa-lang.org/changelog.html) | [Discussions](https://github.com/wa-lang/wa/discussions)
......@@ -18,46 +16,44 @@
</div>
凹语言™(凹读音“Wa”)是 针对 WASM 平台设计的通用编程语言,同时支持 Linux、macOS 和 Windows 等主流操作系统和 Chrome 等浏览器环境,同时也支持作为独立Shell脚本和被嵌入脚本模式执行。
Wa is a general-purpose programming language designed for developing robustness and maintainability WebAssembly software.
Instead of requiring complex toolchains to set up, you can simply go install it - or run it in a browser.
![](docs/images/logo/logo-animate1-blue.svg)
- 主页 (Homepage): [https://wa-lang.org](https://wa-lang.org)
- 代码仓库 (Gitee): [https://gitee.com/wa-lang/wa](https://gitee.com/wa-lang/wa)
- 代码仓库 (Github): [https://github.com/wa-lang/wa](https://github.com/wa-lang/wa)
- Go 参考文档: [https://pkg.go.dev/github.com/wa-lang/wa](https://pkg.go.dev/github.com/wa-lang/wa)
- 开发工具 (Develop Tools): [Playground](https://wa-lang.org/playground), [VSCode 插件](https://marketplace.visualstudio.com/items?itemName=xxxDeveloper.vscode-wa), [Fleet 插件](https://github.com/wa-lang/fleet-wa), [Vim 插件](https://github.com/wa-lang/vim-wa)
- 开发组 (Core Team): [柴树杉(chai2010)](https://github.com/chai2010)[丁尔男(Ending)](https://github.com/3dgen)[史斌(Benshi)](https://github.com/benshi001)[扈梦明(xxxDeveloper)](https://github.com/xxxDeveloper)[刘云峰(leaftree)](https://github.com/leaftree)[宋汝阳(ShiinaOrez)](https://github.com/ShiinaOrez)
- Homepage: [https://wa-lang.org](https://wa-lang.org)
- Github: [https://github.com/wa-lang/wa](https://github.com/wa-lang/wa)
- Gitee: [https://gitee.com/wa-lang/wa](https://gitee.com/wa-lang/wa)
- Go Doc: [https://pkg.go.dev/github.com/wa-lang/wa](https://pkg.go.dev/github.com/wa-lang/wa)
- Develop Tools: [Playground](https://wa-lang.org/playground), [VSCode](https://marketplace.visualstudio.com/items?itemName=xxxDeveloper.vscode-wa), [Fleet](https://github.com/wa-lang/fleet-wa), [Vim](https://github.com/wa-lang/vim-wa)
- Core Team: [柴树杉(chai2010)](https://github.com/chai2010)[丁尔男(Ending)](https://github.com/3dgen)[史斌(Benshi)](https://github.com/benshi001)[扈梦明(xxxDeveloper)](https://github.com/xxxDeveloper)[刘云峰(leaftree)](https://github.com/leaftree)[宋汝阳(ShiinaOrez)](https://github.com/ShiinaOrez)
## Playground 在线预览
## Playground
[https://wa-lang.org/playground](https://wa-lang.org/playground)
![[![](https://wa-lang.org/smalltalk/images/st0011-01.png)](https://wa-lang.org/playground)](https://wa-lang.org/static/images/playground.gif)
## 本地安装和测试 (Install and Run):
## Install and Run:
1. `go install github.com/wa-lang/wa@latest`
2. `wa init -name=_examples/hi`
3. `wa run _examples/hi`
> 项目尚处于原型开源阶段,如果有共建和PR需求请参考 [如何贡献代码](https://wa-lang.org/community/contribute.html)。
> The Wa project is still in very early stage. If you want to submit PR, please read the [Contribution Guide(Chinese)](https://wa-lang.org/community/contribute.html).
## 例子: 凹语言 (Example: Print 凹语言)
## Example: Print Wa
打印字符和调用函数(Print rune and call function)
Print rune and call function
```wa
# Copyright @2019-2022 The Wa author. All rights reserved.
import "fmt"
fn main {
println("你好,凹语言!")
println("hello, Wa!")
println(add(40, 2))
fmt.Println(1+1)
......@@ -68,22 +64,20 @@ fn add(a: i32, b: i32) => i32 {
}
```
运行并输出结果 (Execute the program):
Execute the program:
```
$ go run main.go hello.wa
你好,凹语言!
hello, Wa!
42
2
```
## 例子: 打印素数 (Example: Print Prime)
## Example: Print Prime
打印 30 以内的素数 (Print prime numbers up to 30):
Print prime numbers up to 30:
```
# 版权 @2021 凹语言™ 作者。保留所有权利。
fn main {
for n := 2; n <= 30; n = n + 1 {
var isPrime int = 1
......@@ -99,7 +93,7 @@ fn main {
}
```
运行并输出结果 (Execute the program):
Execute the program:
```
$ go run main.go run _examples/prime
......@@ -115,11 +109,11 @@ $ go run main.go run _examples/prime
29
```
更多例子 (More examples) [_examples](_examples)
More examples [_examples](_examples)
## 作为脚本执行 (Execut as a script)
## Execut as a script
凹语言本身也可以像 Lua 语言被嵌入 Go 宿主语言环境执行 (The Wa language itself can also be executed like the Lua language embedded in the Go host locale):
The Wa language itself can also be executed like the Lua language embedded in the Go host locale:
```
package main
......@@ -130,13 +124,14 @@ import (
)
func main() {
# TODO: fix example
output, err := api.RunCode("hello.wa", "fn main() { println(40+2) }")
fmt.Print(string(output), err)
}
```
注:作为脚本执行目前只支持本地环境。(Note: Executing as a script currently only supports native environments.)
Note: Executing as a script currently only supports native environments.
## 版权(License)
## License
版权 @2019-2022 凹语言™ 作者。保留所有权利。(Copyrighe @2019-2022 The Wa author. All rights reserved.)
Copyright @2019-2022 The Wa author. All rights reserved.
# Test the llvm backend.
# Make Arduino's builtin LED blinking.
# `wa native --target=avr arduino_blink.wa`
#wa:linkname __avr_write_port__
fn write_port(p i16, v i8)
# Delay a period of time
var cnt i8
fn delay(n i32) {
for i := i32(0); i < n; i++ {
cnt++
}
}
fn main() {
# Set Pin #5 (connected with the builtin LED) of Port B to output mode.
write_port(0x24, 0x20)
for b := 0; ; b++ {
if (b % 2) == 0 {
# Turn on the LED.
write_port(0x25, 0x20)
} else {
# Turn off the LED.
write_port(0x25, 0x00)
}
# Delay a period of time
delay(99999)
}
}
# Test the llvm backend.
# Test bitwise logic.
var a i64 = 0x55555555
var b i64 = 0x33333333
var c i16 = 0x5555
var d i16 = 0x3333
var e u8 = 0x55
var f u8 = 0x33
fn main() {
println("not ", 0x55555555, " = ", bw_not(0x55555555))
println("not ", 0xaaaaaaaa, " = ", bw_not(0xaaaaaaaa))
println(a, " and ", b, " = ", bw_and(a, b), "(", 0x11111111, ")")
println(c, " or ", d, " = ", bw_or(c, d), "(", 0x7777, ")")
println(e, " xor ", f, " = ", bw_xor(e, f), "(", 0x66, ")")
}
fn bw_not(a u32) u32 {
return ^a
}
fn bw_and(a i64, b i64) i64 {
return a & b
}
fn bw_or(a i16, b i16) i16 {
return a | b
}
fn bw_xor(a u8, b u8) u8 {
return a ^ b
}
# Test the llvm backend.
# Test logical/arithmetic shift operations.
var ga i32 = -15
var gb i32 = 15
var gc i64 = -15
var gd i64 = 15
var ge u16 = 0xffcc
fn main() {
println(ga, " << ", 2, " = ", test_shl_0(ga, 2))
println(gb, " << ", 2, " = ", test_shl_1(gb, 2))
println(ga, " << ", 2, " = ", test_shl_2(ga, 2))
println(gc, " >> ", 2, " = ", test_ashr_0(gc, 2))
println(gd, " >> ", 2, " = ", test_ashr_1(gd, 2))
println(ge, " >> ", 2, " = ", test_lshr_0(ge, 2), "(", 0x3ff3, ")")
println(ge, " >> ", 2, " = ", test_lshr_1(ge, 2), "(", 0x3ff3, ")")
}
fn test_shl_0(a i32, b i64) i32 {
return a << b
}
fn test_shl_1(a i32, b i16) i32 {
return a << b
}
fn test_shl_2(a i32, b u16) i32 {
return a << b
}
fn test_ashr_0(a i64, b i64) i64 {
return a >> b
}
fn test_ashr_1(a i64, b u32) i64 {
return a >> b
}
fn test_lshr_0(a u16, b i32) u16 {
return a >> b
}
fn test_lshr_1(a u16, b u8) u16 {
return a >> b
}
......@@ -7,7 +7,6 @@ import (
"io/fs"
"github.com/wa-lang/wa/internal/backends/compiler_wat"
"github.com/wa-lang/wa/internal/backends/target_spec"
"github.com/wa-lang/wa/internal/config"
"github.com/wa-lang/wa/internal/format"
"github.com/wa-lang/wa/internal/loader"
......@@ -42,28 +41,6 @@ type PkgVFS = config.PkgVFS
// 指针和整数大小
type StdSize = config.StdSizes
// 目标机器
type Machine = target_spec.Machine
const (
Machine_default = Machine_Wasm32_wa // 默认输出的目标类型
Machine_Wasm32_wa = target_spec.Machine_Wasm32_wa // 凹语言定义的 WASM 规范
Machine_Wasm32_wasi = target_spec.Machine_Wasm32_wasi // WASI 定义的 WASM 规范
)
// 解析字符串类型
func ParseMachine(s string) (target Machine, ok bool) {
switch t := Machine(s); t {
case Machine_Wasm32_wa:
return t, true
case Machine_Wasm32_wasi:
return t, true
default:
return "", false
}
}
// 加载 WaModFile 文件
// 如果 vfs 为空则从本地文件系统读取
func LoadManifest(vfs fs.FS, appPath string) (p *Manifest, err error) {
......@@ -89,28 +66,26 @@ func LoadProgramVFS(vfs *config.PkgVFS, cfg *config.Config, pkgPath string) (*Pr
}
// 构建 wat 目标
func BuildFile(filename string, src interface{}, target Machine) (wat []byte, err error) {
cfg := config.DefaultConfig()
func BuildFile(cfg *config.Config, filename string, src interface{}) (wat []byte, err error) {
prog, err := LoadProgramFile(cfg, filename, src)
if err != nil || prog == nil {
logger.Tracef(&config.EnableTrace_api, "LoadProgramVFS failed, err = %v", err)
return nil, err
}
watOut, err := compiler_wat.New().Compile(prog, target)
watOut, err := compiler_wat.New().Compile(prog)
return []byte(watOut), err
}
// 构建 wat 目标
func BuildVFS(vfs *config.PkgVFS, appPkg string, target Machine) (wat []byte, err error) {
cfg := config.DefaultConfig()
func BuildVFS(cfg *config.Config, vfs *config.PkgVFS, appPkg string) (wat []byte, err error) {
prog, err := LoadProgramVFS(vfs, cfg, appPkg)
if err != nil || prog == nil {
logger.Tracef(&config.EnableTrace_api, "LoadProgramVFS failed, err = %v", err)
return nil, err
}
watOut, err := compiler_wat.New().Compile(prog, target)
watOut, err := compiler_wat.New().Compile(prog)
return []byte(watOut), err
}
......
......@@ -9,12 +9,13 @@ import (
"os"
"github.com/wa-lang/wa/internal/app/apputil"
"github.com/wa-lang/wa/internal/config"
)
// 执行凹代码
func RunCode(filename, code string) (stdoutStderr []byte, err error) {
func RunCode(cfg *config.Config, filename, code string) (stdoutStderr []byte, err error) {
// 编译为 wat 格式
wat, err := BuildFile(filename, code, Machine_Wasm32_wa)
wat, err := BuildFile(cfg, filename, code)
// wat 写到临时文件
outfile := "a.out.wat"
......
......@@ -7,6 +7,7 @@ import (
"log"
"github.com/wa-lang/wa/api"
"github.com/wa-lang/wa/internal/config"
)
func ExampleRunCode() {
......@@ -22,7 +23,7 @@ func ExampleRunCode() {
}
`
output, err := api.RunCode("hello.wa", code)
output, err := api.RunCode(config.DefaultConfig(), "hello.wa", code)
if err != nil {
log.Fatal(err)
}
......
https://wa-lang.org
......@@ -22,7 +22,6 @@ import (
"github.com/wa-lang/wa/internal/backends/compiler_c"
"github.com/wa-lang/wa/internal/backends/compiler_llvm"
"github.com/wa-lang/wa/internal/backends/compiler_wat"
"github.com/wa-lang/wa/internal/backends/target_spec"
"github.com/wa-lang/wa/internal/config"
"github.com/wa-lang/wa/internal/format"
"github.com/wa-lang/wa/internal/loader"
......@@ -34,15 +33,6 @@ import (
"github.com/wa-lang/wa/internal/waroot"
)
// 命令行选项
type Option struct {
Debug bool
TargetArch string
TargetOS string
Clang string
Llc string
}
// 命令行程序对象
type App struct {
opt Option
......@@ -341,6 +331,12 @@ func (p *App) LLVM(infile string, outfile string, target string, debug bool) err
if target != "" {
llc = append(llc, "-mtriple", target)
}
// Add target specific options.
switch target {
case "avr":
llc = append(llc, "-mcpu=atmega328")
default:
}
cmd0 := exec.Command(p.opt.Llc, llc...)
cmd0.Stderr = os.Stderr
if err := cmd0.Run(); err != nil {
......@@ -348,6 +344,35 @@ func (p *App) LLVM(infile string, outfile string, target string, debug bool) err
return err
}
// TODO: This is a temporary solution for AVR-Arduino. We generate
// an Arduino project instead of an ELF.
if target == "avr" {
// Create a new directory for the output Arduino project.
ext, outdir := path.Ext(outfile), ""
if len(ext) > 0 {
pos := strings.Index(outfile, ext)
outdir = outfile[0:pos]
}
if err := os.RemoveAll(outdir); err != nil {
return err
}
if err := os.Mkdir(outdir, 0755); err != nil {
return err
}
// Move the assembly file to the project directory.
newAsmFile := strings.ReplaceAll(asmfile, ".s", ".S")
if err := os.Rename(asmfile, path.Join(outdir, newAsmFile)); err != nil {
return err
}
// Create the project main '.ino' file.
inoFile := path.Join(outdir, path.Base(outdir)+".ino")
inoStr := "void setup(void) {}\nextern \"C\" { extern void wa_main(void); }\nvoid loop(void) { wa_main(); }\n"
if err := os.WriteFile(inoFile, []byte(inoStr), 0644); err != nil {
return err
}
return nil
}
// Invoke command `clang xxx.s -o outfile --target=xxx`.
clangArgs := []string{asmfile, "-static", "-o", outfile}
if target != "" {
......@@ -367,14 +392,14 @@ func (p *App) LLVM(infile string, outfile string, target string, debug bool) err
return nil
}
func (p *App) WASM(filename string, target target_spec.Machine) ([]byte, error) {
func (p *App) WASM(filename string) ([]byte, error) {
cfg := config.DefaultConfig()
prog, err := loader.LoadProgram(cfg, filename)
if err != nil {
return nil, err
}
output, err := compiler_wat.New().Compile(prog, target)
output, err := compiler_wat.New().Compile(prog)
if err != nil {
return nil, err
}
......
// 版权 @2019 凹语言 作者。保留所有权利。
package app
import "github.com/wa-lang/wa/internal/config"
// 命令行选项
type Option struct {
Debug bool
TargetArch string
TargetOS string
Clang string
Llc string
LD_StackSize int
LD_MaxMemory int
}
func (opt *Option) Config() *config.Config {
cfg := config.DefaultConfig()
if opt.Debug {
cfg.Debug = true
}
if opt.TargetArch != "" {
cfg.WaArch = opt.TargetArch
}
if opt.TargetOS != "" {
cfg.WaOS = opt.TargetOS
}
if opt.LD_StackSize != 0 {
cfg.LDFlags.StackSize = opt.LD_StackSize
}
if opt.LD_MaxMemory != 0 {
cfg.LDFlags.MaxMemory = opt.LD_MaxMemory
}
switch cfg.WaArch {
case "wasm":
cfg.WaSizes.MaxAlign = 4
cfg.WaSizes.WordSize = 4
case "amd64":
cfg.WaSizes.MaxAlign = 8
cfg.WaSizes.WordSize = 8
case "arm64":
cfg.WaSizes.MaxAlign = 8
cfg.WaSizes.WordSize = 8
default:
panic("todo")
}
return cfg
}
# 版权 @2022 凹语言 作者。保留所有权利。
default:
GOOS=js GOARCH=wasm go build -o wa.wasm
mv wa.wasm ../../../docs
clean:
// 版权 @2022 凹语言 作者。保留所有权利。
//go:build !wasm
// +build !wasm
package main
func main() {
println("only for build wa.wasm")
}
// 版权 @2022 凹语言 作者。保留所有权利。
package main
import (
"syscall/js"
"github.com/wa-lang/wa/api"
"github.com/wa-lang/wa/internal/config"
)
func main() {
window := js.Global().Get("window")
waCode := window.Get("waCode").String()
wat, err := api.BuildFile(config.DefaultConfig(), "hello.wa", waCode)
if err != nil {
window.Set("waWat", err.Error())
} else {
window.Set("waWat", string(wat))
}
}
......@@ -56,7 +56,7 @@ func (p *Compiler) Compile(prog *loader.Program) (output string, err error) {
}
// Emit some auxiliary functions.
p.output.WriteString("define void @main() {\n")
p.output.WriteString("define void @wa_main() {\n")
p.output.WriteString(" call void @")
p.output.WriteString(getNormalName(prog.SSAMainPkg.Pkg.Path() + ".init()\n"))
p.output.WriteString(" call void @")
......@@ -67,8 +67,22 @@ func (p *Compiler) Compile(prog *loader.Program) (output string, err error) {
// Emit some target specific functions.
switch getArch(p.target) {
case "", "x86_64", "aarch64":
p.output.WriteString("define void @main() {\n")
p.output.WriteString(" call void @wa_main()\n")
p.output.WriteString(" ret void\n")
p.output.WriteString("}\n\n")
p.output.WriteString("declare i32 @printf(i8* readonly, ...)\n")
case "avr":
p.output.WriteString("define void @__avr_write_port__(i16 %0, i8 zeroext %1) {\n")
p.output.WriteString(" %3 = inttoptr i16 %0 to i8*\n")
p.output.WriteString(" store volatile i8 %1, i8* %3, align 1\n")
p.output.WriteString(" ret void\n")
p.output.WriteString("}\n\n")
p.output.WriteString("define zeroext i8 @__avr_read_port__(i16 %0) {\n")
p.output.WriteString(" %2 = inttoptr i16 %0 to i8*\n")
p.output.WriteString(" %3 = load volatile i8, i8* %2, align 1\n")
p.output.WriteString(" ret i8 %3\n")
p.output.WriteString("}\n\n")
default:
}
......
......@@ -12,6 +12,10 @@ import (
)
func (p *Compiler) compileFunction(fn *ssa.Function) error {
if isTargetBuiltin(fn.LinkName(), p.target) || isTargetBuiltin(fn.Name(), p.target) {
return nil
}
// Translate return type.
var retTyStr string
rets := fn.Signature.Results()
......@@ -47,10 +51,18 @@ func (p *Compiler) compileFunction(fn *ssa.Function) error {
}
// Emit a proper function name.
p.output.WriteString("define ")
if len(fn.Blocks) == 0 {
p.output.WriteString("declare ")
} else {
p.output.WriteString("define ")
}
p.output.WriteString(retTyStr)
p.output.WriteString(" @")
p.output.WriteString(getNormalName(fn.Pkg.Pkg.Path() + "." + fn.Name()))
if len(fn.LinkName()) > 0 {
p.output.WriteString(fn.LinkName())
} else {
p.output.WriteString(getNormalName(fn.Pkg.Pkg.Path() + "." + fn.Name()))
}
p.output.WriteString("(")
// Translate arguments.
......@@ -70,7 +82,12 @@ func (p *Compiler) compileFunction(fn *ssa.Function) error {
p.output.WriteString(", ")
}
}
p.output.WriteString(") {\n")
if len(fn.Blocks) == 0 {
p.output.WriteString(")\n\n")
return nil
} else {
p.output.WriteString(") {\n")
}
// Translate Go SSA intermediate instructions.
for i, b := range fn.Blocks {
......
......@@ -218,9 +218,15 @@ func (p *Compiler) compileUnOp(val *ssa.UnOp) error {
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val.X))
case token.XOR:
p.output.WriteString("xor ")
p.output.WriteString(getTypeStr(val.X.Type(), p.target))
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val.X))
p.output.WriteString(", -1")
default:
p.output.WriteString(" ; " + val.Name() + " = " + val.String())
// panic("unsupported Value '" + val.Name() + " = " + val.String() + "'")
panic("unsupported Value '" + val.Name() + " = " + val.String() + "'")
}
p.output.WriteString("\n")
......@@ -240,6 +246,11 @@ func (p *Compiler) compileBinOp(val *ssa.BinOp) error {
token.GTR: "icmp sgt",
token.LEQ: "icmp sle",
token.GEQ: "icmp sge",
token.AND: "and",
token.OR: "or",
token.XOR: "xor",
token.SHL: "shl",
token.SHR: "ashr",
}
uintOpMap := map[token.Token]string{
token.ADD: "add",
......@@ -253,6 +264,11 @@ func (p *Compiler) compileBinOp(val *ssa.BinOp) error {
token.GTR: "icmp ugt",
token.LEQ: "icmp ule",
token.GEQ: "icmp uge",
token.AND: "and",
token.OR: "or",
token.XOR: "xor",
token.SHL: "shl",
token.SHR: "lshr",
}
floatOpMap := map[token.Token]string{
token.ADD: "fadd",
......@@ -278,8 +294,39 @@ func (p *Compiler) compileBinOp(val *ssa.BinOp) error {
opMap = uintOpMap
}
// Special process for float32 constants.
// Special process for shift operations.
xStr, yStr := "", ""
if val.Op == token.SHL || val.Op == token.SHR {
tyCOp := ""
switch {
case getTypeSize(val.X.Type(), p.target) < getTypeSize(val.Y.Type(), p.target):
tyCOp = "trunc"
case getTypeSize(val.X.Type(), p.target) > getTypeSize(val.Y.Type(), p.target):
_, yIsSigned := checkType(val.Y.Type())
if !isSigned || !yIsSigned {
tyCOp = "zext"
} else {
tyCOp = "sext"
}
default:
}
if tyCOp != "" {
yStr = fmt.Sprintf("%%tmp%d", rand.Int())
p.output.WriteString(" ")
p.output.WriteString(yStr)
p.output.WriteString(" = ")
p.output.WriteString(tyCOp)
p.output.WriteString(" ")
p.output.WriteString(getTypeStr(val.Y.Type(), p.target))
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val.Y))
p.output.WriteString(" to ")
p.output.WriteString(getTypeStr(val.X.Type(), p.target))
p.output.WriteString("\n")
}
}
// Special process for float32 constants.
if isConstFloat32(val.X) {
xStr = p.wrapConstFloat32(val.X)
} else {
......@@ -287,7 +334,7 @@ func (p *Compiler) compileBinOp(val *ssa.BinOp) error {
}
if isConstFloat32(val.Y) {
yStr = p.wrapConstFloat32(val.Y)
} else {
} else if yStr == "" {
yStr = getValueStr(val.Y)
}
......@@ -307,9 +354,7 @@ func (p *Compiler) compileBinOp(val *ssa.BinOp) error {
return nil
}
p.output.WriteString(" ; " + val.Name() + " = " + val.String() + "\n")
return nil
// panic("unsupported Value '" + val.Name() + " = " + val.String() + "'")
panic("unsupported Value '" + val.Name() + " = " + val.String() + "'")
}
func (p *Compiler) compileCall(val *ssa.Call) error {
......
......@@ -303,6 +303,7 @@ func getNormalName(name string) string {
name = strings.ReplaceAll(name, ".", "__")
name = strings.ReplaceAll(name, "$", "__")
name = strings.ReplaceAll(name, "/", "__")
name = strings.ReplaceAll(name, "#", "__")
return name
}
......@@ -315,3 +316,24 @@ func getRealType(ty types.Type) types.Type {
}
}
}
func isTargetBuiltin(fn string, target string) bool {
avr := []string{"__avr_write_port__", "__avr_read_port__"}
other := []string{"printf"}
var ts []string
switch getArch(target) {
case "avr":
ts = avr
default:
ts = other
}
for _, v := range ts {
if v == fn {
return true
}
}
return false
}
......@@ -3,11 +3,8 @@
package compiler_wat
import (
"fmt"
"github.com/wa-lang/wa/internal/backends/compiler_wat/wir"
"github.com/wa-lang/wa/internal/backends/compiler_wat/wir/wat"
"github.com/wa-lang/wa/internal/backends/target_spec"
"github.com/wa-lang/wa/internal/loader"
"github.com/wa-lang/wa/internal/ssa"
)
......@@ -26,15 +23,8 @@ func New() *Compiler {
return p
}
func (p *Compiler) Compile(prog *loader.Program, target target_spec.Machine) (output string, err error) {
switch target {
case target_spec.Machine_Wasm32_wa, "":
p.module.BaseWat = modBaseWat_wa
case target_spec.Machine_Wasm32_wasi:
p.module.BaseWat = modBaseWat_wasi
default:
return "", fmt.Errorf("compiler_wat.Compiler: unsupport target: %v", target)
}
func (p *Compiler) Compile(prog *loader.Program) (output string, err error) {
p.module.BaseWat = modBaseWat_wa
for _, pkg := range prog.Pkgs {
p.ssaPkg = pkg.SSAPkg
......
// 版权 @2019 凹语言 作者。保留所有权利。
package target_spec
// 目标机器
type Machine string
const (
Machine_Wasm32_wa Machine = "wasm32-wa" // 凹语言定义的 WASM 规范
Machine_Wasm32_wasi Machine = "wasm32-wasi" // WASI 定义的 WASM 规范
)
......@@ -17,7 +17,6 @@ import (
"github.com/wa-lang/wa/internal/3rdparty/cli"
"github.com/wa-lang/wa/internal/app"
"github.com/wa-lang/wa/internal/app/apputil"
"github.com/wa-lang/wa/internal/backends/target_spec"
"github.com/wa-lang/wa/internal/config"
)
......@@ -45,14 +44,6 @@ func main() {
Aliases: []string{"t"},
Usage: "set trace mode (*|app|compiler|loader)",
},
&cli.StringFlag{
Name: "clang",
Usage: "set llvm/clang path",
},
&cli.StringFlag{
Name: "llc",
Usage: "set llvm/llc path",
},
}
cliApp.Before = func(c *cli.Context) error {
......@@ -72,7 +63,7 @@ func main() {
}
ctx := app.NewApp(build_Options(c))
output, err := ctx.WASM(c.Args().First(), target_spec.Machine_Wasm32_wa)
output, err := ctx.WASM(c.Args().First())
if err != nil {
fmt.Println(err)
os.Exit(1)
......@@ -109,7 +100,10 @@ func main() {
Name: "debug",
Usage: "only for dev/debug",
Action: func(c *cli.Context) error {
wat, err := api.BuildFile("hello.wa", "fn main() { println(123) }", "")
wat, err := api.BuildFile(
config.DefaultConfig(),
"hello.wa", "fn main() { println(123) }",
)
if err != nil {
if len(wat) != 0 {
fmt.Println(string(wat))
......@@ -171,7 +165,7 @@ func main() {
}
ctx := app.NewApp(build_Options(c))
output, err := ctx.WASM(c.Args().First(), target_spec.Machine_Wasm32_wa)
output, err := ctx.WASM(c.Args().First())
if err != nil {
fmt.Println(err)
os.Exit(1)
......@@ -222,7 +216,7 @@ func main() {
},
&cli.StringFlag{
Name: "target",
Usage: "set target",
Usage: "set target (*wa|wasi|arduino)",
},
&cli.IntFlag{
Name: "ld-stack-size",
......@@ -241,21 +235,8 @@ func main() {
os.Exit(1)
}
var target target_spec.Machine
if s := c.String("target"); s != "" {
if t, ok := api.ParseMachine(s); ok {
target = t
} else {
fmt.Printf("invalid target: %q", s)
os.Exit(1)
}
}
if target == "" {
target = target_spec.Machine_Wasm32_wa
}
ctx := app.NewApp(build_Options(c))
output, err := ctx.WASM(c.Args().First(), target)
output, err := ctx.WASM(c.Args().First())
if err != nil {
fmt.Println(err)
os.Exit(1)
......@@ -296,6 +277,14 @@ func main() {
Name: "debug",
Usage: "dump orginal intermediate representation",
},
&cli.StringFlag{
Name: "clang",
Usage: "set llvm/clang path",
},
&cli.StringFlag{
Name: "llc",
Usage: "set llvm/llc path",
},
},
Action: func(c *cli.Context) error {
outfile := c.String("output")
......@@ -464,9 +453,26 @@ func main() {
}
func build_Options(c *cli.Context) *app.Option {
return &app.Option{
Debug: c.Bool("debug"),
Clang: c.String("clang"),
Llc: c.String("llc"),
opt := &app.Option{
Debug: c.Bool("debug"),
Clang: c.String("clang"),
Llc: c.String("llc"),
LD_StackSize: c.Int("ld-stack-size"),
LD_MaxMemory: c.Int("ld-max-memory"),
}
switch c.String("target") {
case "", "wa":
opt.TargetArch = "wasm"
opt.TargetOS = "wa"
case "wasi":
opt.TargetArch = "wasm"
opt.TargetOS = "wasi"
case "arduino":
opt.TargetArch = "wasm"
opt.TargetOS = "arduino"
default:
opt.TargetArch = "wasm"
opt.TargetOS = "unknown"
}
return opt
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册