Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wa-lang
wa
提交
0c9f5866
wa
项目概览
wa-lang
/
wa
12 个月 前同步成功
通知
68
Star
655
Fork
45
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
wa
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0c9f5866
编写于
7月 24, 2022
作者:
chai2010
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加 LLVM 后端
上级
919a51c4
变更
25
展开全部
隐藏空白更改
内联
并排
Showing
25 changed file
with
2639 addition
and
0 deletion
+2639
-0
internal/backends/compiler_ll/builtin/Makefile
internal/backends/compiler_ll/builtin/Makefile
+9
-0
internal/backends/compiler_ll/builtin/_builtin.c
internal/backends/compiler_ll/builtin/_builtin.c
+149
-0
internal/backends/compiler_ll/builtin/_builtin.ll
internal/backends/compiler_ll/builtin/_builtin.ll
+492
-0
internal/backends/compiler_ll/builtin/_builtin_wasm.ll
internal/backends/compiler_ll/builtin/_builtin_wasm.ll
+2
-0
internal/backends/compiler_ll/builtin/builtin.go
internal/backends/compiler_ll/builtin/builtin.go
+35
-0
internal/backends/compiler_ll/builtin/builtin.ll
internal/backends/compiler_ll/builtin/builtin.ll
+28
-0
internal/backends/compiler_ll/builtin/main.ll
internal/backends/compiler_ll/builtin/main.ll
+14
-0
internal/backends/compiler_ll/compile.go
internal/backends/compiler_ll/compile.go
+251
-0
internal/backends/compiler_ll/compile_builtin.go
internal/backends/compiler_ll/compile_builtin.go
+202
-0
internal/backends/compiler_ll/compile_func.go
internal/backends/compiler_ll/compile_func.go
+3
-0
internal/backends/compiler_ll/compile_helper.go
internal/backends/compiler_ll/compile_helper.go
+97
-0
internal/backends/compiler_ll/compile_instruction.go
internal/backends/compiler_ll/compile_instruction.go
+104
-0
internal/backends/compiler_ll/compile_instruction_value.go
internal/backends/compiler_ll/compile_instruction_value.go
+230
-0
internal/backends/compiler_ll/compile_named_obj.go
internal/backends/compiler_ll/compile_named_obj.go
+16
-0
internal/backends/compiler_ll/compile_type.go
internal/backends/compiler_ll/compile_type.go
+217
-0
internal/backends/compiler_ll/compile_value_const.go
internal/backends/compiler_ll/compile_value_const.go
+78
-0
internal/backends/compiler_ll/compile_value_zero.go
internal/backends/compiler_ll/compile_value_zero.go
+59
-0
internal/backends/compiler_ll/llutil/llutil.wa.go
internal/backends/compiler_ll/llutil/llutil.wa.go
+92
-0
internal/backends/compiler_ll/names.go
internal/backends/compiler_ll/names.go
+7
-0
internal/backends/compiler_ll/syscall/print.wa.go
internal/backends/compiler_ll/syscall/print.wa.go
+27
-0
internal/backends/compiler_ll/syscall/syscall.wa.go
internal/backends/compiler_ll/syscall/syscall.wa.go
+30
-0
internal/backends/compiler_ll/types/builtin.wa.go
internal/backends/compiler_ll/types/builtin.wa.go
+19
-0
internal/backends/compiler_ll/types/interface.wa.go
internal/backends/compiler_ll/types/interface.wa.go
+90
-0
internal/backends/compiler_ll/types/package.wa.go
internal/backends/compiler_ll/types/package.wa.go
+35
-0
internal/backends/compiler_ll/types/type.wa.go
internal/backends/compiler_ll/types/type.wa.go
+353
-0
未找到文件。
internal/backends/compiler_ll/builtin/Makefile
0 → 100644
浏览文件 @
0c9f5866
default
:
clang
-S
-emit-llvm
_builtin.c
clang
-Woverride-module
_builtin.ll main.ll
./a.out
||
echo
$$
?
builtin-ll
:
clang
-S
-emit-llvm
_builtin.c
clean
:
internal/backends/compiler_ll/builtin/_builtin.c
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ----------------------------------------------------------------------------
// bool
// ----------------------------------------------------------------------------
typedef
uint8_t
ugo_bool_t
;
// ----------------------------------------------------------------------------
// ugo_string_t
// ----------------------------------------------------------------------------
typedef
struct
{
char
*
data
;
int
size
;
}
ugo_string_t
;
ugo_string_t
*
ugo_string_new
(
int
size
,
const
char
*
data
)
{
ugo_string_t
*
p
=
malloc
(
sizeof
(
*
p
)
+
size
+
1
);
p
->
data
=
(
char
*
)(
p
+
1
);
p
->
size
=
size
;
if
(
data
!=
NULL
)
{
memcpy
(
p
->
data
,
data
,
size
);
p
->
data
[
size
]
=
'\0'
;
}
else
{
memset
(
p
->
data
,
0
,
size
+
1
);
}
return
p
;
}
ugo_string_t
*
ugo_string_clone
(
ugo_string_t
*
s
)
{
ugo_string_t
*
p
=
malloc
(
sizeof
(
*
p
)
+
s
->
size
+
1
);
memcpy
(
p
->
data
,
s
->
data
,
s
->
size
);
p
->
data
[
s
->
size
]
=
'\0'
;
p
->
size
=
s
->
size
;
return
p
;
}
void
ugo_string_free
(
ugo_string_t
*
s
)
{
free
(
s
);
}
// ----------------------------------------------------------------------------
// cstring
// ----------------------------------------------------------------------------
char
*
ugo_cstring_join
(
const
char
*
s1
,
const
char
*
s2
)
{
int
len1
=
strlen
(
s1
);
int
len2
=
strlen
(
s2
);
char
*
dst
=
malloc
(
len1
+
len2
+
1
);
strcpy
(
dst
,
s1
);
strcat
(
dst
,
s2
);
return
dst
;
}
char
*
ugo_cstring_slice
(
const
char
*
s
,
int
low
,
int
high
)
{
int
src_len
=
strlen
(
s
);
int
dst_len
=
0
;
char
*
dst
=
NULL
;
if
(
low
<
0
)
{
low
=
0
;
}
if
(
high
<
0
)
{
high
=
src_len
;
}
if
(
low
>=
src_len
)
{
low
=
src_len
-
1
;
}
if
(
high
>
src_len
)
{
low
=
src_len
;
}
dst_len
=
high
-
low
;
dst
=
malloc
(
dst_len
+
1
);
memcpy
(
dst
,
s
+
low
,
dst_len
);
dst
[
dst_len
]
=
'\0'
;
return
dst
;
}
int
ugo_cstring_index
(
const
char
*
s
,
int
idx
)
{
return
s
[
idx
];
}
int
ugo_cstring_cmp
(
const
char
*
s1
,
const
char
*
s2
)
{
return
strcmp
(
s1
,
s2
);
}
// ----------------------------------------------------------------------------
// ugo_print_xxx
// ----------------------------------------------------------------------------
int
ugo_print_rune
(
int
ch
)
{
return
printf
(
"%c"
,
ch
);
}
int
ugo_print_cstring
(
const
char
*
s
)
{
return
printf
(
"%s"
,
s
);
}
int
ugo_print_cstring_len
(
const
char
*
s
,
int
n
)
{
while
(
n
--
>
0
)
{
printf
(
"%c"
,
*
s
++
);
}
return
1
;
}
int
ugo_print_string
(
const
ugo_string_t
*
s
)
{
return
printf
(
"%.*s"
,
s
->
size
,
s
->
data
);
}
int
ugo_print_bool
(
ugo_bool_t
x
)
{
return
printf
(
"%s"
,
x
?
"true"
:
"false"
);
}
int
ugo_print_int
(
int
x
)
{
return
printf
(
"%d"
,
x
);
}
int
ugo_print_int64
(
int64_t
x
)
{
return
printf
(
"%lld"
,
x
);
}
int
ugo_print_ptr
(
void
*
p
)
{
return
printf
(
"0x%x"
,
p
,
p
);
}
int
ugo_printf
(
const
char
*
format
,
...)
{
va_list
args
;
int
n
;
va_start
(
args
,
format
);
n
=
vprintf
(
format
,
args
);
va_end
(
args
);
return
n
;
}
// ----------------------------------------------------------------------------
// builtin
// ----------------------------------------------------------------------------
int
ugo_builtin_println
(
int
x
)
{
return
printf
(
"%d
\n
"
,
x
);
}
int
ugo_builtin_exit
(
int
x
)
{
exit
(
x
);
return
0
;
}
// ----------------------------------------------------------------------------
// END
// ----------------------------------------------------------------------------
internal/backends/compiler_ll/builtin/_builtin.ll
0 → 100644
浏览文件 @
0c9f5866
此差异已折叠。
点击以展开。
internal/backends/compiler_ll/builtin/_builtin_wasm.ll
0 → 100644
浏览文件 @
0c9f5866
; declare i32 @ugo_builtin_println(i32*)
; declare i32 @ugo_builtin_println(i32)
internal/backends/compiler_ll/builtin/builtin.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
builtin
import
_
"embed"
//go:embed _builtin.ll
var
llBuiltin
string
//go:embed _builtin_wasm.ll
var
llBuiltin_wasm
string
func
GetBuiltinLL
(
goos
,
goarch
string
)
string
{
switch
goos
{
case
"wasm"
:
return
llBuiltin_wasm
case
"darwin"
:
case
"linux"
:
case
"windows"
:
}
return
llBuiltin
}
const
Header
=
`
declare i32 @ugo_builtin_println(i32)
declare i32 @ugo_builtin_exit(i32)
`
const
MainMain
=
`
define i32 @main() {
call i32() @ugo_main_init()
call i32() @ugo_main_main()
ret i32 0
}
`
internal/backends/compiler_ll/builtin/builtin.ll
0 → 100644
浏览文件 @
0c9f5866
; ModuleID = 'builtin.c'
source_filename
=
"builtin.c"
target
datalayout
=
"e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target
triple
=
"x86_64-apple-macosx10.15.4"
; Function Attrs: noinline nounwind optnone ssp uwtable
define
i32
@ugo_builtin_exit
(
i32
)
#0
{
%2
=
alloca
i32
,
align
4
store
i32
%0
,
i32
*
%2
,
align
4
%3
=
load
i32
,
i32
*
%2
,
align
4
call
void
@exit
(
i32
%3
)
#2
unreachable
}
; Function Attrs: noreturn
declare
void
@exit
(
i32
)
#1
attributes
#0
=
{
noinline
nounwind
optnone
ssp
uwtable
"correctly-rounded-divide-sqrt-fp-math"
=
"false"
"darwin-stkchk-strong-link"
"disable-tail-calls"
=
"false"
"frame-pointer"
=
"all"
"less-precise-fpmad"
=
"false"
"min-legal-vector-width"
=
"0"
"no-infs-fp-math"
=
"false"
"no-jump-tables"
=
"false"
"no-nans-fp-math"
=
"false"
"no-signed-zeros-fp-math"
=
"false"
"no-trapping-math"
=
"false"
"probe-stack"
=
"___chkstk_darwin"
"stack-protector-buffer-size"
=
"8"
"target-cpu"
=
"penryn"
"target-features"
=
"+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
"unsafe-fp-math"
=
"false"
"use-soft-float"
=
"false"
}
attributes
#1
=
{
noreturn
"correctly-rounded-divide-sqrt-fp-math"
=
"false"
"darwin-stkchk-strong-link"
"disable-tail-calls"
=
"false"
"frame-pointer"
=
"all"
"less-precise-fpmad"
=
"false"
"no-infs-fp-math"
=
"false"
"no-nans-fp-math"
=
"false"
"no-signed-zeros-fp-math"
=
"false"
"no-trapping-math"
=
"false"
"probe-stack"
=
"___chkstk_darwin"
"stack-protector-buffer-size"
=
"8"
"target-cpu"
=
"penryn"
"target-features"
=
"+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
"unsafe-fp-math"
=
"false"
"use-soft-float"
=
"false"
}
attributes
#2
=
{
noreturn
}
!llvm.module.flags
=
!{
!0
,
!1
,
!2
}
!llvm.ident
=
!{
!3
}
!0
=
!{
i32
2
,
!"SDK Version"
,
[
3
x
i32
]
[
i32
10
,
i32
15
,
i32
4
]}
!1
=
!{
i32
1
,
!"wchar_size"
,
i32
4
}
!2
=
!{
i32
7
,
!"PIC Level"
,
i32
2
}
!3
=
!{
!"Apple clang version 11.0.3 (clang-1103.0.32.62)"
}
internal/backends/compiler_ll/builtin/main.ll
0 → 100644
浏览文件 @
0c9f5866
declare
i32
@ugo_builtin_exit
(
i32
)
define
i32
@ugo_main_main
()
{
%t0
=
add
i32
0
,
40
; t0 = 40
%t1
=
add
i32
0
,
2
; t1 = 2
%t2
=
add
i32
%t0
,
%t1
; t2 = t1 + t1
call
i32
(
i32
)
@ugo_builtin_exit
(
i32
%t2
)
ret
i32
0
}
define
i32
@main
()
{
call
i32
()
@ugo_main_main
()
ret
i32
0
}
internal/backends/compiler_ll/compile.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"fmt"
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/config"
"github.com/wa-lang/wa/internal/loader"
"github.com/wa-lang/wa/internal/logger"
"github.com/wa-lang/wa/internal/ssa"
)
type
Compiler
struct
{
prog
*
loader
.
Program
module
*
llir
.
Module
curFunc
*
llir
.
Func
curLocals
map
[
ssa
.
Value
]
llvalue
.
Value
curBlockEntries
map
[
*
ssa
.
BasicBlock
]
*
llir
.
Block
// a *ssa.BasicBlock may be split up
phis
map
[
*
ssa
.
Phi
]
*
llir
.
InstPhi
llTypeNameMap
map
[
lltypes
.
Type
]
string
llNamedTypeMap
map
[
string
]
lltypes
.
Type
llFuncNameMap
map
[
*
llir
.
Func
]
string
llNamedFuncMap
map
[
string
]
*
llir
.
Func
compilePkgDoneMap
map
[
*
ssa
.
Package
]
bool
}
func
New
()
*
Compiler
{
return
&
Compiler
{}
}
func
(
p
*
Compiler
)
Compile
(
prog
*
loader
.
Program
)
(
output
string
,
err
error
)
{
p
.
prog
=
prog
p
.
module
=
llir
.
NewModule
()
p
.
llTypeNameMap
=
make
(
map
[
lltypes
.
Type
]
string
)
p
.
llNamedTypeMap
=
make
(
map
[
string
]
lltypes
.
Type
)
p
.
llFuncNameMap
=
make
(
map
[
*
llir
.
Func
]
string
)
p
.
llNamedFuncMap
=
make
(
map
[
string
]
*
llir
.
Func
)
p
.
compilePkgDoneMap
=
make
(
map
[
*
ssa
.
Package
]
bool
)
if
!
p
.
prog
.
Cfg
.
Debug
{
defer
func
()
{
//if r := recover(); r != nil {
// err = fmt.Errorf("%v", r)
//}
}()
}
// 定义 builtin 类型和函数
if
err
:=
p
.
defineBuiltin
();
err
!=
nil
{
return
""
,
err
}
// 编译全部包
for
_
,
pkg
:=
range
prog
.
SSAProgram
.
AllPackages
()
{
if
err
:=
p
.
compilePackage
(
pkg
);
err
!=
nil
{
return
""
,
err
}
}
// main 包入口
{
main_init
:=
p
.
getFunc
(
"main.init"
)
main_main
:=
p
.
getFunc
(
"main.main"
)
mainFunc
:=
p
.
module
.
NewFunc
(
"main"
,
lltypes
.
I32
)
mainFuncBlock
:=
mainFunc
.
NewBlock
(
"entry"
)
mainFuncBlock
.
NewCall
(
main_init
)
mainFuncBlock
.
NewCall
(
main_main
)
mainFuncBlock
.
NewRet
(
llconstant
.
NewInt
(
lltypes
.
I32
,
0
))
}
// 输出 LLIR 文件
return
p
.
module
.
String
(),
nil
}
func
(
p
*
Compiler
)
compilePackage
(
pkg
*
ssa
.
Package
)
(
err
error
)
{
// 已经编译过
if
p
.
compilePkgDoneMap
[
pkg
]
{
return
nil
}
// 成功编译后记录状态
defer
func
()
{
if
err
==
nil
{
p
.
compilePkgDoneMap
[
pkg
]
=
true
}
}()
// 先编译导入的包
for
_
,
importPkg
:=
range
pkg
.
Pkg
.
Imports
()
{
ssaPkg
:=
p
.
prog
.
Pkgs
[
importPkg
.
Path
()]
.
SSAPkg
if
err
:=
p
.
compilePackage
(
ssaPkg
);
err
!=
nil
{
return
err
}
}
// 定义类型
for
_
,
member
:=
range
pkg
.
Members
{
if
typ
,
ok
:=
member
.
(
*
ssa
.
Type
);
ok
{
if
err
:=
p
.
compileType
(
pkg
,
typ
);
err
!=
nil
{
return
err
}
}
}
// 定义常量
for
_
,
member
:=
range
pkg
.
Members
{
if
namedConst
,
ok
:=
member
.
(
*
ssa
.
NamedConst
);
ok
{
if
err
:=
p
.
compileNamedConst
(
pkg
,
namedConst
);
err
!=
nil
{
return
err
}
}
}
// 定义全局变量
for
_
,
member
:=
range
pkg
.
Members
{
if
g
,
ok
:=
member
.
(
*
ssa
.
Global
);
ok
{
if
err
:=
p
.
compileGlobal
(
pkg
,
g
);
err
!=
nil
{
return
err
}
}
}
// 声明函数
for
_
,
member
:=
range
pkg
.
Members
{
if
fn
,
ok
:=
member
.
(
*
ssa
.
Function
);
ok
{
if
err
:=
p
.
compileFuncDeclare
(
pkg
,
fn
);
err
!=
nil
{
return
err
}
}
}
// 定义函数
for
_
,
member
:=
range
pkg
.
Members
{
if
fn
,
ok
:=
member
.
(
*
ssa
.
Function
);
ok
{
if
err
:=
p
.
compileFunc
(
fn
);
err
!=
nil
{
return
err
}
}
}
return
nil
}
func
(
p
*
Compiler
)
compileNamedConst
(
pkg
*
ssa
.
Package
,
namedConst
*
ssa
.
NamedConst
)
error
{
return
nil
}
func
(
p
*
Compiler
)
compileGlobal
(
pkg
*
ssa
.
Package
,
g
*
ssa
.
Global
)
error
{
p
.
defGlobal
(
g
)
return
nil
}
func
(
p
*
Compiler
)
compileFuncDeclare
(
pkg
*
ssa
.
Package
,
fn
*
ssa
.
Function
)
error
{
logger
.
Tracef
(
&
config
.
EnableTrace_compiler
,
"pkgpath:%s, name=%s"
,
fn
.
Pkg
.
Pkg
.
Path
(),
fn
.
Pkg
.
Pkg
.
Name
())
var
mangledName
string
if
pkgName
:=
fn
.
Pkg
.
Pkg
.
Name
();
pkgName
==
"main"
||
pkgName
==
""
{
mangledName
=
fmt
.
Sprintf
(
"%s.%s"
,
"main"
,
fn
.
Name
())
}
else
{
mangledName
=
fmt
.
Sprintf
(
"%s.%s"
,
pkg
.
Pkg
.
Path
(),
fn
.
Name
())
}
p
.
curFunc
=
p
.
getFunc
(
mangledName
)
if
p
.
curFunc
==
nil
{
fnType
:=
p
.
toLLFuncType
(
fn
.
Signature
)
fnParams
:=
[]
*
llir
.
Param
{}
for
i
,
typ
:=
range
fnType
.
Params
{
fnParams
=
append
(
fnParams
,
llir
.
NewParam
(
fmt
.
Sprint
(
i
),
typ
))
}
p
.
curFunc
=
p
.
module
.
NewFunc
(
mangledName
,
fnType
.
RetType
,
fnParams
...
)
}
return
nil
}
func
(
p
*
Compiler
)
compileFunc
(
fn
*
ssa
.
Function
)
error
{
logger
.
Tracef
(
&
config
.
EnableTrace_compiler
,
"pkgpath=%s, name=%s"
,
fn
.
Pkg
.
Pkg
.
Path
(),
fn
.
Pkg
.
Pkg
.
Name
())
var
mangledName
string
if
pkgName
:=
fn
.
Pkg
.
Pkg
.
Name
();
pkgName
==
"main"
||
pkgName
==
""
{
mangledName
=
fmt
.
Sprintf
(
"%s.%s"
,
"main"
,
fn
.
Name
())
}
else
{
mangledName
=
fmt
.
Sprintf
(
"%s.%s"
,
fn
.
Pkg
.
Pkg
.
Path
(),
fn
.
Name
())
}
p
.
curFunc
=
p
.
getFunc
(
mangledName
)
if
p
.
curFunc
==
nil
{
fnType
:=
p
.
toLLFuncType
(
fn
.
Signature
)
fnParams
:=
[]
*
llir
.
Param
{}
for
i
,
typ
:=
range
fnType
.
Params
{
fnParams
=
append
(
fnParams
,
llir
.
NewParam
(
fmt
.
Sprint
(
i
),
typ
))
}
p
.
curFunc
=
p
.
module
.
NewFunc
(
mangledName
,
fnType
.
RetType
,
fnParams
...
)
}
p
.
curLocals
=
make
(
map
[
ssa
.
Value
]
llvalue
.
Value
)
p
.
curBlockEntries
=
make
(
map
[
*
ssa
.
BasicBlock
]
*
llir
.
Block
)
p
.
phis
=
make
(
map
[
*
ssa
.
Phi
]
*
llir
.
InstPhi
)
for
_
,
block
:=
range
fn
.
Blocks
{
p
.
curBlockEntries
[
block
]
=
p
.
curFunc
.
NewBlock
(
fmt
.
Sprintf
(
"block_%04d"
,
block
.
Index
))
}
for
_
,
block
:=
range
fn
.
Blocks
{
if
err
:=
p
.
compileBlock
(
block
);
err
!=
nil
{
return
err
}
}
// fix phis
for
expr
,
phi
:=
range
p
.
phis
{
var
incomings
[]
*
llir
.
Incoming
for
i
,
edge
:=
range
expr
.
Edges
{
x
:=
p
.
getValue
(
edge
)
pred
:=
p
.
curBlockEntries
[
expr
.
Block
()
.
Preds
[
i
]]
incomings
=
append
(
incomings
,
llir
.
NewIncoming
(
x
,
pred
))
}
phi
.
Incs
=
incomings
}
return
nil
}
func
(
p
*
Compiler
)
compileBlock
(
block
*
ssa
.
BasicBlock
)
error
{
llirBlock
:=
p
.
curBlockEntries
[
block
]
if
llirBlock
==
nil
{
panic
(
"unreachable"
)
}
for
_
,
ins
:=
range
block
.
Instrs
{
if
err
:=
p
.
compileInstruction
(
ins
);
err
!=
nil
{
return
err
}
}
if
llirBlock
.
Term
==
nil
{
llirBlock
.
Term
=
llir
.
NewUnreachable
()
}
return
nil
}
internal/backends/compiler_ll/compile_builtin.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"fmt"
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/config"
"github.com/wa-lang/wa/internal/logger"
"github.com/wa-lang/wa/internal/ssa"
)
func
(
p
*
Compiler
)
defineBuiltin
()
error
{
// syscall: int write(i32 fd, void* buf, int n)
p
.
module
.
NewFunc
(
"write"
,
lltypes
.
I64
,
llir
.
NewParam
(
"fd"
,
lltypes
.
I32
),
llir
.
NewParam
(
"buf"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
llir
.
NewParam
(
"size"
,
lltypes
.
I64
),
)
p
.
module
.
NewTypeDef
(
g_typ_complex64_name
,
lltypes
.
NewStruct
(
lltypes
.
Float
,
lltypes
.
Float
),
)
p
.
module
.
NewTypeDef
(
g_typ_complex128_name
,
lltypes
.
NewStruct
(
lltypes
.
Double
,
lltypes
.
Double
),
)
p
.
module
.
NewTypeDef
(
g_typ_string_name
,
lltypes
.
NewStruct
(
lltypes
.
NewPointer
(
lltypes
.
I8
),
lltypes
.
I64
),
)
p
.
module
.
NewFunc
(
"ugo_print_rune"
,
lltypes
.
I32
,
llir
.
NewParam
(
"x"
,
lltypes
.
I32
),
)
p
.
module
.
NewFunc
(
"ugo_print_bool"
,
lltypes
.
I32
,
llir
.
NewParam
(
"x"
,
lltypes
.
I8
),
)
p
.
module
.
NewFunc
(
"ugo_print_int"
,
lltypes
.
I32
,
llir
.
NewParam
(
"x"
,
lltypes
.
I32
),
)
p
.
module
.
NewFunc
(
"ugo_print_int64"
,
lltypes
.
I32
,
llir
.
NewParam
(
"x"
,
lltypes
.
I64
),
)
p
.
module
.
NewFunc
(
"ugo_print_ptr"
,
lltypes
.
I32
,
llir
.
NewParam
(
"p"
,
lltypes
.
I8Ptr
),
)
p
.
module
.
NewFunc
(
"ugo_print_cstring"
,
lltypes
.
I32
,
llir
.
NewParam
(
"s"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
)
p
.
module
.
NewFunc
(
"ugo_print_cstring_len"
,
lltypes
.
I32
,
llir
.
NewParam
(
"s"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
llir
.
NewParam
(
"n"
,
lltypes
.
I32
),
)
fn
:=
p
.
module
.
NewFunc
(
"ugo_printf"
,
lltypes
.
I32
,
llir
.
NewParam
(
"format"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
)
fn
.
Sig
.
Variadic
=
true
p
.
module
.
NewFunc
(
"ugo_cstring_join"
,
lltypes
.
NewPointer
(
lltypes
.
I8
),
llir
.
NewParam
(
"s0"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
llir
.
NewParam
(
"s1"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
)
p
.
module
.
NewFunc
(
"ugo_cstring_slice"
,
lltypes
.
NewPointer
(
lltypes
.
I8
),
llir
.
NewParam
(
"s"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
llir
.
NewParam
(
"low"
,
lltypes
.
I32
),
llir
.
NewParam
(
"high"
,
lltypes
.
I32
),
)
p
.
module
.
NewFunc
(
"ugo_cstring_index"
,
lltypes
.
I32
,
llir
.
NewParam
(
"s"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
llir
.
NewParam
(
"idx"
,
lltypes
.
I32
),
)
p
.
module
.
NewFunc
(
"ugo_cstring_cmp"
,
lltypes
.
I32
,
llir
.
NewParam
(
"s0"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
llir
.
NewParam
(
"s1"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
)
p
.
module
.
NewFunc
(
"ugo_string_new"
,
lltypes
.
NewPointer
(
p
.
getLLType
(
g_typ_string_name
),
),
llir
.
NewParam
(
"size"
,
lltypes
.
I32
),
llir
.
NewParam
(
"data"
,
lltypes
.
NewPointer
(
lltypes
.
I8
)),
)
p
.
module
.
NewFunc
(
"ugo_print_string"
,
lltypes
.
I32
,
llir
.
NewParam
(
"s"
,
lltypes
.
NewPointer
(
p
.
getLLType
(
g_typ_string_name
),
)),
)
return
nil
}
func
(
p
*
Compiler
)
callBuiltin
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
)
llvalue
.
Value
{
logger
.
Tracef
(
&
config
.
EnableTrace_compiler
,
"expr=%v, builtin=%v"
,
expr
,
builtin
)
switch
builtin
.
Name
()
{
case
"print"
,
"println"
:
for
i
,
arg
:=
range
expr
.
Common
()
.
Args
{
if
i
>
0
{
p
.
builtin_print_space
(
expr
,
builtin
)
}
arg
:=
p
.
getValue
(
arg
)
if
p
.
llIsStrType
(
arg
.
Type
())
{
p
.
builtin_print_str
(
expr
,
builtin
,
arg
)
continue
}
switch
typ
:=
arg
.
Type
()
.
(
type
)
{
case
*
lltypes
.
IntType
:
switch
typ
.
BitSize
{
case
32
:
p
.
builtin_print_int
(
expr
,
builtin
,
arg
)
case
64
:
p
.
builtin_print_int64
(
expr
,
builtin
,
arg
)
}
default
:
// todo: string => *lltypes.StructType
fmt
.
Printf
(
"callBuiltin: %T, %v
\n
"
,
typ
,
p
.
llIsStrType
(
typ
))
}
}
if
builtin
.
Name
()
==
"println"
{
p
.
builtin_print_newline
(
expr
,
builtin
)
}
return
nil
}
return
nil
}
func
(
p
*
Compiler
)
builtin_print_str
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
,
arg
llvalue
.
Value
)
llvalue
.
Value
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
switch
x
:=
arg
.
(
type
)
{
case
*
llir
.
Param
:
logger
.
Panicf
(
"TODO: arg: %T, %v"
,
arg
,
arg
)
panic
(
"unreachable"
)
case
*
llconstant
.
Struct
:
data
:=
x
.
Fields
[
0
]
.
(
*
llconstant
.
CharArray
)
_p0
:=
llirBlock
.
NewAlloca
(
data
.
Typ
)
llirBlock
.
NewStore
(
data
,
_p0
)
_p_data00
:=
llirBlock
.
NewGetElementPtr
(
data
.
Typ
,
_p0
,
llconstant
.
NewInt
(
lltypes
.
I64
,
0
),
llconstant
.
NewInt
(
lltypes
.
I64
,
0
),
)
_size32
:=
llconstant
.
NewInt
(
lltypes
.
I32
,
int64
(
len
(
data
.
X
)))
llirBlock
.
NewCall
(
p
.
getFunc
(
"ugo_print_cstring_len"
),
_p_data00
,
_size32
)
return
nil
default
:
logger
.
Panicf
(
"arg: %T, %v"
,
arg
,
arg
)
panic
(
"unreachable"
)
}
}
func
(
p
*
Compiler
)
builtin_print_newline
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
)
llvalue
.
Value
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
llirBlock
.
NewCall
(
p
.
getFunc
(
"ugo_print_rune"
),
llconstant
.
NewInt
(
lltypes
.
I32
,
'\n'
))
return
nil
}
func
(
p
*
Compiler
)
builtin_print_int
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
,
arg
llvalue
.
Value
)
llvalue
.
Value
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
llirBlock
.
NewCall
(
p
.
getFunc
(
"ugo_print_int"
),
arg
)
return
nil
}
func
(
p
*
Compiler
)
builtin_print_int64
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
,
arg
llvalue
.
Value
)
llvalue
.
Value
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
llirBlock
.
NewCall
(
p
.
getFunc
(
"ugo_print_int64"
),
arg
)
return
nil
}
func
(
p
*
Compiler
)
builtin_print_rune
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
,
arg
rune
)
llvalue
.
Value
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
llirBlock
.
NewCall
(
p
.
getFunc
(
"ugo_print_rune"
),
llconstant
.
NewInt
(
lltypes
.
I32
,
int64
(
arg
)))
return
nil
}
func
(
p
*
Compiler
)
builtin_print_space
(
expr
*
ssa
.
Call
,
builtin
*
ssa
.
Builtin
)
llvalue
.
Value
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
llirBlock
.
NewCall
(
p
.
getFunc
(
"ugo_print_rune"
),
llconstant
.
NewInt
(
lltypes
.
I32
,
' '
))
return
nil
}
internal/backends/compiler_ll/compile_func.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
internal/backends/compiler_ll/compile_helper.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"fmt"
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/logger"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/types"
)
func
(
p
*
Compiler
)
getLLType
(
typName
string
)
lltypes
.
Type
{
for
_
,
typ
:=
range
p
.
module
.
TypeDefs
{
if
typ
.
Name
()
==
typName
{
return
typ
}
}
return
nil
}
func
(
p
*
Compiler
)
getLLFunc
(
fnName
string
)
*
llir
.
Func
{
for
_
,
x
:=
range
p
.
module
.
Funcs
{
if
x
.
Name
()
==
fnName
{
return
x
}
}
return
nil
}
// 定义全局变量
func
(
p
*
Compiler
)
defGlobal
(
g
*
ssa
.
Global
)
{
mangledName
:=
fmt
.
Sprintf
(
"%s.%s"
,
g
.
Pkg
.
Pkg
.
Path
(),
g
.
Name
())
// 全局变量类似一个地址, 需要取其指向的元素类型
typ
:=
p
.
toLLType
(
g
.
Type
()
.
(
*
types
.
Pointer
)
.
Elem
())
glob
:=
p
.
module
.
NewGlobal
(
mangledName
,
typ
)
glob
.
Init
=
llconstant
.
NewZeroInitializer
(
typ
)
}
// 根据名字查询全局变量
func
(
p
*
Compiler
)
getGlobal
(
g
*
ssa
.
Global
)
*
llir
.
Global
{
mangledName
:=
fmt
.
Sprintf
(
"%s.%s"
,
g
.
Pkg
.
Pkg
.
Path
(),
g
.
Name
())
for
_
,
x
:=
range
p
.
module
.
Globals
{
if
x
.
Name
()
==
mangledName
{
return
x
}
}
return
nil
}
func
(
p
*
Compiler
)
getLocal
(
expr
ssa
.
Value
)
llvalue
.
Value
{
x
,
ok
:=
p
.
curLocals
[
expr
]
if
!
ok
{
logger
.
Debugln
(
expr
,
"not found"
)
}
return
x
}
func
(
p
*
Compiler
)
defLocal
(
block
*
llir
.
Block
,
expr
ssa
.
Value
)
llvalue
.
Value
{
if
x
,
ok
:=
p
.
curLocals
[
expr
];
ok
{
return
x
}
x
:=
block
.
NewAlloca
(
p
.
toLLType
(
expr
.
Type
()))
p
.
curLocals
[
expr
]
=
x
return
x
}
func
(
p
*
Compiler
)
getFunc
(
name
string
)
*
llir
.
Func
{
for
_
,
fn
:=
range
p
.
module
.
Funcs
{
if
fn
.
Name
()
==
name
{
return
fn
}
}
return
nil
}
func
(
p
*
Compiler
)
mustGetFunc
(
name
string
)
*
llir
.
Func
{
if
fn
:=
p
.
getFunc
(
name
);
fn
!=
nil
{
return
fn
}
panic
(
fmt
.
Sprintf
(
"mustGetFunc: %s not found"
,
name
))
}
func
(
p
*
Compiler
)
getBlock
(
name
string
)
*
llir
.
Block
{
if
p
.
curFunc
==
nil
{
return
nil
}
for
_
,
block
:=
range
p
.
curFunc
.
Blocks
{
if
block
.
Name
()
==
name
{
return
block
}
}
return
nil
}
internal/backends/compiler_ll/compile_instruction.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"fmt"
"github.com/wa-lang/wa/internal/ssa"
)
func
(
p
*
Compiler
)
compileInstruction
(
ins
ssa
.
Instruction
)
error
{
switch
ins
:=
ins
.
(
type
)
{
default
:
return
p
.
compileInstruction_value
(
ins
)
case
*
ssa
.
DebugRef
:
return
p
.
compileInstruction_DebugRef
(
ins
)
case
*
ssa
.
Defer
:
return
p
.
compileInstruction_Defer
(
ins
)
case
*
ssa
.
If
:
return
p
.
compileInstruction_If
(
ins
)
case
*
ssa
.
Jump
:
return
p
.
compileInstruction_Jump
(
ins
)
case
*
ssa
.
MapUpdate
:
return
p
.
compileInstruction_MapUpdate
(
ins
)
case
*
ssa
.
Panic
:
return
p
.
compileInstruction_Panic
(
ins
)
case
*
ssa
.
Return
:
return
p
.
compileInstruction_Return
(
ins
)
case
*
ssa
.
RunDefers
:
return
p
.
compileInstruction_RunDefers
(
ins
)
case
*
ssa
.
Store
:
return
p
.
compileInstruction_Store
(
ins
)
}
}
func
(
p
*
Compiler
)
compileInstruction_value
(
ins
ssa
.
Instruction
)
error
{
if
ssaValue
,
ok
:=
ins
.
(
ssa
.
Value
);
ok
{
p
.
curLocals
[
ssaValue
]
=
p
.
getValue
(
ssaValue
)
return
nil
}
return
fmt
.
Errorf
(
"unknown Instruction(%T)"
,
ins
)
}
func
(
p
*
Compiler
)
compileInstruction_DebugRef
(
ins
*
ssa
.
DebugRef
)
error
{
panic
(
"TODO: *ssa.DebugRef"
)
}
func
(
p
*
Compiler
)
compileInstruction_Defer
(
ins
*
ssa
.
Defer
)
error
{
panic
(
"TODO: *ssa.Defer"
)
}
func
(
p
*
Compiler
)
compileInstruction_If
(
ins
*
ssa
.
If
)
error
{
llirBlock
:=
p
.
curBlockEntries
[
ins
.
Block
()]
cond
:=
p
.
getValue
(
ins
.
Cond
)
blockTrue
:=
p
.
curBlockEntries
[
ins
.
Block
()
.
Succs
[
0
]]
blockElse
:=
p
.
curBlockEntries
[
ins
.
Block
()
.
Succs
[
1
]]
llirBlock
.
NewCondBr
(
cond
,
blockTrue
,
blockElse
)
return
nil
}
func
(
p
*
Compiler
)
compileInstruction_Jump
(
ins
*
ssa
.
Jump
)
error
{
llirBlock
:=
p
.
curBlockEntries
[
ins
.
Block
()]
blockJump
:=
p
.
curBlockEntries
[
ins
.
Block
()
.
Succs
[
0
]]
llirBlock
.
NewBr
(
blockJump
)
return
nil
}
func
(
p
*
Compiler
)
compileInstruction_MapUpdate
(
ins
*
ssa
.
MapUpdate
)
error
{
panic
(
"TODO: *ssa.MapUpdate"
)
}
func
(
p
*
Compiler
)
compileInstruction_Panic
(
ins
*
ssa
.
Panic
)
error
{
panic
(
"TODO: *ssa.Panic"
)
}
func
(
p
*
Compiler
)
compileInstruction_Return
(
ins
*
ssa
.
Return
)
error
{
llirBlock
:=
p
.
curBlockEntries
[
ins
.
Block
()]
switch
{
case
len
(
ins
.
Results
)
==
0
:
llirBlock
.
NewRet
(
nil
)
case
len
(
ins
.
Results
)
==
1
:
llirBlock
.
NewRet
(
p
.
getValue
(
ins
.
Results
[
0
]))
default
:
return
fmt
.
Errorf
(
"todo: Multiple return values"
)
}
return
nil
}
func
(
p
*
Compiler
)
compileInstruction_RunDefers
(
ins
*
ssa
.
RunDefers
)
error
{
panic
(
"TODO: *ssa.RunDefers"
)
}
func
(
p
*
Compiler
)
compileInstruction_Store
(
ins
*
ssa
.
Store
)
error
{
llirBlock
:=
p
.
curBlockEntries
[
ins
.
Block
()]
dst
:=
p
.
getValue
(
ins
.
Addr
)
src
:=
p
.
getValue
(
ins
.
Val
)
llirBlock
.
NewStore
(
src
,
dst
)
return
nil
}
internal/backends/compiler_ll/compile_instruction_value.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"fmt"
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/llenum"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/token"
)
func
(
p
*
Compiler
)
getValue
(
expr
ssa
.
Value
)
(
v
llvalue
.
Value
)
{
if
x
,
ok
:=
p
.
curLocals
[
expr
];
ok
{
return
x
}
defer
func
()
{
p
.
curLocals
[
expr
]
=
v
}()
switch
expr
:=
expr
.
(
type
)
{
case
*
ssa
.
Const
:
return
p
.
compileValue_Const
(
expr
)
case
*
ssa
.
Function
:
return
p
.
compileValue_Function
(
expr
)
case
*
ssa
.
Global
:
return
p
.
compileValue_Global
(
expr
)
case
*
ssa
.
Convert
:
return
p
.
compileValue_Convert
(
expr
)
case
*
ssa
.
UnOp
:
return
p
.
compileValue_UnOp
(
expr
)
case
*
ssa
.
Parameter
:
return
p
.
compileValue_Parameter
(
expr
)
case
*
ssa
.
BinOp
:
return
p
.
compileValue_BinOp
(
expr
)
case
*
ssa
.
Phi
:
return
p
.
compileValue_Phi
(
expr
)
case
*
ssa
.
Call
:
return
p
.
compileValue_Call
(
expr
)
}
fmt
.
Printf
(
"todo: Compiler.getValue(expr.type=%T, expr.val=%+v)
\n
"
,
expr
,
expr
)
return
nil
}
func
(
p
*
Compiler
)
compileValue_Const
(
expr
*
ssa
.
Const
)
(
v
llvalue
.
Value
)
{
return
p
.
constValue
(
expr
)
}
func
(
p
*
Compiler
)
compileValue_Function
(
expr
*
ssa
.
Function
)
(
v
llvalue
.
Value
)
{
panic
(
"TODO"
)
}
func
(
p
*
Compiler
)
compileValue_Global
(
expr
*
ssa
.
Global
)
(
v
llvalue
.
Value
)
{
return
p
.
getGlobal
(
expr
)
}
func
(
p
*
Compiler
)
compileValue_Convert
(
expr
*
ssa
.
Convert
)
(
v
llvalue
.
Value
)
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
return
llirBlock
.
NewTrunc
(
p
.
getValue
(
expr
.
X
),
p
.
toLLType
(
expr
.
Type
()))
}
func
(
p
*
Compiler
)
compileValue_UnOp
(
expr
*
ssa
.
UnOp
)
(
v
llvalue
.
Value
)
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
switch
expr
.
Op
{
case
token
.
MUL
:
return
llirBlock
.
NewLoad
(
p
.
toLLType
(
expr
.
Type
()),
p
.
getValue
(
expr
.
X
))
default
:
panic
(
"TODO"
)
}
}
func
(
p
*
Compiler
)
compileValue_Parameter
(
expr
*
ssa
.
Parameter
)
(
v
llvalue
.
Value
)
{
for
i
,
x
:=
range
expr
.
Parent
()
.
Params
{
if
x
==
expr
{
return
p
.
curFunc
.
Params
[
i
]
}
}
return
nil
}
func
(
p
*
Compiler
)
compileValue_BinOp
(
expr
*
ssa
.
BinOp
)
(
v
llvalue
.
Value
)
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
switch
expr
.
Op
{
case
token
.
ADD
:
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isStrType
(
expr
.
X
.
Type
())
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
return
llirBlock
.
NewCall
(
p
.
getLLFunc
(
"ugo_cstring_join"
),
x
,
y
)
}
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFAdd
(
x
,
y
)
}
return
llirBlock
.
NewAdd
(
x
,
y
)
case
token
.
SUB
:
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFSub
(
x
,
y
)
}
return
llirBlock
.
NewSub
(
x
,
y
)
case
token
.
MUL
:
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFMul
(
x
,
y
)
}
return
llirBlock
.
NewMul
(
x
,
y
)
case
token
.
QUO
:
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFDiv
(
x
,
y
)
}
return
llirBlock
.
NewSDiv
(
x
,
y
)
case
token
.
REM
:
// %
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFRem
(
x
,
y
)
}
return
llirBlock
.
NewSRem
(
x
,
y
)
case
token
.
EQL
:
// ==
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isStrType
(
expr
.
X
.
Type
())
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
cmpRet
:=
llirBlock
.
NewCall
(
p
.
getLLFunc
(
"ugo_cstring_cmp"
),
x
,
y
)
cond
:=
llirBlock
.
NewICmp
(
llenum
.
IPredNE
,
cmpRet
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
))
return
cond
}
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFCmp
(
llenum
.
FPredOEQ
,
x
,
y
)
}
return
llirBlock
.
NewICmp
(
llenum
.
IPredEQ
,
x
,
y
)
case
token
.
NEQ
:
// !=
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isStrType
(
expr
.
X
.
Type
())
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
cmpRet
:=
llirBlock
.
NewCall
(
p
.
getLLFunc
(
"ugo_cstring_cmp"
),
x
,
y
)
cond
:=
llirBlock
.
NewICmp
(
llenum
.
IPredEQ
,
cmpRet
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
))
return
cond
}
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFCmp
(
llenum
.
FPredONE
,
x
,
y
)
}
return
llirBlock
.
NewICmp
(
llenum
.
IPredNE
,
x
,
y
)
case
token
.
LSS
:
// <
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFCmp
(
llenum
.
FPredOLT
,
x
,
y
)
}
return
llirBlock
.
NewICmp
(
llenum
.
IPredSLT
,
x
,
y
)
case
token
.
GTR
:
// >
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFCmp
(
llenum
.
FPredOGT
,
x
,
y
)
}
return
llirBlock
.
NewICmp
(
llenum
.
IPredSGT
,
x
,
y
)
case
token
.
LEQ
:
// <=
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFCmp
(
llenum
.
FPredOLE
,
x
,
y
)
}
return
llirBlock
.
NewICmp
(
llenum
.
IPredSLE
,
x
,
y
)
case
token
.
GEQ
:
// <=
x
:=
p
.
getValue
(
expr
.
X
)
y
:=
p
.
getValue
(
expr
.
Y
)
if
p
.
isFloatType
(
expr
.
X
.
Type
())
{
return
llirBlock
.
NewFCmp
(
llenum
.
FPredOGE
,
x
,
y
)
}
return
llirBlock
.
NewICmp
(
llenum
.
IPredSGE
,
x
,
y
)
}
panic
(
fmt
.
Sprintf
(
"TODO: op: %+v"
,
expr
.
Op
))
}
func
(
p
*
Compiler
)
compileValue_Phi
(
expr
*
ssa
.
Phi
)
(
v
llvalue
.
Value
)
{
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
var
incomings
[]
*
llir
.
Incoming
for
i
,
edge
:=
range
expr
.
Edges
{
x
:=
p
.
zeroValue
(
edge
.
Type
())
pred
:=
p
.
curBlockEntries
[
expr
.
Block
()
.
Preds
[
i
]]
incomings
=
append
(
incomings
,
llir
.
NewIncoming
(
x
,
pred
))
}
phi
:=
llirBlock
.
NewPhi
(
incomings
...
)
p
.
phis
[
expr
]
=
phi
return
phi
}
func
(
p
*
Compiler
)
compileValue_Call
(
expr
*
ssa
.
Call
)
(
v
llvalue
.
Value
)
{
if
builtin
,
ok
:=
expr
.
Call
.
Value
.
(
*
ssa
.
Builtin
);
ok
{
return
p
.
callBuiltin
(
expr
,
builtin
)
}
if
expr
.
Call
.
Method
==
nil
{
if
fn
,
ok
:=
expr
.
Call
.
Value
.
(
*
ssa
.
Function
);
ok
{
var
mangledName
string
if
fn
.
Pkg
.
Pkg
.
Name
()
==
"main"
{
mangledName
=
fmt
.
Sprintf
(
"%s.%s"
,
fn
.
Pkg
.
Pkg
.
Name
(),
fn
.
Name
())
}
else
{
mangledName
=
fmt
.
Sprintf
(
"%s.%s"
,
fn
.
Pkg
.
Pkg
.
Path
(),
fn
.
Name
())
}
fn
:=
p
.
getFunc
(
mangledName
)
var
args
[]
llvalue
.
Value
for
_
,
arg
:=
range
expr
.
Common
()
.
Args
{
args
=
append
(
args
,
p
.
getValue
(
arg
))
}
llirBlock
:=
p
.
curBlockEntries
[
expr
.
Block
()]
return
llirBlock
.
NewCall
(
fn
,
args
...
)
}
}
panic
(
"TODO"
)
}
internal/backends/compiler_ll/compile_named_obj.go
0 → 100644
浏览文件 @
0c9f5866
package
compiler
import
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
func
(
p
*
Compiler
)
llGetNamedType
(
mangledName
string
)
lltypes
.
Type
{
return
p
.
llNamedTypeMap
[
mangledName
]
}
func
(
p
*
Compiler
)
llGetTypeName
(
typ
lltypes
.
Type
)
string
{
return
p
.
llTypeNameMap
[
typ
]
}
func
(
p
*
Compiler
)
llRegTypeName
(
typ
lltypes
.
Type
,
name
string
)
{
p
.
llTypeNameMap
[
typ
]
=
name
p
.
llNamedTypeMap
[
name
]
=
typ
}
internal/backends/compiler_ll/compile_type.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/types"
)
func
(
p
*
Compiler
)
compileType
(
pkg
*
ssa
.
Package
,
typMember
*
ssa
.
Type
)
error
{
if
typ
,
ok
:=
typMember
.
Type
()
.
(
*
types
.
Named
);
ok
{
if
ty
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Struct
);
ok
{
p
.
module
.
NewTypeDef
(
typ
.
Obj
()
.
Id
(),
p
.
toLLType
(
ty
))
}
}
return
nil
}
func
(
p
*
Compiler
)
isBoolType
(
typ
types
.
Type
)
bool
{
if
t
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Basic
);
ok
{
return
t
.
Info
()
&
types
.
IsBoolean
!=
0
}
return
false
}
func
(
p
*
Compiler
)
isIntType
(
typ
types
.
Type
)
bool
{
if
t
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Basic
);
ok
{
return
t
.
Info
()
&
types
.
IsInteger
!=
0
}
return
false
}
func
(
p
*
Compiler
)
isUIntType
(
typ
types
.
Type
)
bool
{
if
t
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Basic
);
ok
{
return
t
.
Info
()
&
types
.
IsUnsigned
!=
0
}
return
false
}
func
(
p
*
Compiler
)
isFloatType
(
typ
types
.
Type
)
bool
{
if
t
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Basic
);
ok
{
return
t
.
Info
()
&
types
.
IsFloat
!=
0
}
return
false
}
func
(
p
*
Compiler
)
isComplexType
(
typ
types
.
Type
)
bool
{
if
t
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Basic
);
ok
{
return
t
.
Info
()
&
types
.
IsComplex
!=
0
}
return
false
}
func
(
p
*
Compiler
)
isStrType
(
typ
types
.
Type
)
bool
{
if
t
,
ok
:=
typ
.
Underlying
()
.
(
*
types
.
Basic
);
ok
{
return
t
.
Info
()
&
types
.
IsString
!=
0
}
return
false
}
func
(
p
*
Compiler
)
llIsStrType
(
typ
lltypes
.
Type
)
bool
{
for
_
,
t
:=
range
p
.
module
.
TypeDefs
{
if
t
==
typ
{
return
t
.
Name
()
==
g_typ_string_name
}
}
return
false
}
func
(
p
*
Compiler
)
waIsStrType
(
typ
types
.
Type
)
bool
{
if
x
,
ok
:=
typ
.
(
*
types
.
Basic
);
ok
{
if
x
.
Kind
()
==
types
.
String
||
x
.
Kind
()
==
types
.
UntypedString
{
return
true
}
}
return
false
}
func
(
p
*
Compiler
)
waIsComplexType
(
typ
types
.
Type
)
bool
{
if
x
,
ok
:=
typ
.
(
*
types
.
Basic
);
ok
{
if
x
.
Kind
()
==
types
.
Complex64
||
x
.
Kind
()
==
types
.
Complex128
{
return
true
}
}
return
false
}
func
(
p
*
Compiler
)
isPointerType
(
typ
types
.
Type
)
bool
{
if
_
,
ok
:=
typ
.
(
*
types
.
Pointer
);
ok
{
return
true
}
else
if
typ
,
ok
:=
typ
.
(
*
types
.
Basic
);
ok
&&
typ
.
Kind
()
==
types
.
UnsafePointer
{
return
true
}
else
{
return
false
}
}
func
(
p
*
Compiler
)
toLLFuncType
(
t
types
.
Type
)
*
lltypes
.
FuncType
{
return
p
.
toLLType
(
t
)
.
(
*
lltypes
.
FuncType
)
}
func
(
p
*
Compiler
)
toLLType
(
t
types
.
Type
)
lltypes
.
Type
{
switch
t
:=
t
.
(
type
)
{
case
*
types
.
Basic
:
switch
t
.
Kind
()
{
case
types
.
Int
,
types
.
Uint
:
return
lltypes
.
I64
case
types
.
Uintptr
:
return
lltypes
.
I64
case
types
.
UnsafePointer
:
return
lltypes
.
NewPointer
(
nil
)
case
types
.
Bool
,
types
.
UntypedBool
:
return
lltypes
.
I1
case
types
.
Int8
,
types
.
Uint8
:
return
lltypes
.
I8
case
types
.
Int16
,
types
.
Uint16
:
return
lltypes
.
I16
case
types
.
Int32
,
types
.
Uint32
:
return
lltypes
.
I32
case
types
.
Int64
,
types
.
Uint64
:
return
lltypes
.
I64
case
types
.
Float32
:
return
lltypes
.
Float
case
types
.
Float64
:
return
lltypes
.
Double
case
types
.
Complex64
:
structType
:=
lltypes
.
NewStruct
(
lltypes
.
Float
,
lltypes
.
Float
)
return
structType
case
types
.
Complex128
:
return
lltypes
.
NewStruct
(
lltypes
.
Double
,
lltypes
.
Double
)
case
types
.
String
,
types
.
UntypedString
:
return
p
.
getLLType
(
g_typ_string_name
)
default
:
panic
(
"unreachable"
)
}
case
*
types
.
Pointer
:
return
lltypes
.
NewPointer
(
p
.
toLLType
(
t
.
Elem
()))
case
*
types
.
Array
:
return
lltypes
.
NewArray
(
uint64
(
t
.
Len
()),
p
.
toLLType
(
t
.
Elem
()))
case
*
types
.
Slice
:
return
lltypes
.
NewStruct
(
p
.
toLLType
(
t
.
Elem
()),
lltypes
.
I64
,
// len
lltypes
.
I64
,
// cap
)
case
*
types
.
Struct
:
fields
:=
make
([]
lltypes
.
Type
,
t
.
NumFields
())
for
i
:=
0
;
i
<
t
.
NumFields
();
i
++
{
fields
[
i
]
=
p
.
toLLType
(
t
.
Field
(
i
)
.
Type
())
}
return
lltypes
.
NewStruct
(
fields
...
)
case
*
types
.
Tuple
:
fields
:=
make
([]
lltypes
.
Type
,
t
.
Len
())
for
i
:=
0
;
i
<
t
.
Len
();
i
++
{
fields
[
i
]
=
p
.
toLLType
(
t
.
At
(
i
)
.
Type
())
}
return
lltypes
.
NewStruct
(
fields
...
)
case
*
types
.
Map
:
// todo
case
*
types
.
Interface
:
// todo
case
*
types
.
Named
:
if
st
,
ok
:=
t
.
Underlying
()
.
(
*
types
.
Struct
);
ok
{
fields
:=
make
([]
lltypes
.
Type
,
st
.
NumFields
())
for
i
:=
0
;
i
<
st
.
NumFields
();
i
++
{
fields
[
i
]
=
p
.
toLLType
(
st
.
Field
(
i
)
.
Type
())
}
t2
:=
lltypes
.
NewStruct
(
fields
...
)
// t2.TypeName = "TODO"
return
t2
}
return
p
.
toLLType
(
t
.
Underlying
())
case
*
types
.
Signature
:
var
returnType
lltypes
.
Type
switch
t
.
Results
()
.
Len
()
{
case
0
:
returnType
=
lltypes
.
Void
case
1
:
returnType
=
p
.
toLLType
(
t
.
Results
()
.
At
(
0
)
.
Type
())
default
:
fields
:=
make
([]
lltypes
.
Type
,
t
.
Results
()
.
Len
())
for
i
:=
0
;
i
<
t
.
Results
()
.
Len
();
i
++
{
fields
[
i
]
=
p
.
toLLType
(
t
.
Results
()
.
At
(
i
)
.
Type
())
}
returnType
=
lltypes
.
NewStruct
(
fields
...
)
}
var
paramTypes
[]
lltypes
.
Type
if
t
.
Recv
()
!=
nil
{
recv
:=
p
.
toLLType
(
t
.
Recv
()
.
Type
())
paramTypes
=
append
(
paramTypes
,
recv
)
}
for
i
:=
0
;
i
<
t
.
Params
()
.
Len
();
i
++
{
subType
:=
p
.
toLLType
(
t
.
Params
()
.
At
(
i
)
.
Type
())
paramTypes
=
append
(
paramTypes
,
subType
)
}
return
lltypes
.
NewFunc
(
returnType
,
paramTypes
...
)
default
:
panic
(
"unknown type: "
+
t
.
String
())
}
return
nil
}
internal/backends/compiler_ll/compile_value_const.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/constant"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/types"
)
// 暂时全部用 I64 表示 int 和 指针
func
(
p
*
Compiler
)
constValue
(
expr
*
ssa
.
Const
)
llvalue
.
Value
{
t
:=
expr
.
Type
()
.
Underlying
()
switch
t
:=
t
.
(
type
)
{
case
*
types
.
Basic
:
switch
t
.
Kind
()
{
case
types
.
Int
,
types
.
Uint
:
n
,
_
:=
constant
.
Int64Val
(
expr
.
Value
)
return
llconstant
.
NewInt
(
lltypes
.
I64
,
n
)
case
types
.
Uintptr
:
n
,
_
:=
constant
.
Int64Val
(
expr
.
Value
)
return
llconstant
.
NewInt
(
lltypes
.
I64
,
n
)
case
types
.
Bool
,
types
.
UntypedBool
:
return
llconstant
.
NewBool
(
constant
.
BoolVal
(
expr
.
Value
))
case
types
.
Int8
,
types
.
Uint8
:
n
,
_
:=
constant
.
Int64Val
(
expr
.
Value
)
return
llconstant
.
NewInt
(
lltypes
.
I8
,
n
)
case
types
.
Int16
,
types
.
Uint16
:
n
,
_
:=
constant
.
Int64Val
(
expr
.
Value
)
return
llconstant
.
NewInt
(
lltypes
.
I16
,
n
)
case
types
.
Int32
,
types
.
Uint32
:
n
,
_
:=
constant
.
Int64Val
(
expr
.
Value
)
return
llconstant
.
NewInt
(
lltypes
.
I32
,
n
)
case
types
.
Int64
,
types
.
Uint64
:
n
,
_
:=
constant
.
Int64Val
(
expr
.
Value
)
return
llconstant
.
NewInt
(
lltypes
.
I64
,
n
)
case
types
.
Float32
:
v
,
_
:=
constant
.
Float64Val
(
expr
.
Value
)
return
llconstant
.
NewFloat
(
lltypes
.
Float
,
v
)
case
types
.
Float64
:
v
,
_
:=
constant
.
Float64Val
(
expr
.
Value
)
return
llconstant
.
NewFloat
(
lltypes
.
Double
,
v
)
case
types
.
Complex64
:
real_v
,
_
:=
constant
.
Float64Val
(
constant
.
Real
(
expr
.
Value
))
imag_v
,
_
:=
constant
.
Float64Val
(
constant
.
Imag
(
expr
.
Value
))
return
llconstant
.
NewStruct
(
p
.
getLLType
(
g_typ_complex64_name
)
.
(
*
lltypes
.
StructType
),
llconstant
.
NewFloat
(
lltypes
.
Float
,
real_v
),
llconstant
.
NewFloat
(
lltypes
.
Float
,
imag_v
),
)
case
types
.
Complex128
:
real_v
,
_
:=
constant
.
Float64Val
(
constant
.
Real
(
expr
.
Value
))
imag_v
,
_
:=
constant
.
Float64Val
(
constant
.
Imag
(
expr
.
Value
))
return
llconstant
.
NewStruct
(
p
.
getLLType
(
g_typ_complex128_name
)
.
(
*
lltypes
.
StructType
),
llconstant
.
NewFloat
(
lltypes
.
Double
,
real_v
),
llconstant
.
NewFloat
(
lltypes
.
Double
,
imag_v
),
)
case
types
.
String
,
types
.
UntypedString
:
s
:=
constant
.
StringVal
(
expr
.
Value
)
return
llconstant
.
NewStruct
(
p
.
getLLType
(
g_typ_string_name
)
.
(
*
lltypes
.
StructType
),
llconstant
.
NewCharArray
(
append
([]
byte
(
s
),
0
)),
llconstant
.
NewInt
(
lltypes
.
I64
,
int64
(
len
(
s
)
+
1
)),
)
}
}
panic
(
"unknown const type: "
+
t
.
String
())
}
internal/backends/compiler_ll/compile_value_zero.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler
import
(
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/types"
)
func
(
p
*
Compiler
)
zeroValue
(
t
types
.
Type
)
llvalue
.
Value
{
switch
t
:=
t
.
(
type
)
{
case
*
types
.
Basic
:
switch
t
.
Kind
()
{
case
types
.
Int
,
types
.
Uint
:
return
llconstant
.
NewInt
(
lltypes
.
I64
,
0
)
case
types
.
Uintptr
:
return
llconstant
.
NewInt
(
lltypes
.
I64
,
0
)
case
types
.
Bool
,
types
.
UntypedBool
:
return
llconstant
.
NewBool
(
false
)
case
types
.
Int8
,
types
.
Uint8
:
return
llconstant
.
NewInt
(
lltypes
.
I8
,
0
)
case
types
.
Int16
,
types
.
Uint16
:
return
llconstant
.
NewInt
(
lltypes
.
I16
,
0
)
case
types
.
Int32
,
types
.
Uint32
:
return
llconstant
.
NewInt
(
lltypes
.
I32
,
0
)
case
types
.
Int64
,
types
.
Uint64
:
return
llconstant
.
NewInt
(
lltypes
.
I64
,
102
)
// todo: debug
case
types
.
Float32
:
return
llconstant
.
NewFloat
(
lltypes
.
Float
,
0
)
case
types
.
Float64
:
return
llconstant
.
NewFloat
(
lltypes
.
Double
,
0
)
case
types
.
Complex64
:
return
llconstant
.
NewStruct
(
lltypes
.
NewStruct
(
lltypes
.
Float
,
lltypes
.
Float
),
llconstant
.
NewFloat
(
lltypes
.
Float
,
0
),
llconstant
.
NewFloat
(
lltypes
.
Float
,
0
),
)
case
types
.
Complex128
:
return
llconstant
.
NewStruct
(
lltypes
.
NewStruct
(
lltypes
.
Double
,
lltypes
.
Double
),
llconstant
.
NewFloat
(
lltypes
.
Double
,
0
),
llconstant
.
NewFloat
(
lltypes
.
Double
,
0
),
)
case
types
.
String
,
types
.
UntypedString
:
return
llconstant
.
NewStruct
(
p
.
getLLType
(
g_typ_string_name
)
.
(
*
lltypes
.
StructType
),
llconstant
.
NewCharArray
(
append
([]
byte
(
""
),
0
)),
llconstant
.
NewInt
(
lltypes
.
I64
,
0
),
)
}
}
panic
(
"unknown const type: "
+
t
.
String
())
}
internal/backends/compiler_ll/llutil/llutil.wa.go
0 → 100644
浏览文件 @
0c9f5866
// 版权 @2021 凹语言 作者。保留所有权利。
package
llutil
import
(
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
)
func
GetType
(
m
*
llir
.
Module
,
typName
string
)
lltypes
.
Type
{
for
_
,
typ
:=
range
m
.
TypeDefs
{
if
typ
.
Name
()
==
typName
{
return
typ
}
}
return
nil
}
func
GetFunc
(
m
*
llir
.
Module
,
fnName
string
)
*
llir
.
Func
{
for
_
,
x
:=
range
m
.
Funcs
{
if
x
.
Name
()
==
fnName
{
return
x
}
}
return
nil
}
func
PtrElemType
(
src
llvalue
.
Value
)
lltypes
.
Type
{
return
src
.
Type
()
.
(
*
lltypes
.
PointerType
)
.
ElemType
}
func
StrConstant
(
in
string
)
*
llconstant
.
CharArray
{
return
llconstant
.
NewCharArray
(
append
([]
byte
(
in
),
0
))
}
func
StrToi8Ptr
(
block
*
llir
.
Block
,
src
llvalue
.
Value
)
*
llir
.
InstGetElementPtr
{
return
block
.
NewGetElementPtr
(
PtrElemType
(
src
),
src
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
)
}
func
StrLen
(
block
*
llir
.
Block
,
src
llvalue
.
Value
)
llvalue
.
Value
{
if
_
,
ok
:=
src
.
Type
()
.
(
*
lltypes
.
PointerType
);
ok
{
l
:=
block
.
NewGetElementPtr
(
PtrElemType
(
src
),
src
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
)
return
block
.
NewLoad
(
PtrElemType
(
l
),
l
)
}
return
block
.
NewExtractValue
(
src
,
0
)
}
func
StrToI8Ptr
(
block
*
llir
.
Block
,
src
llvalue
.
Value
)
llvalue
.
Value
{
if
_
,
ok
:=
src
.
Type
()
.
(
*
lltypes
.
PointerType
);
ok
{
l
:=
block
.
NewGetElementPtr
(
PtrElemType
(
src
),
src
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
1
),
)
return
block
.
NewLoad
(
PtrElemType
(
l
),
l
)
}
return
block
.
NewExtractValue
(
src
,
1
)
}
func
Slice
(
itemType
lltypes
.
Type
)
*
lltypes
.
StructType
{
return
lltypes
.
NewStruct
(
lltypes
.
I32
,
// Len
lltypes
.
I32
,
// Cap
lltypes
.
I32
,
// Array Offset
lltypes
.
NewPointer
(
itemType
),
// Content
)
}
func
String
()
*
lltypes
.
StructType
{
return
lltypes
.
NewStruct
(
lltypes
.
NewPointer
(
lltypes
.
I8
),
// Content
lltypes
.
I32
,
// String length
)
}
func
StringLen
(
stringType
lltypes
.
Type
)
*
llir
.
Func
{
param
:=
llir
.
NewParam
(
"input"
,
stringType
)
res
:=
llir
.
NewFunc
(
"string_len"
,
lltypes
.
I64
,
param
)
block
:=
res
.
NewBlock
(
"entry"
)
block
.
NewRet
(
block
.
NewExtractValue
(
param
,
0
))
return
res
}
internal/backends/compiler_ll/names.go
0 → 100644
浏览文件 @
0c9f5866
package
compiler
const
(
g_typ_string_name
=
"ugo_string_t"
g_typ_complex64_name
=
"ugo_complex64_t"
g_typ_complex128_name
=
"ugo_complex128_t"
)
internal/backends/compiler_ll/syscall/print.wa.go
0 → 100644
浏览文件 @
0c9f5866
package
syscall
import
(
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/backends/compiler_ll/llutil"
)
func
Print
(
block
*
llir
.
Block
,
value
llvalue
.
Value
,
goos
string
)
{
asmFunc
:=
llir
.
NewInlineAsm
(
lltypes
.
NewPointer
(
lltypes
.
NewFunc
(
lltypes
.
I64
)),
"syscall"
,
"=r,{rax},{rdi},{rsi},{rdx}"
,
)
asmFunc
.
SideEffect
=
true
strPtr
:=
llutil
.
StrToI8Ptr
(
block
,
value
)
strLen
:=
llutil
.
StrLen
(
block
,
value
)
block
.
NewCall
(
asmFunc
,
llconstant
.
NewInt
(
lltypes
.
I64
,
Convert
(
WRITE
,
goos
)),
// rax
llconstant
.
NewInt
(
lltypes
.
I64
,
1
),
// rdi, stdout
strPtr
,
// rsi
strLen
,
// rdx
)
}
internal/backends/compiler_ll/syscall/syscall.wa.go
0 → 100644
浏览文件 @
0c9f5866
package
syscall
// https://opensource.apple.com/source/xnu/xnu-2782.20.48/bsd/kern/syscalls.master
type
fn
string
const
(
EXIT
fn
=
"EXIT"
WRITE
fn
=
"WRITE"
)
var
convDarwin
=
map
[
fn
]
int64
{
EXIT
:
0x2000001
,
WRITE
:
0x2000004
,
}
var
convLinux
=
map
[
fn
]
int64
{
EXIT
:
60
,
WRITE
:
1
,
}
func
Convert
(
f
fn
,
goos
string
)
int64
{
switch
goos
{
case
"darwin"
:
return
convDarwin
[
f
]
case
"linux"
:
return
convLinux
[
f
]
default
:
panic
(
"unknown goos"
)
}
}
internal/backends/compiler_ll/types/builtin.wa.go
0 → 100644
浏览文件 @
0c9f5866
package
types
import
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
var
(
I8
=
&
Int
{
Type
:
lltypes
.
I8
,
TypeName
:
"int8"
,
TypeSize
:
8
/
8
,
Signed
:
true
}
U8
=
&
Int
{
Type
:
lltypes
.
I8
,
TypeName
:
"uint8"
,
TypeSize
:
8
/
8
}
I16
=
&
Int
{
Type
:
lltypes
.
I16
,
TypeName
:
"int16"
,
TypeSize
:
18
/
8
,
Signed
:
true
}
U16
=
&
Int
{
Type
:
lltypes
.
I16
,
TypeName
:
"uint16"
,
TypeSize
:
18
/
8
}
I32
=
&
Int
{
Type
:
lltypes
.
I32
,
TypeName
:
"int32"
,
TypeSize
:
32
/
8
,
Signed
:
true
}
U32
=
&
Int
{
Type
:
lltypes
.
I32
,
TypeName
:
"uint32"
,
TypeSize
:
32
/
8
}
I64
=
&
Int
{
Type
:
lltypes
.
I64
,
TypeName
:
"int64"
,
TypeSize
:
64
/
8
,
Signed
:
true
}
U64
=
&
Int
{
Type
:
lltypes
.
I64
,
TypeName
:
"uint64"
,
TypeSize
:
64
/
8
}
Uintptr
=
&
Int
{
Type
:
lltypes
.
I64
,
TypeName
:
"uintptr"
,
TypeSize
:
64
/
8
}
Void
=
&
VoidType
{}
Bool
=
&
BoolType
{}
String
=
&
StringType
{}
)
internal/backends/compiler_ll/types/interface.wa.go
0 → 100644
浏览文件 @
0c9f5866
package
types
import
(
"fmt"
"sort"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
)
type
Interface
struct
{
backingType
SourceName
string
RequiredMethods
map
[
string
]
InterfaceMethod
}
func
(
i
Interface
)
Name
()
string
{
return
fmt
.
Sprintf
(
"interface(%s)"
,
i
.
SourceName
)
}
// SortedRequiredMethods returns a sorted slice of all method names
// The returned order is the order the methods will be layed out in the JumpTable
func
(
i
Interface
)
SortedRequiredMethods
()
[]
string
{
var
orderedMethods
[]
string
for
methodName
:=
range
i
.
RequiredMethods
{
orderedMethods
=
append
(
orderedMethods
,
methodName
)
}
sort
.
Strings
(
orderedMethods
)
return
orderedMethods
}
func
(
i
Interface
)
JumpTable
()
*
lltypes
.
StructType
{
orderedMethods
:=
i
.
SortedRequiredMethods
()
var
ifaceTableMethods
[]
lltypes
.
Type
for
_
,
methodName
:=
range
orderedMethods
{
methodSignature
:=
i
.
RequiredMethods
[
methodName
]
var
retType
lltypes
.
Type
=
lltypes
.
Void
if
len
(
methodSignature
.
ReturnTypes
)
>
0
{
retType
=
methodSignature
.
ReturnTypes
[
0
]
.
LLVM
()
}
paramTypes
:=
[]
lltypes
.
Type
{
lltypes
.
NewPointer
(
lltypes
.
I8
)}
for
_
,
argType
:=
range
methodSignature
.
ArgumentTypes
{
paramTypes
=
append
(
paramTypes
,
argType
.
LLVM
())
}
ifaceTableMethods
=
append
(
ifaceTableMethods
,
lltypes
.
NewPointer
(
lltypes
.
NewFunc
(
retType
,
paramTypes
...
)))
}
return
lltypes
.
NewStruct
(
ifaceTableMethods
...
)
}
func
(
i
Interface
)
LLVM
()
lltypes
.
Type
{
return
lltypes
.
NewStruct
(
// Pointer to the backing data
lltypes
.
NewPointer
(
lltypes
.
I8
),
// Backing data type
lltypes
.
I32
,
// Interface table
// Used for method resolving
lltypes
.
NewPointer
(
i
.
JumpTable
()),
)
}
func
(
Interface
)
Size
()
int64
{
return
64
/
8
*
3
}
type
InterfaceMethod
struct
{
backingType
LlvmJumpFunction
llvalue
.
Named
ArgumentTypes
[]
Type
ReturnTypes
[]
Type
}
func
(
InterfaceMethod
)
LLVM
()
lltypes
.
Type
{
panic
(
"InterfaceMethod has no LLVM value"
)
}
func
(
InterfaceMethod
)
Name
()
string
{
return
"InterfaceMethod"
}
internal/backends/compiler_ll/types/package.wa.go
0 → 100644
浏览文件 @
0c9f5866
package
types
import
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
type
PackageInstance
struct
{
backingType
name
string
funcs
map
[
string
]
*
Function
}
func
(
p
*
PackageInstance
)
SetName
(
name
string
)
{
p
.
name
=
name
}
func
(
p
*
PackageInstance
)
SetFunc
(
name
string
,
val
*
Function
)
{
if
p
.
funcs
==
nil
{
p
.
funcs
=
make
(
map
[
string
]
*
Function
)
}
p
.
funcs
[
name
]
=
val
}
func
(
p
*
PackageInstance
)
GetFunc
(
name
string
)
(
*
Function
,
bool
)
{
v
,
ok
:=
p
.
funcs
[
name
]
return
v
,
ok
}
func
(
PackageInstance
)
LLVM
()
lltypes
.
Type
{
// TODO: Packages are not values, and should be represented some other way
// Maybe via LLVM IR modules?
panic
(
"Package does not have LLVM defined"
)
}
func
(
p
PackageInstance
)
Name
()
string
{
return
p
.
name
}
internal/backends/compiler_ll/types/type.wa.go
0 → 100644
浏览文件 @
0c9f5866
package
types
import
(
"fmt"
"math/big"
"github.com/wa-lang/wa/internal/3rdparty/llir"
"github.com/wa-lang/wa/internal/3rdparty/llir/llconstant"
"github.com/wa-lang/wa/internal/3rdparty/llir/lltypes"
"github.com/wa-lang/wa/internal/3rdparty/llir/llvalue"
"github.com/wa-lang/wa/internal/backends/compiler_ll/llutil"
)
type
Type
interface
{
LLVM
()
lltypes
.
Type
Name
()
string
// Size of type in bytes
Size
()
int64
AddMethod
(
string
,
*
Method
)
GetMethod
(
string
)
(
*
Method
,
bool
)
Zero
(
*
llir
.
Block
,
llvalue
.
Value
)
IsSigned
()
bool
}
type
backingType
struct
{
methods
map
[
string
]
*
Method
}
func
(
b
*
backingType
)
AddMethod
(
name
string
,
method
*
Method
)
{
if
b
.
methods
==
nil
{
b
.
methods
=
make
(
map
[
string
]
*
Method
)
}
b
.
methods
[
name
]
=
method
}
func
(
b
*
backingType
)
GetMethod
(
name
string
)
(
*
Method
,
bool
)
{
m
,
ok
:=
b
.
methods
[
name
]
return
m
,
ok
}
func
(
backingType
)
Size
()
int64
{
panic
(
"Type does not have size set"
)
}
func
(
backingType
)
Zero
(
*
llir
.
Block
,
llvalue
.
Value
)
{
// NOOP
}
func
(
backingType
)
IsSigned
()
bool
{
return
false
}
type
Struct
struct
{
backingType
Members
map
[
string
]
Type
MemberIndexes
map
[
string
]
int
IsHeapAllocated
bool
SourceName
string
Type
lltypes
.
Type
}
func
(
s
Struct
)
LLVM
()
lltypes
.
Type
{
return
s
.
Type
}
func
(
s
Struct
)
Name
()
string
{
return
fmt
.
Sprintf
(
"struct(%s)"
,
s
.
SourceName
)
}
func
(
s
Struct
)
Zero
(
block
*
llir
.
Block
,
alloca
llvalue
.
Value
)
{
for
key
,
valType
:=
range
s
.
Members
{
ptr
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
alloca
),
alloca
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
int64
(
s
.
MemberIndexes
[
key
])),
)
valType
.
Zero
(
block
,
ptr
)
}
}
func
(
s
Struct
)
Size
()
int64
{
var
sum
int64
for
_
,
valType
:=
range
s
.
Members
{
sum
+=
valType
.
Size
()
}
return
sum
}
type
Method
struct
{
backingType
Function
*
Function
LlvmFunction
llvalue
.
Named
PointerReceiver
bool
MethodName
string
}
func
(
m
Method
)
LLVM
()
lltypes
.
Type
{
return
m
.
Function
.
LLVM
()
}
func
(
m
Method
)
Name
()
string
{
return
m
.
MethodName
}
type
Function
struct
{
backingType
// LlvmFunction llvalue.Named
FuncType
lltypes
.
Type
// The return type of the LLVM function (is always 1)
LlvmReturnType
Type
// Return types of the Tre function
ReturnTypes
[]
Type
IsVariadic
bool
ArgumentTypes
[]
Type
IsExternal
bool
// Is used when calling an interface method
JumpFunction
*
llir
.
Func
}
func
(
f
Function
)
LLVM
()
lltypes
.
Type
{
return
f
.
FuncType
}
func
(
f
Function
)
Name
()
string
{
return
"func"
}
type
BoolType
struct
{
backingType
}
func
(
BoolType
)
LLVM
()
lltypes
.
Type
{
return
lltypes
.
I1
}
func
(
BoolType
)
Name
()
string
{
return
"bool"
}
func
(
BoolType
)
Size
()
int64
{
return
1
}
func
(
b
BoolType
)
Zero
(
block
*
llir
.
Block
,
alloca
llvalue
.
Value
)
{
block
.
NewStore
(
llconstant
.
NewInt
(
lltypes
.
I1
,
0
),
alloca
)
}
type
VoidType
struct
{
backingType
}
func
(
VoidType
)
LLVM
()
lltypes
.
Type
{
return
lltypes
.
Void
}
func
(
VoidType
)
Name
()
string
{
return
"void"
}
func
(
VoidType
)
Size
()
int64
{
return
0
}
type
Int
struct
{
backingType
Type
*
lltypes
.
IntType
TypeName
string
TypeSize
int64
Signed
bool
}
func
(
i
Int
)
LLVM
()
lltypes
.
Type
{
return
i
.
Type
}
func
(
i
Int
)
Name
()
string
{
return
i
.
TypeName
}
func
(
i
Int
)
Size
()
int64
{
return
i
.
TypeSize
}
func
(
i
Int
)
Zero
(
block
*
llir
.
Block
,
alloca
llvalue
.
Value
)
{
b
:=
big
.
NewInt
(
0
)
if
!
i
.
IsSigned
()
{
b
.
SetUint64
(
0
)
}
c
:=
&
llconstant
.
Int
{
Typ
:
i
.
Type
,
X
:
b
,
}
block
.
NewStore
(
c
,
alloca
)
}
func
(
i
Int
)
IsSigned
()
bool
{
return
i
.
Signed
}
type
StringType
struct
{
backingType
Type
lltypes
.
Type
}
// Populated by compiler.go
var
ModuleStringType
lltypes
.
Type
var
EmptyStringConstant
*
llir
.
Global
func
(
StringType
)
LLVM
()
lltypes
.
Type
{
return
ModuleStringType
}
func
(
StringType
)
Name
()
string
{
return
"string"
}
func
(
StringType
)
Size
()
int64
{
return
16
}
func
(
s
StringType
)
Zero
(
block
*
llir
.
Block
,
alloca
llvalue
.
Value
)
{
lenPtr
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
alloca
),
alloca
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
0
))
backingDataPtr
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
alloca
),
alloca
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
1
))
block
.
NewStore
(
llconstant
.
NewInt
(
lltypes
.
I64
,
0
),
lenPtr
)
block
.
NewStore
(
llutil
.
StrToi8Ptr
(
block
,
EmptyStringConstant
),
backingDataPtr
)
}
type
Array
struct
{
backingType
Type
Type
Len
uint64
LlvmType
lltypes
.
Type
}
func
(
a
Array
)
LLVM
()
lltypes
.
Type
{
return
a
.
LlvmType
}
func
(
a
Array
)
Name
()
string
{
return
"array"
}
func
(
a
Array
)
Zero
(
block
*
llir
.
Block
,
alloca
llvalue
.
Value
)
{
for
i
:=
uint64
(
0
);
i
<
a
.
Len
;
i
++
{
ptr
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
alloca
),
alloca
,
llconstant
.
NewInt
(
lltypes
.
I64
,
0
),
llconstant
.
NewInt
(
lltypes
.
I64
,
int64
(
i
)))
a
.
Type
.
Zero
(
block
,
ptr
)
}
}
type
Slice
struct
{
backingType
Type
Type
// type of the items in the slice []int => int
LlvmType
lltypes
.
Type
}
func
(
s
Slice
)
LLVM
()
lltypes
.
Type
{
return
s
.
LlvmType
}
func
(
Slice
)
Name
()
string
{
return
"slice"
}
func
(
Slice
)
Size
()
int64
{
return
3
*
4
+
8
// 3 int32s and a pointer
}
func
(
s
Slice
)
SliceZero
(
block
*
llir
.
Block
,
mallocFunc
llvalue
.
Named
,
initCap
int
,
emptySlice
llvalue
.
Value
)
{
// The cap must always be larger than 0
// Use 2 as the default value
if
initCap
<
2
{
initCap
=
2
}
len
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
emptySlice
),
emptySlice
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
0
))
len
.
SetName
(
"len"
)
cap
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
emptySlice
),
emptySlice
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
1
))
cap
.
SetName
(
"cap"
)
offset
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
emptySlice
),
emptySlice
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
2
))
offset
.
SetName
(
"offset"
)
backingArray
:=
block
.
NewGetElementPtr
(
llutil
.
PtrElemType
(
emptySlice
),
emptySlice
,
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
llconstant
.
NewInt
(
lltypes
.
I32
,
3
))
backingArray
.
SetName
(
"backing"
)
block
.
NewStore
(
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
len
)
block
.
NewStore
(
llconstant
.
NewInt
(
lltypes
.
I32
,
int64
(
initCap
)),
cap
)
block
.
NewStore
(
llconstant
.
NewInt
(
lltypes
.
I32
,
0
),
offset
)
mallocatedSpaceRaw
:=
block
.
NewCall
(
mallocFunc
,
llconstant
.
NewInt
(
lltypes
.
I64
,
int64
(
initCap
)
*
s
.
Type
.
Size
()))
mallocatedSpaceRaw
.
SetName
(
"slicezero"
)
bitcasted
:=
block
.
NewBitCast
(
mallocatedSpaceRaw
,
lltypes
.
NewPointer
(
s
.
Type
.
LLVM
()))
block
.
NewStore
(
bitcasted
,
backingArray
)
}
type
Pointer
struct
{
backingType
Type
Type
IsNonAllocDereference
bool
LlvmType
lltypes
.
Type
}
func
(
p
Pointer
)
LLVM
()
lltypes
.
Type
{
return
lltypes
.
NewPointer
(
p
.
Type
.
LLVM
())
}
func
(
p
Pointer
)
Name
()
string
{
return
fmt
.
Sprintf
(
"pointer(%s)"
,
p
.
Type
.
Name
())
}
func
(
p
Pointer
)
Size
()
int64
{
return
8
}
// MultiValue is used when returning multiple values from a function
type
MultiValue
struct
{
backingType
Types
[]
Type
}
func
(
m
MultiValue
)
Name
()
string
{
return
"multivalue"
}
func
(
m
MultiValue
)
LLVM
()
lltypes
.
Type
{
panic
(
"MutliValue has no LLVM type"
)
}
type
UntypedConstantNumber
struct
{
backingType
}
func
(
m
UntypedConstantNumber
)
Name
()
string
{
return
"UntypedConstantNumber"
}
func
(
m
UntypedConstantNumber
)
LLVM
()
lltypes
.
Type
{
panic
(
"UntypedConstantNumber has no LLVM type"
)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录