Skip to content

Commit

Permalink
SSA generation for basic language constructs (#3)
Browse files Browse the repository at this point in the history
* Tidy code and add some documentation

* Basic data structures for risc-v backend

* Produces SSA for basic operations

* SSA for loops, branches and memory access

* Implement some of intrinsics

* Update documentation and tidy up

* Remove multiple jumps at the end of basic block
  • Loading branch information
AdUhTkJm authored Dec 23, 2024
1 parent 95378a0 commit faf14be
Show file tree
Hide file tree
Showing 17 changed files with 1,370 additions and 357 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ You would also need to build the core library, as instructed in the following se

### Usage

MoonBit's core library is typically installed in `~/.moon/lib/core/`. In following commands, we use `$core` to denote the path. The language is shipped with pre-built libraries under different targets: `js`, `wasm` and `wasm-gc`; however, this compiler currently supports only `wasm-gc`. Let `$target` stand for this value.
MoonBit's core library is typically installed in `~/.moon/lib/core/`. In following commands, we use `$core` to denote the path. You can choose your target between `riscv` and `wasm-gc`, which we denote by `$target`. Currently, `riscv` will only produce a `.ssa` file for static single assignment IR, and does not proceed to generate assembly.

We use `$src` to denote the path to your main package. This package must contain, along with your source files, a `moon.pkg.json`; if you're not sure how this works, you can use [moon](https://github.com/moonbitlang/moon) to initialize a MoonBit repository.

Expand All @@ -67,15 +67,17 @@ moon bundle --source-dir $core

We strongly recommend that you build the core library yourself via the commands above. The pre-built binaries are not always compatible with this compiler, as MoonBit is still under development.

You should verify that there is a folder called `wasm-gc` under `$core/target`.
You should verify that now there is a folder called `wasm-gc` under `$core/target`.

Now you can compile `.mbt` files with these commands:

```bash
bundled=$core/target/$target/release/bundle
# Even if you are targeting RISC-V, you can still use this path.
# That's because it's intermediate representation (IR) in the bundle;
# it is ignorant of target.
bundled=$core/target/wasm-gc/release/bundle

# Here, main.mbt should be a file containing `fn main`.
# `build-package` produces intermediate representation (IR); it is ignorant of target.
moonc build-package $src/main.mbt -is-main -std-path $bundled -o $obj

# If you have more than one package, remember to include all of them in -pkg-sources. They should be separated by colon ':'.
Expand Down
6 changes: 4 additions & 2 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dune build -p moonbit-lang

### 使用

MoonBit 的核心库一般安装在 `~/.moon/lib/core` 下。在下面的命令中,我们会用 `$core` 表示核心库的安装路径。`$core/target` 下,有 `js`, `wasm``wasm-gc` 这三个文件夹,它们包含在对应目标下编译好的核心库。我们用 `$target` 表示这三者之一
MoonBit 的核心库一般安装在 `~/.moon/lib/core` 下。在下面的命令中,我们会用 `$core` 表示核心库的安装路径。你可以选择 `riscv``wasm-gc` 作为编译目标,我们用 `$target` 表示这两者之一。值得注意的是,目前 `riscv` 只会产生 SSA 文件,而不会产生汇编代码

`$src` 表示源代码的路径;在这个文件夹下,除了源代码之外还必须包括一个 `moon.pkg.json`。如果你不清楚如何编写这个文件,可以考虑使用 [moon](https://github.com/moonbitlang/moon) 来初始化。

Expand Down Expand Up @@ -70,7 +70,9 @@ moon bundle --source-dir $core
现在你可以使用这些命令来编译 `.mbt` 文件:

```bash
bundled=$core/target/$target/release/bundle
# 即使 $target 是 `riscv`,也依然可以使用这个路径。
# 这是因为 bundle 文件夹的内容是中间表示 (IR),它和编译目标无关。
bundled=$core/target/wasm-gc/release/bundle

# 这里 main.mbt 是一个含有 `fn main` 的文件。
moonc build-package $src/main.mbt -is-main -std-path $core/target/$bundled -o $obj -target $target
Expand Down
2 changes: 1 addition & 1 deletion src/ast_derive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1329,7 +1329,7 @@ let derive_from_json (trait : Syntax.type_name) (decl : Syntax.type_decl)
in
(S.pmap pattern, expr))
in
Lst.append_one map_cases err_case |> S.match_ json
List.append map_cases [err_case] |> S.match_ json
| Ptd_record fields ->
let vars = Lst.map fields (fun _ -> fresh_name "field") in
let pattern =
Expand Down
7 changes: 5 additions & 2 deletions src/basic_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@

module Map_string = Basic_map_string

type target = Wasm_gc
type target = Wasm_gc | Riscv

include struct
let sexp_of_target target = match target with
| Wasm_gc -> S.Atom "Wasm_gc"
| Riscv -> S.Atom "Riscv"

let hash_fold_target hsv arg =
Ppx_base.hash_fold_int hsv (match arg with
| Wasm_gc -> 1)
| Wasm_gc -> 1
| Riscv -> 2)

let hash_target arg =
Ppx_base.get_hash_value
Expand All @@ -37,6 +39,7 @@ type error_format = Human | Json

let parse_target_exn = function
| "wasm-gc" -> Wasm_gc
| "riscv" -> Riscv
| other -> raise (Arg.Bad ("unsupported target: " ^ other))

let parse_error_format_exn = function
Expand Down
124 changes: 50 additions & 74 deletions src/basic_core_ident.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,22 @@ module Key = struct
include struct
let _ = fun (_ : t) -> ()

let (hash_fold_t : Ppx_base.state -> t -> Ppx_base.state) =
(fun hsv arg ->
match arg with
| Pdot _a0 ->
let hsv = Ppx_base.hash_fold_int hsv 0 in
let hsv = hsv in
Qual_ident.hash_fold_t hsv _a0
| Plocal_method _a0 ->
let hsv = Ppx_base.hash_fold_int hsv 1 in
let hsv = hsv in
Ident.hash_fold_local_method hsv _a0
| Pident _ir ->
let hsv = Ppx_base.hash_fold_int hsv 2 in
let hsv =
let hsv = hsv in
Ppx_base.hash_fold_int hsv _ir.stamp
in
hsv
| Pmutable_ident _ir ->
let hsv = Ppx_base.hash_fold_int hsv 3 in
let hsv =
let hsv = hsv in
Ppx_base.hash_fold_int hsv _ir.stamp
in
hsv
: Ppx_base.state -> t -> Ppx_base.state)

let _ = hash_fold_t
let hash_fold_t hsv arg =
match arg with
| Pdot _a0 ->
let hsv = Ppx_base.hash_fold_int hsv 0 in
Qual_ident.hash_fold_t hsv _a0
| Plocal_method _a0 ->
let hsv = Ppx_base.hash_fold_int hsv 1 in
Ident.hash_fold_local_method hsv _a0
| Pident _ir ->
let hsv = Ppx_base.hash_fold_int hsv 2 in
let hsv = Ppx_base.hash_fold_int hsv _ir.stamp in
hsv
| Pmutable_ident _ir ->
let hsv = Ppx_base.hash_fold_int hsv 3 in
let hsv = Ppx_base.hash_fold_int hsv _ir.stamp in
hsv

let (hash : t -> Ppx_base.hash_value) =
let func arg =
Expand All @@ -65,52 +53,40 @@ module Key = struct
in
fun x -> func x

let _ = hash

let equal =
(fun a__001_ b__002_ ->
if Stdlib.( == ) a__001_ b__002_ then true
else
match (a__001_, b__002_) with
| Pdot _a__003_, Pdot _b__004_ -> Qual_ident.equal _a__003_ _b__004_
| Pdot _, _ -> false
| _, Pdot _ -> false
| Plocal_method _a__005_, Plocal_method _b__006_ ->
Ident.equal_local_method _a__005_ _b__006_
| Plocal_method _, _ -> false
| _, Plocal_method _ -> false
| Pident _a__007_, Pident _b__008_ ->
Stdlib.( = ) (_a__007_.stamp : int) _b__008_.stamp
| Pident _, _ -> false
| _, Pident _ -> false
| Pmutable_ident _a__009_, Pmutable_ident _b__010_ ->
Stdlib.( = ) (_a__009_.stamp : int) _b__010_.stamp
: t -> t -> bool)

let _ = equal

let compare =
(fun a__011_ b__012_ ->
if Stdlib.( == ) a__011_ b__012_ then 0
else
match (a__011_, b__012_) with
| Pdot _a__013_, Pdot _b__014_ ->
Qual_ident.compare _a__013_ _b__014_
| Pdot _, _ -> -1
| _, Pdot _ -> 1
| Plocal_method _a__015_, Plocal_method _b__016_ ->
Ident.compare_local_method _a__015_ _b__016_
| Plocal_method _, _ -> -1
| _, Plocal_method _ -> 1
| Pident _a__017_, Pident _b__018_ ->
Stdlib.compare (_a__017_.stamp : int) _b__018_.stamp
| Pident _, _ -> -1
| _, Pident _ -> 1
| Pmutable_ident _a__019_, Pmutable_ident _b__020_ ->
Stdlib.compare (_a__019_.stamp : int) _b__020_.stamp
: t -> t -> int)

let _ = compare
let equal a b =
if a == b then true
else match (a, b) with
| Pdot x, Pdot y -> Qual_ident.equal x y
| Pdot _, _ -> false
| _, Pdot _ -> false
| Plocal_method x, Plocal_method y ->
Ident.equal_local_method x y
| Plocal_method _, _ -> false
| _, Plocal_method _ -> false
| Pident x, Pident y ->
x.stamp = y.stamp
| Pident _, _ -> false
| _, Pident _ -> false
| Pmutable_ident x, Pmutable_ident y ->
x.stamp = y.stamp

let compare a b =
if a == b then 0
else match (a, b) with
| Pdot x, Pdot y ->
Qual_ident.compare x y
| Pdot _, _ -> -1
| _, Pdot _ -> 1
| Plocal_method x, Plocal_method y ->
Ident.compare_local_method x y
| Plocal_method _, _ -> -1
| _, Plocal_method _ -> 1
| Pident x, Pident y ->
Stdlib.compare x.stamp y.stamp
| Pident _, _ -> -1
| _, Pident _ -> 1
| Pmutable_ident x, Pmutable_ident y ->
Stdlib.compare x.stamp y.stamp
end

let to_string (x : t) =
Expand Down
Loading

0 comments on commit faf14be

Please sign in to comment.