Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wa-lang
wa
提交
f939ef4d
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,发现更多精彩内容 >>
提交
f939ef4d
编写于
7月 27, 2022
作者:
3
3dgen
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'backend_c'
上级
93bddc42
b8a5d1eb
变更
18
显示空白变更内容
内联
并排
Showing
18 changed file
with
2777 addition
and
0 deletion
+2777
-0
internal/app/app.wa.go
internal/app/app.wa.go
+16
-0
internal/backends/compiler_c/cir/cconstant/cconstant.go
internal/backends/compiler_c/cir/cconstant/cconstant.go
+229
-0
internal/backends/compiler_c/cir/ctypes/ctypes.go
internal/backends/compiler_c/cir/ctypes/ctypes.go
+445
-0
internal/backends/compiler_c/cir/ctypes/rich_type.go
internal/backends/compiler_c/cir/ctypes/rich_type.go
+173
-0
internal/backends/compiler_c/cir/decl.go
internal/backends/compiler_c/cir/decl.go
+107
-0
internal/backends/compiler_c/cir/expr.go
internal/backends/compiler_c/cir/expr.go
+303
-0
internal/backends/compiler_c/cir/ident.go
internal/backends/compiler_c/cir/ident.go
+18
-0
internal/backends/compiler_c/cir/scope.go
internal/backends/compiler_c/cir/scope.go
+210
-0
internal/backends/compiler_c/cir/stmt.go
internal/backends/compiler_c/cir/stmt.go
+245
-0
internal/backends/compiler_c/cir/util.go
internal/backends/compiler_c/cir/util.go
+105
-0
internal/backends/compiler_c/cir/var.go
internal/backends/compiler_c/cir/var.go
+25
-0
internal/backends/compiler_c/compile_const.go
internal/backends/compiler_c/compile_const.go
+13
-0
internal/backends/compiler_c/compile_func.go
internal/backends/compiler_c/compile_func.go
+687
-0
internal/backends/compiler_c/compile_global.go
internal/backends/compiler_c/compile_global.go
+27
-0
internal/backends/compiler_c/compile_type.go
internal/backends/compiler_c/compile_type.go
+42
-0
internal/backends/compiler_c/compiler_c.go
internal/backends/compiler_c/compiler_c.go
+111
-0
internal/backends/compiler_c/compiler_util.go
internal/backends/compiler_c/compiler_util.go
+3
-0
main.go
main.go
+18
-0
未找到文件。
internal/app/app.wa.go
浏览文件 @
f939ef4d
...
...
@@ -18,6 +18,7 @@ import (
"time"
"github.com/wa-lang/wa/internal/ast"
"github.com/wa-lang/wa/internal/backends/compiler_c"
"github.com/wa-lang/wa/internal/backends/compiler_ll"
"github.com/wa-lang/wa/internal/backends/compiler_ll/builtin"
"github.com/wa-lang/wa/internal/config"
...
...
@@ -278,6 +279,21 @@ func (p *App) SSA(filename string) error {
return
nil
}
func
(
p
*
App
)
CIR
(
filename
string
)
error
{
cfg
:=
config
.
DefaultConfig
()
prog
,
err
:=
loader
.
LoadProgram
(
cfg
,
filename
)
if
err
!=
nil
{
return
err
}
var
c
compiler_c
.
CompilerC
c
.
CompilePackage
(
prog
.
SSAMainPkg
)
print
(
"
\n\n
"
)
print
(
c
.
String
())
return
nil
}
func
(
p
*
App
)
ASM
(
filename
string
)
error
{
cfg
:=
config
.
DefaultConfig
()
prog
,
err
:=
loader
.
LoadProgram
(
cfg
,
filename
)
...
...
internal/backends/compiler_c/cir/cconstant/cconstant.go
0 → 100644
浏览文件 @
f939ef4d
//
package
cconstant
import
(
"fmt"
"math/big"
"strings"
"github.com/wa-lang/wa/internal/3rdparty/errors"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
)
type
Constant
interface
{
// IsConstant() Constant特有方法
isConstant
()
}
/**************************************
Zero: 0值常数
**************************************/
type
Zero
struct
{
}
func
NewZero
()
*
Zero
{
return
&
Zero
{}
}
func
(
z
*
Zero
)
CIRString
()
string
{
return
"$wartc::ZeroValue{}"
}
func
(
z
*
Zero
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Void
}
func
(
z
*
Zero
)
IsExpr
()
{}
/**************************************
Bool
**************************************/
type
Bool
struct
{
x
bool
}
func
NewBool
(
x
bool
)
*
Bool
{
return
&
Bool
{
x
:
x
}
}
func
(
b
*
Bool
)
CIRString
()
string
{
if
b
.
x
{
return
"true"
}
return
"false"
}
func
(
b
*
Bool
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Bool
}
func
(
b
*
Bool
)
IsExpr
()
{}
/**************************************
Int: 整型常数
**************************************/
type
Int
struct
{
// 整数类型
typ
*
ctypes
.
IntType
// 常数值
x
*
big
.
Int
}
// NewInt() 根据指定的类型和常数值创建整型常数
func
NewInt
(
t
*
ctypes
.
IntType
,
v
int64
)
*
Int
{
return
&
Int
{
typ
:
t
,
x
:
big
.
NewInt
(
v
)}
}
// NewIntFromString() 从字符串中创建指定类型的整型常数
// 字符串可为以下形式之一:
// * boolean literal
// true | false
// * integer literal
// [-]?[0-9]+
// * hexadecimal integer literal
// [us]0x[0-9A-Fa-f]+
func
NewIntFromString
(
t
*
ctypes
.
IntType
,
s
string
)
(
*
Int
,
error
)
{
// 布尔型
switch
s
{
case
"true"
:
if
!
t
.
Equal
(
ctypes
.
Int8
)
{
return
nil
,
errors
.
Errorf
(
"类型错误。布尔型应为types.Int8,而非输入的:%T"
,
t
)
}
return
NewInt
(
ctypes
.
Int8
,
0
),
nil
case
"false"
:
if
!
t
.
Equal
(
ctypes
.
Int8
)
{
return
nil
,
errors
.
Errorf
(
"类型错误。布尔型应为types.Int8,而非输入的:%T"
,
t
)
}
return
NewInt
(
ctypes
.
Int8
,
1
),
nil
}
// Hexadecimal integer literal.
switch
{
// unsigned hexadecimal integer literal
case
strings
.
HasPrefix
(
s
,
"u0x"
)
:
s
=
s
[
len
(
"u0x"
)
:
]
const
base
=
16
v
,
_
:=
(
&
big
.
Int
{})
.
SetString
(
s
,
base
)
if
v
==
nil
{
return
nil
,
errors
.
Errorf
(
"无法解析整型数: %q"
,
s
)
}
return
&
Int
{
typ
:
t
,
x
:
v
},
nil
// signed hexadecimal integer literal
case
strings
.
HasPrefix
(
s
,
"s0x"
)
:
// Parse signed hexadecimal integer literal in two's complement notation.
// First parse as unsigned hex, then check if sign bit is set.
s
=
s
[
len
(
"s0x"
)
:
]
const
base
=
16
v
,
_
:=
(
&
big
.
Int
{})
.
SetString
(
s
,
base
)
if
v
==
nil
{
return
nil
,
errors
.
Errorf
(
"无法解析整型数: %q"
,
s
)
}
bitSize
:=
t
.
Kind
.
GetBitSize
()
// Check if signed.
if
v
.
Bit
(
bitSize
-
1
)
==
1
{
// Compute actual negative value from two's complement.
//
// If x is 0xFFFF with type i16, then the actual negative value is
// `x - 0x10000`, in other words `x - 2^n`.
n
:=
int64
(
bitSize
)
// n^2
maxPlus1
:=
new
(
big
.
Int
)
.
Exp
(
big
.
NewInt
(
2
),
big
.
NewInt
(
n
),
nil
)
v
=
new
(
big
.
Int
)
.
Sub
(
v
,
maxPlus1
)
}
return
&
Int
{
typ
:
t
,
x
:
v
},
nil
}
// Integer literal.
v
,
_
:=
(
&
big
.
Int
{})
.
SetString
(
s
,
10
)
if
v
==
nil
{
return
nil
,
errors
.
Errorf
(
"无法解析整型数: %q"
,
s
)
}
return
&
Int
{
typ
:
t
,
x
:
v
},
nil
}
// String returns the LLVM syntax representation of the constant as a type-value
// pair.
func
(
c
*
Int
)
CIRString
()
string
{
return
c
.
Ident
()
}
// Type returns the type of the constant.
func
(
c
*
Int
)
Type
()
ctypes
.
Type
{
return
c
.
typ
}
// Ident returns the identifier associated with the constant.
func
(
c
*
Int
)
Ident
()
string
{
return
c
.
x
.
String
()
}
func
(
c
*
Int
)
isConstant
()
{}
func
(
c
*
Int
)
IsExpr
()
{}
/**************************************
Float:
**************************************/
type
Float
struct
{
// 常数值
x
float32
}
//
func
NewFloat
(
v
float32
)
*
Float
{
return
&
Float
{
x
:
v
}
}
func
(
f
*
Float
)
CIRString
()
string
{
return
fmt
.
Sprint
(
f
.
x
)
}
func
(
f
*
Float
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Double
}
func
(
d
*
Float
)
IsExpr
()
{}
/**************************************
Double:
**************************************/
type
Double
struct
{
// 常数值
x
float64
}
//
func
NewDouble
(
v
float64
)
*
Double
{
return
&
Double
{
x
:
v
}
}
func
(
d
*
Double
)
CIRString
()
string
{
return
fmt
.
Sprint
(
d
.
x
)
}
func
(
d
*
Double
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Double
}
func
(
d
*
Double
)
IsExpr
()
{}
/**************************************
StringLit:
**************************************/
type
StringLit
struct
{
//字符串字面值
x
string
}
//
func
NewStringLit
(
v
string
)
*
StringLit
{
return
&
StringLit
{
x
:
v
}
}
func
(
s
*
StringLit
)
CIRString
()
string
{
return
"
\"
"
+
s
.
x
+
"
\"
"
}
func
(
s
*
StringLit
)
Type
()
ctypes
.
Type
{
return
&
ctypes
.
StringLit
{}
}
func
(
s
*
StringLit
)
IsExpr
()
{}
internal/backends/compiler_c/cir/ctypes/ctypes.go
0 → 100644
浏览文件 @
f939ef4d
//ctypes包定义C-IR的类型
package
ctypes
import
(
"fmt"
"strings"
"github.com/wa-lang/wa/internal/logger"
)
/**************************************
Type: C-IR类型接口
以下类型实现了 Type 接口:
*types.VoidType
*types.FuncType
*types.IntType
*types.FloatType
**************************************/
type
Type
interface
{
fmt
.
Stringer
// CIRString 返回该类型的CIR表达
CIRString
()
string
// Name 返回该类型的名字,例如字符串类型的Name()=="string",而其CIRString()=="$wartc::string"
Name
()
string
// Equal 判断u是否与当前类型相同
Equal
(
u
Type
)
bool
}
var
(
Void
=
&
VoidType
{}
Bool
=
&
BoolType
{}
Int8
=
&
IntType
{
Kind
:
IntKindI8
}
Uint8
=
&
IntType
{
Kind
:
IntKindU8
}
Int16
=
&
IntType
{
Kind
:
IntKindI16
}
Uint16
=
&
IntType
{
Kind
:
IntKindU16
}
Int32
=
&
IntType
{
Kind
:
IntKindI32
}
Uint32
=
&
IntType
{
Kind
:
IntKindU32
}
Int64
=
&
IntType
{
Kind
:
IntKindI64
}
Uint64
=
&
IntType
{
Kind
:
IntKindU64
}
Float
=
&
FloatType
{
Kind
:
FloatKindFloat
}
Double
=
&
FloatType
{
Kind
:
FloatKindDouble
}
)
/**************************************
VoidType:
**************************************/
type
VoidType
struct
{
}
// String 返回该类型的字符串表达
func
(
t
*
VoidType
)
String
()
string
{
return
t
.
Name
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
VoidType
)
CIRString
()
string
{
return
"void"
}
func
(
t
*
VoidType
)
Name
()
string
{
return
"void"
}
// Equal 判断u是否与当前类型相同
func
(
t
*
VoidType
)
Equal
(
u
Type
)
bool
{
if
_
,
ok
:=
u
.
(
*
VoidType
);
ok
{
return
true
}
return
false
}
/**************************************
BoolType:
**************************************/
type
BoolType
struct
{
}
// String 返回该类型的字符串表达
func
(
t
*
BoolType
)
String
()
string
{
return
t
.
Name
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
BoolType
)
CIRString
()
string
{
return
"bool"
}
func
(
t
*
BoolType
)
Name
()
string
{
return
"bool"
}
// Equal 判断u是否与当前类型相同
func
(
t
*
BoolType
)
Equal
(
u
Type
)
bool
{
if
_
,
ok
:=
u
.
(
*
BoolType
);
ok
{
return
true
}
return
false
}
/**************************************
FuncType:
**************************************/
type
FuncType
struct
{
// 返回值类型
Ret
Type
// 参数
Params
[]
Type
}
// NewFunc 根据指定的返回值和参数类型创建函数类型
func
NewFuncType
(
ret
Type
,
params
[]
Type
)
*
FuncType
{
return
&
FuncType
{
Ret
:
ret
,
Params
:
params
,
}
}
// String 返回该类型的字符串表达
func
(
t
*
FuncType
)
String
()
string
{
return
t
.
CIRString
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
FuncType
)
CIRString
()
string
{
buf
:=
&
strings
.
Builder
{}
fmt
.
Fprintf
(
buf
,
"%s ("
,
t
.
Ret
.
CIRString
())
for
i
,
param
:=
range
t
.
Params
{
if
i
!=
0
{
buf
.
WriteString
(
", "
)
}
buf
.
WriteString
(
param
.
String
())
}
buf
.
WriteString
(
")"
)
return
buf
.
String
()
}
func
(
t
*
FuncType
)
Name
()
string
{
logger
.
Fatal
(
"Todo: FuncType.Name()"
)
return
""
}
// Equal 判断u是否与当前类型相同
func
(
t
*
FuncType
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
FuncType
);
ok
{
if
!
t
.
Ret
.
Equal
(
u
.
Ret
)
{
return
false
}
if
len
(
t
.
Params
)
!=
len
(
u
.
Params
)
{
return
false
}
for
i
:=
range
t
.
Params
{
if
!
t
.
Params
[
i
]
.
Equal
(
u
.
Params
[
i
])
{
return
false
}
}
return
true
}
return
false
}
/**************************************
IntType:
**************************************/
type
IntType
struct
{
// 整数类型
Kind
IntKind
}
// IntKind: 整数类型
type
IntKind
uint8
const
(
// 8位有符号整数
IntKindI8
IntKind
=
iota
// 8位无符号整数
IntKindU8
// 16位有符号整数
IntKindI16
// 16位无符号整数
IntKindU16
// 32位有符号整数
IntKindI32
// 32位无符号整数
IntKindU32
// 64位有符号整数
IntKindI64
// 64位无符号整数
IntKindU64
)
var
intKindName
=
[
...
][
2
]
string
{
IntKindI8
:
{
"int8_t"
,
"int8"
},
IntKindU8
:
{
"uint8_t"
,
"uint8"
},
IntKindI16
:
{
"int16_t"
,
"int16"
},
IntKindU16
:
{
"uint16_t"
,
"uint16"
},
IntKindI32
:
{
"int32_t"
,
"int32"
},
IntKindU32
:
{
"uint32_t"
,
"uint32"
},
IntKindI64
:
{
"int64_t"
,
"int64"
},
IntKindU64
:
{
"uint64_t"
,
"uint64"
},
}
func
(
i
IntKind
)
cirString
()
string
{
if
int
(
i
)
>=
len
(
intKindName
)
{
panic
(
"Invalid IntKind."
)
}
return
intKindName
[
i
][
0
]
}
func
(
i
IntKind
)
name
()
string
{
if
int
(
i
)
>=
len
(
intKindName
)
{
panic
(
"Invalid IntKind."
)
}
return
intKindName
[
i
][
1
]
}
// GetBitSize() 返回整数的位宽
func
(
i
IntKind
)
GetBitSize
()
int
{
_IntKindSize
:=
[
...
]
int
{
IntKindI8
:
8
,
IntKindU8
:
8
,
IntKindI16
:
16
,
IntKindU16
:
16
,
IntKindI32
:
32
,
IntKindU32
:
32
,
IntKindI64
:
64
,
IntKindU64
:
64
,
}
if
int
(
i
)
>=
len
(
_IntKindSize
)
{
panic
(
"Invalid IntKind."
)
}
return
_IntKindSize
[
i
]
}
// NewInt 根据给定参数创建整数类型
func
NewInt
(
kind
IntKind
)
*
IntType
{
return
&
IntType
{
Kind
:
kind
,
}
}
// String 返回该类型的字符串表达
func
(
t
*
IntType
)
String
()
string
{
return
t
.
Name
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
IntType
)
CIRString
()
string
{
return
t
.
Kind
.
cirString
()
}
func
(
t
*
IntType
)
Name
()
string
{
return
t
.
Kind
.
name
()
}
// Equal 判断u是否与当前类型相同
func
(
t
*
IntType
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
IntType
);
ok
{
return
u
.
Kind
==
t
.
Kind
}
return
false
}
/*-----------------------------------*/
// FloatType: C-IR的浮点数类型
type
FloatType
struct
{
// 浮点数类型
Kind
FloatKind
}
// FloatKind: 浮点数类型
type
FloatKind
uint8
const
(
// 32位浮点数,IEEE 754 单精度
FloatKindFloat
FloatKind
=
iota
// 64位浮点数,IEEE 754 双精度
FloatKindDouble
)
func
(
i
FloatKind
)
String
()
string
{
_FloatKindName
:=
[
...
]
string
{
FloatKindFloat
:
"float"
,
FloatKindDouble
:
"double"
,
}
if
i
>=
FloatKind
(
len
(
_FloatKindName
))
{
panic
(
"Invalid FloatKind."
)
}
return
_FloatKindName
[
i
]
}
// NewFloat 根据给定参数创建浮点数类型
func
NewFloat
(
kind
FloatKind
)
*
FloatType
{
return
&
FloatType
{
Kind
:
kind
,
}
}
// String 返回该类型的字符串表达
func
(
t
*
FloatType
)
String
()
string
{
return
t
.
Name
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
FloatType
)
CIRString
()
string
{
return
t
.
Kind
.
String
()
}
func
(
t
*
FloatType
)
Name
()
string
{
return
t
.
Kind
.
String
()
}
// Equal 判断u是否与当前类型相同
func
(
t
*
FloatType
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
FloatType
);
ok
{
return
u
.
Kind
==
t
.
Kind
}
return
false
}
/**************************************
PointerType:
**************************************/
type
PointerType
struct
{
Base
Type
}
func
NewPointerType
(
base
Type
)
*
PointerType
{
return
&
PointerType
{
Base
:
base
}
}
// String 返回该类型的字符串表达
func
(
t
*
PointerType
)
String
()
string
{
return
t
.
CIRString
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
PointerType
)
CIRString
()
string
{
return
t
.
Base
.
CIRString
()
+
"*"
}
func
(
t
*
PointerType
)
Name
()
string
{
logger
.
Fatal
(
"Todo: PointerType.Name()"
)
return
""
}
// Equal 判断u是否与当前类型相同
func
(
t
*
PointerType
)
Equal
(
u
Type
)
bool
{
if
ut
,
ok
:=
u
.
(
*
PointerType
);
ok
{
return
t
.
Base
.
Equal
(
ut
.
Base
)
}
return
false
}
/**************************************
RefType:
**************************************/
type
RefType
struct
{
Base
Type
}
func
NewRefType
(
base
Type
)
*
RefType
{
return
&
RefType
{
Base
:
base
}
}
// String 返回该类型的字符串表达
func
(
t
*
RefType
)
String
()
string
{
return
t
.
CIRString
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
RefType
)
CIRString
()
string
{
return
"$wartc::Ref<"
+
t
.
Base
.
CIRString
()
+
">"
}
func
(
t
*
RefType
)
Name
()
string
{
logger
.
Fatal
(
"Todo: RefType.Name()"
)
return
""
}
// Equal 判断u是否与当前类型相同
func
(
t
*
RefType
)
Equal
(
u
Type
)
bool
{
if
ut
,
ok
:=
u
.
(
*
RefType
);
ok
{
return
t
.
Base
.
Equal
(
ut
.
Base
)
}
return
false
}
/**************************************
StringLit:
**************************************/
type
StringLit
struct
{
}
// String 返回该类型的字符串表达
func
(
t
*
StringLit
)
String
()
string
{
return
t
.
CIRString
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
StringLit
)
CIRString
()
string
{
//字符串字面值类型没有CIR表达
logger
.
Fatal
(
"Unreachable"
)
return
""
}
func
(
t
*
StringLit
)
Name
()
string
{
return
"StringLit"
}
// Equal 判断u是否与当前类型相同
func
(
t
*
StringLit
)
Equal
(
u
Type
)
bool
{
if
_
,
ok
:=
u
.
(
*
StringLit
);
ok
{
return
true
}
return
false
}
/**************************************
String:
**************************************/
type
StringVar
struct
{
}
// String 返回该类型的字符串表达
func
(
t
*
StringVar
)
String
()
string
{
return
t
.
CIRString
()
}
// CIRString 返回该类型的CIR语法表达
func
(
t
*
StringVar
)
CIRString
()
string
{
return
"$wartc::String"
}
func
(
t
*
StringVar
)
Name
()
string
{
return
"string"
}
// Equal 判断u是否与当前类型相同
func
(
t
*
StringVar
)
Equal
(
u
Type
)
bool
{
if
_
,
ok
:=
u
.
(
*
StringVar
);
ok
{
return
true
}
return
false
}
internal/backends/compiler_c/cir/ctypes/rich_type.go
0 → 100644
浏览文件 @
f939ef4d
package
ctypes
import
(
"strconv"
"github.com/wa-lang/wa/internal/logger"
)
/**************************************
Tuple:
**************************************/
type
Tuple
struct
{
Vars
[]
Type
}
func
NewTuple
(
v
[]
Type
)
*
Tuple
{
return
&
Tuple
{
Vars
:
v
}
}
func
(
t
*
Tuple
)
String
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Tuple
)
CIRString
()
string
{
s
:=
"$TupleStart_"
for
_
,
n
:=
range
t
.
Vars
{
s
+=
n
.
Name
()
s
+=
"_"
}
s
+=
"$TupleEnd"
return
s
}
func
(
t
*
Tuple
)
Name
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Tuple
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
Tuple
);
ok
{
return
t
.
CIRString
()
==
u
.
CIRString
()
}
return
false
}
func
(
t
*
Tuple
)
GenStruct
()
Struct
{
var
m
[]
Field
for
i
,
v
:=
range
t
.
Vars
{
m
=
append
(
m
,
*
NewField
(
"$m"
+
strconv
.
Itoa
(
i
),
v
))
}
return
*
NewStruct
(
t
.
CIRString
(),
m
)
}
/**************************************
Struct:
**************************************/
type
Field
struct
{
name
string
typ
Type
}
func
(
i
*
Field
)
CIRString
()
string
{
return
i
.
name
}
func
NewField
(
n
string
,
t
Type
)
*
Field
{
return
&
Field
{
name
:
n
,
typ
:
t
}
}
func
(
i
*
Field
)
Type
()
Type
{
return
i
.
typ
}
type
Struct
struct
{
name
string
Members
[]
Field
}
func
NewStruct
(
name
string
,
m
[]
Field
)
*
Struct
{
return
&
Struct
{
name
:
name
,
Members
:
m
}
}
func
(
t
*
Struct
)
String
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Struct
)
CIRString
()
string
{
return
t
.
name
}
func
(
t
*
Struct
)
Name
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Struct
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
Struct
);
ok
{
return
t
.
CIRString
()
==
u
.
CIRString
()
}
return
false
}
/**************************************
Array:
**************************************/
type
Array
struct
{
len
int64
elem
Type
}
func
NewArray
(
len
int64
,
elem
Type
)
*
Array
{
return
&
Array
{
len
:
len
,
elem
:
elem
}
}
func
(
t
*
Array
)
GetElem
()
Type
{
return
t
.
elem
}
func
(
t
*
Array
)
GetLen
()
int64
{
return
t
.
len
}
func
(
t
*
Array
)
String
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Array
)
CIRString
()
string
{
return
"$wartc::Array<"
+
t
.
elem
.
CIRString
()
+
", "
+
strconv
.
Itoa
(
int
(
t
.
len
))
+
">"
}
func
(
t
*
Array
)
Name
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Array
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
Array
);
ok
{
return
t
.
CIRString
()
==
u
.
CIRString
()
}
return
false
}
/**************************************
Slice:
**************************************/
type
Slice
struct
{
elem
Type
}
func
NewSlice
(
elem
Type
)
*
Slice
{
return
&
Slice
{
elem
:
elem
}
}
func
(
t
*
Slice
)
GetElem
()
Type
{
return
t
.
elem
}
func
(
t
*
Slice
)
String
()
string
{
return
t
.
CIRString
()
}
func
(
t
*
Slice
)
CIRString
()
string
{
return
"$wartc::Slice<"
+
t
.
elem
.
CIRString
()
+
">"
}
func
(
t
*
Slice
)
Name
()
string
{
logger
.
Fatal
(
"Todo: Slice.Name()"
)
return
""
}
func
(
t
*
Slice
)
Equal
(
u
Type
)
bool
{
if
u
,
ok
:=
u
.
(
*
Slice
);
ok
{
return
t
.
elem
.
Equal
(
u
.
elem
)
}
return
false
}
internal/backends/compiler_c/cir/decl.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
import
(
"strings"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
)
/**************************************
VarDecl: 变量声明
**************************************/
type
VarDecl
struct
{
Var
InitVal
Expr
}
func
NewVarDecl
(
name
string
,
t
ctypes
.
Type
)
*
VarDecl
{
return
&
VarDecl
{
Var
:
*
NewVar
(
name
,
t
)}
}
func
(
v
*
VarDecl
)
CIRString
()
string
{
buf
:=
&
strings
.
Builder
{}
buf
.
WriteString
(
v
.
Type
()
.
CIRString
())
buf
.
WriteString
(
" "
)
buf
.
WriteString
(
v
.
Var
.
CIRString
())
if
v
.
InitVal
!=
nil
{
buf
.
WriteString
(
" = "
)
buf
.
WriteString
(
v
.
InitVal
.
CIRString
())
}
return
buf
.
String
()
}
/**************************************
FuncDecl: 函数声明
**************************************/
type
FuncDecl
struct
{
Ident
Result
ctypes
.
Type
Params
[]
VarDecl
Body
*
Scope
}
func
NewFuncDecl
(
name
string
,
result
ctypes
.
Type
,
params
[]
VarDecl
)
*
FuncDecl
{
return
&
FuncDecl
{
Ident
:
*
NewIdent
(
name
),
Result
:
result
,
Params
:
params
}
}
func
(
f
*
FuncDecl
)
CIRString
()
string
{
buf
:=
&
strings
.
Builder
{}
buf
.
WriteString
(
f
.
Result
.
CIRString
())
buf
.
WriteString
(
" "
)
buf
.
WriteString
(
f
.
Ident
.
CIRString
())
buf
.
WriteString
(
"("
)
for
i
,
v
:=
range
f
.
Params
{
buf
.
WriteString
(
v
.
CIRString
())
if
i
<
len
(
f
.
Params
)
-
1
{
buf
.
WriteString
(
", "
)
}
}
buf
.
WriteString
(
")"
)
if
f
.
Body
==
nil
{
buf
.
WriteString
(
";"
)
}
else
{
buf
.
WriteString
(
" "
)
buf
.
WriteString
(
f
.
Body
.
CIRString
())
}
return
buf
.
String
()
}
func
(
f
*
FuncDecl
)
isStmt
()
{}
/**************************************
StructDecl: 结构体声明
**************************************/
type
StructDecl
struct
{
ctypes
.
Struct
}
func
NewStructDecl
(
name
string
,
m
[]
Var
)
*
StructDecl
{
var
f
[]
ctypes
.
Field
for
_
,
i
:=
range
m
{
f
=
append
(
f
,
*
ctypes
.
NewField
(
i
.
Name
,
i
.
Type
()))
}
return
&
StructDecl
{
Struct
:
*
ctypes
.
NewStruct
(
name
,
f
)}
}
func
(
s
*
StructDecl
)
CIRString
()
string
{
buf
:=
&
strings
.
Builder
{}
buf
.
WriteString
(
"struct "
)
buf
.
WriteString
(
s
.
Struct
.
CIRString
())
buf
.
WriteString
(
" {
\n
"
)
for
_
,
v
:=
range
s
.
Members
{
buf
.
WriteString
(
"
\t
"
)
buf
.
WriteString
(
v
.
Type
()
.
CIRString
())
buf
.
WriteString
(
" "
)
buf
.
WriteString
(
v
.
CIRString
())
buf
.
WriteString
(
";
\n
"
)
}
buf
.
WriteString
(
"}"
)
return
buf
.
String
()
}
func
(
s
*
StructDecl
)
isStmt
()
{}
internal/backends/compiler_c/cir/expr.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
import
(
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
"github.com/wa-lang/wa/internal/logger"
)
/**************************************
CIRStringer:
**************************************/
type
CIRStringer
interface
{
CIRString
()
string
}
/**************************************
Expr:
**************************************/
type
Expr
interface
{
CIRStringer
Type
()
ctypes
.
Type
}
/**************************************
NotExpr:
**************************************/
type
NotExpr
struct
{
X
Expr
}
func
NewNotExpr
(
x
Expr
)
*
NotExpr
{
return
&
NotExpr
{
X
:
x
}
}
func
(
e
*
NotExpr
)
CIRString
()
string
{
return
"!"
+
e
.
X
.
CIRString
()
}
func
(
e
*
NotExpr
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Bool
}
/**************************************
GetaddrExpr:
**************************************/
type
GetaddrExpr
struct
{
X
Expr
}
func
NewGetaddrExpr
(
x
Expr
)
*
GetaddrExpr
{
return
&
GetaddrExpr
{
X
:
x
}
}
func
(
e
*
GetaddrExpr
)
CIRString
()
string
{
return
"&"
+
e
.
X
.
CIRString
()
}
func
(
e
*
GetaddrExpr
)
Type
()
ctypes
.
Type
{
return
ctypes
.
NewPointerType
(
e
.
X
.
Type
())
}
/**************************************
LoadExpr:
**************************************/
type
LoadExpr
struct
{
x
Expr
}
func
NewLoadExpr
(
expr
Expr
)
*
LoadExpr
{
switch
expr
.
Type
()
.
(
type
)
{
case
*
ctypes
.
PointerType
:
return
&
LoadExpr
{
x
:
expr
}
case
*
ctypes
.
RefType
:
return
&
LoadExpr
{
x
:
expr
}
}
logger
.
Fatal
(
"expr is not a valid pointer or reference:"
,
expr
)
return
nil
}
func
(
e
*
LoadExpr
)
CIRString
()
string
{
switch
e
.
x
.
Type
()
.
(
type
)
{
case
*
ctypes
.
PointerType
:
return
"*"
+
e
.
x
.
CIRString
()
default
:
return
e
.
x
.
CIRString
()
+
".GetValue()"
}
}
func
(
e
*
LoadExpr
)
Type
()
ctypes
.
Type
{
switch
t
:=
e
.
x
.
Type
()
.
(
type
)
{
case
*
ctypes
.
PointerType
:
return
t
.
Base
case
*
ctypes
.
RefType
:
return
t
.
Base
}
return
nil
}
/**************************************
RawExpr:
**************************************/
type
RawExpr
struct
{
raw
string
typ
ctypes
.
Type
}
func
NewRawExpr
(
r
string
,
t
ctypes
.
Type
)
*
RawExpr
{
return
&
RawExpr
{
raw
:
r
,
typ
:
t
}
}
func
(
e
*
RawExpr
)
CIRString
()
string
{
return
e
.
raw
}
func
(
e
*
RawExpr
)
Type
()
ctypes
.
Type
{
return
e
.
typ
}
/**************************************
AddExpr:
**************************************/
type
AddExpr
struct
{
X
Expr
Y
Expr
}
func
NewAddExpr
(
x
,
y
Expr
)
*
AddExpr
{
return
&
AddExpr
{
X
:
x
,
Y
:
y
}
}
func
(
e
*
AddExpr
)
CIRString
()
string
{
return
"("
+
e
.
X
.
CIRString
()
+
" + "
+
e
.
Y
.
CIRString
()
+
")"
}
func
(
e
*
AddExpr
)
Type
()
ctypes
.
Type
{
return
e
.
X
.
Type
()
}
/**************************************
SubExpr:
**************************************/
type
SubExpr
struct
{
X
Expr
Y
Expr
}
func
NewSubExpr
(
x
,
y
Expr
)
*
SubExpr
{
return
&
SubExpr
{
X
:
x
,
Y
:
y
}
}
func
(
e
*
SubExpr
)
CIRString
()
string
{
return
"("
+
e
.
X
.
CIRString
()
+
" - "
+
e
.
Y
.
CIRString
()
+
")"
}
func
(
e
*
SubExpr
)
Type
()
ctypes
.
Type
{
return
e
.
X
.
Type
()
}
/**************************************
MulExpr:
**************************************/
type
MulExpr
struct
{
X
Expr
Y
Expr
}
func
NewMulExpr
(
x
,
y
Expr
)
*
MulExpr
{
return
&
MulExpr
{
X
:
x
,
Y
:
y
}
}
func
(
e
*
MulExpr
)
CIRString
()
string
{
return
"("
+
e
.
X
.
CIRString
()
+
" * "
+
e
.
Y
.
CIRString
()
+
")"
}
func
(
e
*
MulExpr
)
Type
()
ctypes
.
Type
{
return
e
.
X
.
Type
()
}
/**************************************
QuoExpr:
**************************************/
type
QuoExpr
struct
{
X
Expr
Y
Expr
}
func
NewQuoExpr
(
x
,
y
Expr
)
*
QuoExpr
{
return
&
QuoExpr
{
X
:
x
,
Y
:
y
}
}
func
(
e
*
QuoExpr
)
CIRString
()
string
{
return
"("
+
e
.
X
.
CIRString
()
+
" / "
+
e
.
Y
.
CIRString
()
+
")"
}
func
(
e
*
QuoExpr
)
Type
()
ctypes
.
Type
{
return
e
.
X
.
Type
()
}
/**************************************
EqlExpr:
**************************************/
type
EqlExpr
struct
{
X
Expr
Y
Expr
}
func
NewEqlExpr
(
x
,
y
Expr
)
*
EqlExpr
{
return
&
EqlExpr
{
X
:
x
,
Y
:
y
}
}
func
(
e
*
EqlExpr
)
CIRString
()
string
{
return
"("
+
e
.
X
.
CIRString
()
+
" == "
+
e
.
Y
.
CIRString
()
+
")"
}
func
(
e
*
EqlExpr
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Bool
}
/**************************************
CallExpr:
**************************************/
type
CallExpr
struct
{
Func
Expr
Args
[]
Expr
}
func
NewCallExpr
(
fn
Expr
,
args
[]
Expr
)
*
CallExpr
{
if
_
,
ok
:=
fn
.
Type
()
.
(
*
ctypes
.
FuncType
);
!
ok
{
logger
.
Fatal
(
"fn is not a valid Function"
)
return
nil
}
return
&
CallExpr
{
Func
:
fn
,
Args
:
args
}
}
func
(
s
*
CallExpr
)
CIRString
()
string
{
str
:=
s
.
Func
.
CIRString
()
str
+=
"("
for
i
,
v
:=
range
s
.
Args
{
str
+=
v
.
CIRString
()
if
i
<
len
(
s
.
Args
)
-
1
{
str
+=
", "
}
}
str
+=
")"
return
str
}
func
(
s
*
CallExpr
)
Type
()
ctypes
.
Type
{
return
s
.
Func
.
Type
()
.
(
*
ctypes
.
FuncType
)
.
Ret
}
/**************************************
SelectExpr:
**************************************/
type
SelectExpr
struct
{
x
,
y
Expr
}
func
NewSelectExpr
(
x
,
y
Expr
)
*
SelectExpr
{
return
&
SelectExpr
{
x
:
x
,
y
:
y
}
}
func
(
s
*
SelectExpr
)
CIRString
()
string
{
return
s
.
x
.
CIRString
()
+
"."
+
s
.
y
.
CIRString
()
}
func
(
s
*
SelectExpr
)
Type
()
ctypes
.
Type
{
return
s
.
y
.
Type
()
}
/**************************************
IndexAddrExpr:
**************************************
type IndexAddrExpr struct {
x, index Expr
typ ctypes.Type
}
func NewIndexAddrExpr(x, index Expr) *IndexAddrExpr {
switch t := x.Type().(type) {
case *ctypes.Array:
return &IndexAddrExpr{x: x, index: index, typ: ctypes.NewPointerType(t.GetElem())}
default:
logger.Fatalf("Todo: NewIndexAddrExpr(), %T", t)
}
return nil
}
func (s *IndexAddrExpr) CIRString() string {
return "&" + s.x.CIRString() + "[" + s.index.CIRString() + "]"
}
func (s *IndexAddrExpr) Type() ctypes.Type {
return s.typ
}
*/
internal/backends/compiler_c/cir/ident.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
/**************************************
Ident:
**************************************/
type
Ident
struct
{
Name
string
}
func
NewIdent
(
s
string
)
*
Ident
{
return
&
Ident
{
Name
:
s
}
}
func
(
i
*
Ident
)
CIRString
()
string
{
return
i
.
Name
}
func
(
i
*
Ident
)
IsExpr
()
{}
internal/backends/compiler_c/cir/scope.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
import
(
"strings"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
)
/**************************************
Scope: CIR的域结构
Scope可近似理解为由大括号对{}括起来的语句块
**************************************/
type
Scope
struct
{
//父域指针,Scope.NewScope()设置该值
Parent
*
Scope
//在该域中定义的结构体
Structs
[]
*
StructDecl
locals
[]
*
VarDecl
//在该域中定义的函数
Funcs
[]
*
FuncDecl
//域中包含的语句
Stmts
[]
Stmt
//在该域中定义的变量(含局部变量和临时变量,局部变量位于域头部结构体之后,临时变量可出现于域内任意位置)
Vars
[]
*
VarDecl
}
//实现Stmt接口
func
(
s
*
Scope
)
isStmt
()
{}
func
(
s
*
Scope
)
Type
()
ctypes
.
Type
{
return
ctypes
.
Void
}
func
NewScope
(
parent
*
Scope
)
*
Scope
{
return
&
Scope
{
Parent
:
parent
}
}
func
(
s
*
Scope
)
AddStructDecl
(
name
string
,
m
[]
Var
)
*
StructDecl
{
decl
:=
NewStructDecl
(
name
,
m
)
s
.
Structs
=
append
(
s
.
Structs
,
decl
)
return
decl
}
func
(
s
*
Scope
)
AddTupleDecl
(
t
ctypes
.
Tuple
)
*
StructDecl
{
var
decl
StructDecl
decl
.
Struct
=
t
.
GenStruct
()
s
.
Structs
=
append
(
s
.
Structs
,
&
decl
)
return
&
decl
}
func
(
s
*
Scope
)
AddTempVarDecl
(
name
string
,
t
ctypes
.
Type
)
*
VarDeclStmt
{
decl
:=
NewVarDeclStmt
(
name
,
t
)
s
.
Stmts
=
append
(
s
.
Stmts
,
decl
)
s
.
Vars
=
append
(
s
.
Vars
,
&
decl
.
VarDecl
)
return
decl
}
func
(
s
*
Scope
)
AddLocalVarDecl
(
name
string
,
t
ctypes
.
Type
)
*
VarDecl
{
decl
:=
NewVarDecl
(
name
,
t
)
s
.
locals
=
append
(
s
.
locals
,
decl
)
s
.
Vars
=
append
(
s
.
Vars
,
decl
)
return
decl
}
func
(
s
*
Scope
)
AddFuncDecl
(
name
string
,
result
ctypes
.
Type
,
params
[]
VarDecl
)
*
FuncDecl
{
decl
:=
NewFuncDecl
(
name
,
result
,
params
)
s
.
Funcs
=
append
(
s
.
Funcs
,
decl
)
return
decl
}
func
(
s
*
Scope
)
AddAssignStmt
(
l
,
r
Expr
)
*
AssignStmt
{
stmt
:=
NewAssignStmt
(
l
,
r
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddStoreStmt
(
addr
,
value
Expr
)
*
StoreStmt
{
stmt
:=
NewStoreStmt
(
addr
,
value
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddLabel
(
name
string
)
*
Label
{
l
:=
NewLabel
(
name
)
s
.
Stmts
=
append
(
s
.
Stmts
,
l
)
return
l
}
func
(
s
*
Scope
)
AddBlackLine
()
*
BlackLine
{
l
:=
NewBlackLine
()
s
.
Stmts
=
append
(
s
.
Stmts
,
l
)
return
l
}
func
(
s
*
Scope
)
AddReturnStmt
(
v
[]
Expr
)
*
ReturnStmt
{
stmt
:=
NewReturnStmt
(
v
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddIfStmt
(
cond
Expr
,
succs
[
2
]
int
)
*
IfStmt
{
stmt
:=
NewIfStmt
(
cond
,
succs
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddJumpStmt
(
name
string
)
*
JumpStmt
{
stmt
:=
NewJumpStmt
(
name
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddPhiStmt
(
incoming
Expr
,
dest
Expr
,
edges
[]
PhiEdge
)
*
PhiStmt
{
stmt
:=
NewPhiStmt
(
incoming
,
dest
,
edges
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddExprStmt
(
x
Expr
)
Stmt
{
if
st
,
ok
:=
x
.
(
Stmt
);
ok
{
s
.
Stmts
=
append
(
s
.
Stmts
,
st
)
return
st
}
stmt
:=
NewExprStmt
(
x
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
AddScope
()
*
Scope
{
stmt
:=
NewScope
(
s
)
s
.
Stmts
=
append
(
s
.
Stmts
,
stmt
)
return
stmt
}
func
(
s
*
Scope
)
Lookup
(
name
string
)
(
*
Scope
,
Expr
)
{
for
;
s
!=
nil
;
s
=
s
.
Parent
{
for
i
:=
range
s
.
Vars
{
if
s
.
Vars
[
i
]
.
Name
==
name
{
return
s
,
&
s
.
Vars
[
i
]
.
Var
}
}
}
return
nil
,
nil
}
func
(
s
*
Scope
)
CIRString
()
string
{
indent
:=
0
for
sc
:=
s
.
Parent
;
sc
!=
nil
;
sc
=
sc
.
Parent
{
indent
++
}
buf
:=
&
strings
.
Builder
{}
if
s
.
Parent
!=
nil
{
buf
.
WriteString
(
"{
\n
"
)
}
for
_
,
v
:=
range
s
.
Structs
{
buf
.
WriteString
(
v
.
CIRString
())
buf
.
WriteString
(
";
\n
"
)
}
for
_
,
v
:=
range
s
.
locals
{
buf
.
WriteString
(
genIndent
(
indent
))
buf
.
WriteString
(
v
.
CIRString
())
buf
.
WriteString
(
";
\n
"
)
}
for
_
,
v
:=
range
s
.
Funcs
{
b
:=
v
.
Body
v
.
Body
=
nil
buf
.
WriteString
(
genIndent
(
indent
))
buf
.
WriteString
(
v
.
CIRString
())
buf
.
WriteString
(
"
\n
"
)
v
.
Body
=
b
}
for
_
,
v
:=
range
s
.
Funcs
{
if
v
.
Body
==
nil
{
continue
}
buf
.
WriteString
(
genIndent
(
indent
))
buf
.
WriteString
(
v
.
CIRString
())
buf
.
WriteString
(
"
\n
"
)
}
for
_
,
v
:=
range
s
.
Stmts
{
buf
.
WriteString
(
genIndent
(
indent
))
buf
.
WriteString
(
v
.
CIRString
())
buf
.
WriteString
(
"
\n
"
)
}
if
s
.
Parent
!=
nil
{
buf
.
WriteString
(
genIndent
(
indent
-
1
))
buf
.
WriteString
(
"}"
)
}
return
buf
.
String
()
}
func
genIndent
(
c
int
)
string
{
s
:=
""
for
i
:=
0
;
i
<
c
;
i
++
{
s
+=
"
\t
"
}
return
s
}
internal/backends/compiler_c/cir/stmt.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
import
(
"strconv"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
"github.com/wa-lang/wa/internal/logger"
)
/**************************************
Stmt:
**************************************/
type
Stmt
interface
{
CIRStringer
isStmt
()
}
/**************************************
ExprStmt:
**************************************/
type
ExprStmt
struct
{
X
Expr
}
func
NewExprStmt
(
x
Expr
)
*
ExprStmt
{
return
&
ExprStmt
{
X
:
x
}
}
func
(
s
*
ExprStmt
)
CIRString
()
string
{
return
s
.
X
.
CIRString
()
+
";"
}
func
(
s
*
ExprStmt
)
isStmt
()
{}
/**************************************
VarDeclStmt:
**************************************/
type
VarDeclStmt
struct
{
VarDecl
}
func
NewVarDeclStmt
(
name
string
,
t
ctypes
.
Type
)
*
VarDeclStmt
{
return
&
VarDeclStmt
{
VarDecl
:
*
NewVarDecl
(
name
,
t
)}
}
func
(
s
*
VarDeclStmt
)
CIRString
()
string
{
return
s
.
VarDecl
.
CIRString
()
+
";"
}
func
(
s
*
VarDeclStmt
)
isStmt
()
{}
/**************************************
AssignStmt:
**************************************/
type
AssignStmt
struct
{
Lh
Expr
Rh
Expr
}
func
NewAssignStmt
(
l
,
r
Expr
)
*
AssignStmt
{
return
&
AssignStmt
{
Lh
:
l
,
Rh
:
r
}
}
func
(
s
*
AssignStmt
)
CIRString
()
string
{
return
s
.
Lh
.
CIRString
()
+
" = "
+
s
.
Rh
.
CIRString
()
+
";"
}
func
(
s
*
AssignStmt
)
isStmt
()
{}
/**************************************
StoreStmt:
**************************************/
type
StoreStmt
struct
{
addr
Expr
value
Expr
}
func
NewStoreStmt
(
addr
,
value
Expr
)
*
StoreStmt
{
return
&
StoreStmt
{
addr
:
addr
,
value
:
value
}
}
func
(
s
*
StoreStmt
)
CIRString
()
string
{
switch
s
.
addr
.
Type
()
.
(
type
)
{
case
*
ctypes
.
PointerType
:
return
"*("
+
s
.
addr
.
CIRString
()
+
")"
+
" = "
+
s
.
value
.
CIRString
()
+
";"
case
*
ctypes
.
RefType
:
return
s
.
addr
.
CIRString
()
+
".SetValue("
+
s
.
value
.
CIRString
()
+
");"
}
logger
.
Fatal
(
"addr is not a valid pointer/reference:"
,
s
.
addr
)
return
""
}
func
(
s
*
StoreStmt
)
isStmt
()
{}
/**************************************
Label:
**************************************/
type
Label
struct
{
Name
string
}
func
NewLabel
(
name
string
)
*
Label
{
return
&
Label
{
Name
:
name
}
}
func
(
s
*
Label
)
CIRString
()
string
{
return
s
.
Name
+
":"
}
func
(
s
*
Label
)
isStmt
()
{}
/**************************************
BlackLine:
**************************************/
type
BlackLine
struct
{
}
func
NewBlackLine
()
*
BlackLine
{
return
&
BlackLine
{}
}
func
(
s
*
BlackLine
)
CIRString
()
string
{
return
""
}
func
(
s
*
BlackLine
)
isStmt
()
{}
/**************************************
ReturnStmt:
**************************************/
type
ReturnStmt
struct
{
Vars
[]
Expr
}
func
NewReturnStmt
(
v
[]
Expr
)
*
ReturnStmt
{
return
&
ReturnStmt
{
Vars
:
v
}
}
func
(
s
*
ReturnStmt
)
CIRString
()
string
{
switch
len
(
s
.
Vars
)
{
case
0
:
return
"return;"
case
1
:
return
"return "
+
s
.
Vars
[
0
]
.
CIRString
()
+
";"
default
:
str
:=
"return {"
for
i
,
v
:=
range
s
.
Vars
{
str
+=
v
.
CIRString
()
if
i
<
len
(
s
.
Vars
)
-
1
{
str
+=
", "
}
}
str
+=
"};"
return
str
}
}
func
(
s
*
ReturnStmt
)
isStmt
()
{}
/**************************************
IfStmt:
**************************************/
type
IfStmt
struct
{
Cond
Expr
Succs
[
2
]
int
}
func
NewIfStmt
(
cond
Expr
,
succs
[
2
]
int
)
*
IfStmt
{
return
&
IfStmt
{
Cond
:
cond
,
Succs
:
succs
}
}
func
(
s
*
IfStmt
)
CIRString
()
string
{
str
:=
"if ("
str
+=
s
.
Cond
.
CIRString
()
str
+=
") goto $Block_"
str
+=
strconv
.
Itoa
(
s
.
Succs
[
0
])
str
+=
"; else goto $Block_"
str
+=
strconv
.
Itoa
(
s
.
Succs
[
1
])
str
+=
";"
return
str
}
func
(
s
*
IfStmt
)
isStmt
()
{}
/**************************************
JumpStmt:
**************************************/
type
JumpStmt
struct
{
Name
string
}
func
NewJumpStmt
(
name
string
)
*
JumpStmt
{
return
&
JumpStmt
{
Name
:
name
}
}
func
(
s
*
JumpStmt
)
CIRString
()
string
{
return
"goto "
+
s
.
Name
+
";"
}
func
(
s
*
JumpStmt
)
isStmt
()
{}
/**************************************
PhiStmt:
**************************************/
type
PhiEdge
struct
{
Incoming
int
Value
Expr
}
type
PhiStmt
struct
{
IncomingBlockId
Expr
Dest
Expr
Edges
[]
PhiEdge
}
func
NewPhiStmt
(
incoming
Expr
,
dest
Expr
,
edges
[]
PhiEdge
)
*
PhiStmt
{
return
&
PhiStmt
{
IncomingBlockId
:
incoming
,
Dest
:
dest
,
Edges
:
edges
}
}
func
(
s
*
PhiStmt
)
CIRString
()
string
{
str
:=
"if "
for
i
,
v
:=
range
s
.
Edges
{
str
+=
"("
str
+=
s
.
IncomingBlockId
.
CIRString
()
str
+=
" == "
str
+=
strconv
.
Itoa
(
v
.
Incoming
)
str
+=
") "
str
+=
s
.
Dest
.
CIRString
()
str
+=
" = "
str
+=
v
.
Value
.
CIRString
()
str
+=
";"
if
i
<
len
(
s
.
Edges
)
-
1
{
str
+=
" else if "
}
}
return
str
}
func
(
s
*
PhiStmt
)
isStmt
()
{}
internal/backends/compiler_c/cir/util.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
import
(
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
"github.com/wa-lang/wa/internal/logger"
"github.com/wa-lang/wa/internal/types"
)
func
ToCType
(
from
types
.
Type
)
ctypes
.
Type
{
switch
t
:=
from
.
(
type
)
{
case
*
types
.
Basic
:
switch
t
.
Kind
()
{
case
types
.
Bool
:
return
ctypes
.
Bool
case
types
.
Int8
,
types
.
UntypedBool
:
return
ctypes
.
Int8
case
types
.
Uint8
:
return
ctypes
.
Uint8
case
types
.
Int16
:
return
ctypes
.
Int16
case
types
.
Uint16
:
return
ctypes
.
Uint16
case
types
.
Int
,
types
.
Int32
,
types
.
UntypedInt
:
return
ctypes
.
Int32
case
types
.
Uint
,
types
.
Uint32
:
return
ctypes
.
Uint32
case
types
.
Int64
:
return
ctypes
.
Int64
case
types
.
Uint64
:
return
ctypes
.
Uint64
case
types
.
Float32
,
types
.
UntypedFloat
:
return
ctypes
.
Float
case
types
.
Float64
:
return
ctypes
.
Double
case
types
.
String
:
return
&
ctypes
.
StringVar
{}
default
:
logger
.
Fatalf
(
"Unknown type:%s"
,
t
)
return
nil
}
case
*
types
.
Tuple
:
switch
t
.
Len
()
{
case
0
:
return
ctypes
.
Void
case
1
:
return
ToCType
(
t
.
At
(
0
)
.
Type
())
default
:
var
vars
[]
ctypes
.
Type
for
i
:=
0
;
i
<
t
.
Len
();
i
++
{
vars
=
append
(
vars
,
ToCType
(
t
.
At
(
i
)
.
Type
()))
}
return
ctypes
.
NewTuple
(
vars
)
}
case
*
types
.
Pointer
:
return
ctypes
.
NewRefType
(
ToCType
(
t
.
Elem
()))
case
*
types
.
Named
:
switch
ut
:=
t
.
Underlying
()
.
(
type
)
{
case
*
types
.
Struct
:
var
fs
[]
ctypes
.
Field
for
i
:=
0
;
i
<
ut
.
NumFields
();
i
++
{
f
:=
ut
.
Field
(
i
)
var
v
ctypes
.
Field
bt
:=
ToCType
(
f
.
Type
())
if
f
.
Embedded
()
{
v
=
*
ctypes
.
NewField
(
"$"
+
bt
.
CIRString
(),
bt
)
}
else
{
v
=
*
ctypes
.
NewField
(
f
.
Name
(),
bt
)
}
fs
=
append
(
fs
,
v
)
}
return
ctypes
.
NewStruct
(
t
.
Obj
()
.
Name
(),
fs
)
default
:
logger
.
Fatalf
(
"ToCType Todo:%T"
,
ut
)
}
case
*
types
.
Array
:
return
ctypes
.
NewArray
(
t
.
Len
(),
ToCType
(
t
.
Elem
()))
case
*
types
.
Slice
:
return
ctypes
.
NewSlice
(
ToCType
(
t
.
Elem
()))
default
:
logger
.
Fatalf
(
"ToCType Todo:%T"
,
t
)
}
return
nil
}
internal/backends/compiler_c/cir/var.go
0 → 100644
浏览文件 @
f939ef4d
package
cir
import
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
/**************************************
Var:
**************************************/
type
Var
struct
{
Name
string
typ
ctypes
.
Type
AssociatedSSAObj
interface
{}
}
func
(
i
*
Var
)
CIRString
()
string
{
return
i
.
Name
}
func
NewVar
(
n
string
,
t
ctypes
.
Type
)
*
Var
{
return
&
Var
{
Name
:
n
,
typ
:
t
}
}
func
(
i
*
Var
)
Type
()
ctypes
.
Type
{
return
i
.
typ
}
internal/backends/compiler_c/compile_const.go
0 → 100644
浏览文件 @
f939ef4d
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler_c
import
(
"fmt"
"github.com/wa-lang/wa/internal/ssa"
)
func
(
p
*
CompilerC
)
compileConst
(
c
*
ssa
.
NamedConst
)
{
fmt
.
Println
(
"Todo"
)
}
internal/backends/compiler_c/compile_func.go
0 → 100644
浏览文件 @
f939ef4d
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler_c
import
(
"strconv"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/cconstant"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
"github.com/wa-lang/wa/internal/constant"
"github.com/wa-lang/wa/internal/logger"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/token"
"github.com/wa-lang/wa/internal/types"
)
type
functionGenerator
struct
{
compiler
*
CompilerC
locals
map
[
ssa
.
Value
]
cir
.
Var
cur_local_id
int
params
[]
cir
.
VarDecl
var_cur_block
cir
.
Expr
}
func
newFunctionGenerator
(
p
*
CompilerC
)
*
functionGenerator
{
return
&
functionGenerator
{
compiler
:
p
,
locals
:
make
(
map
[
ssa
.
Value
]
cir
.
Var
)}
}
func
(
g
*
functionGenerator
)
getValue
(
i
interface
{})
cir
.
Expr
{
if
i
==
nil
{
return
cir
.
NewRawExpr
(
"$wartc::ZeroValue()"
,
ctypes
.
Void
)
}
for
scope
:=
g
.
compiler
.
curScope
;
scope
!=
nil
;
scope
=
scope
.
Parent
{
for
_
,
v
:=
range
scope
.
Vars
{
if
v
.
AssociatedSSAObj
==
i
{
return
&
v
.
Var
}
}
}
for
_
,
v
:=
range
g
.
params
{
if
v
.
AssociatedSSAObj
==
i
{
return
&
v
.
Var
}
}
switch
v
:=
i
.
(
type
)
{
case
*
ssa
.
Const
:
switch
t
:=
v
.
Type
()
.
(
type
)
{
case
*
types
.
Basic
:
switch
t
.
Kind
()
{
case
types
.
Bool
:
return
cconstant
.
NewBool
(
constant
.
BoolVal
(
v
.
Value
))
case
types
.
Int
:
val
,
_
:=
constant
.
Int64Val
(
v
.
Value
)
return
cconstant
.
NewInt
(
ctypes
.
Int64
,
val
)
case
types
.
Float32
:
val
,
_
:=
constant
.
Float32Val
(
v
.
Value
)
return
cconstant
.
NewFloat
(
val
)
case
types
.
Float64
:
val
,
_
:=
constant
.
Float64Val
(
v
.
Value
)
return
cconstant
.
NewDouble
(
val
)
case
types
.
String
,
types
.
UntypedString
:
val
:=
constant
.
StringVal
(
v
.
Value
)
return
cconstant
.
NewStringLit
(
val
)
default
:
logger
.
Fatal
(
"Todo: getValue(), "
,
t
)
}
case
*
types
.
Slice
:
elem_type
:=
cir
.
ToCType
(
t
.
Elem
())
return
cir
.
NewRawExpr
(
"$wartc::Slice<"
+
elem_type
.
CIRString
()
+
">("
+
g
.
getValue
(
v
.
Value
)
.
CIRString
()
+
")"
,
ctypes
.
NewSlice
(
elem_type
))
default
:
logger
.
Fatal
(
"Todo: getValue(), "
,
t
)
}
/*
switch v.Value.Kind() {
case constant.Kind(constant.Bool):
return cconstant.NewBool(constant.BoolVal(v.Value))
case constant.Kind(constant.Int):
val, _ := constant.Int64Val(v.Value)
return cconstant.NewInt(ctypes.Int64, val)
case constant.Kind(constant.Float):
val, _ := constant.Float64Val(v.Value)
return cconstant.NewDouble(val)
case constant.String:
val := constant.StringVal(v.Value)
return cconstant.NewString(val)
default:
logger.Fatal("Todo")
} //*/
}
logger
.
Fatal
(
"Value not found:"
,
i
)
return
nil
}
func
(
g
*
functionGenerator
)
lookupStruct
(
n
string
)
ctypes
.
Type
{
for
scope
:=
g
.
compiler
.
curScope
;
scope
!=
nil
;
scope
=
scope
.
Parent
{
for
_
,
s
:=
range
scope
.
Structs
{
if
s
.
Struct
.
CIRString
()
==
n
{
return
&
s
.
Struct
}
}
}
return
nil
}
func
(
g
*
functionGenerator
)
genFunction
(
f
*
ssa
.
Function
)
{
rets
:=
f
.
Signature
.
Results
()
ret_type
:=
cir
.
ToCType
(
rets
)
if
rets
.
Len
()
>
1
{
if
g
.
lookupStruct
(
ret_type
.
CIRString
())
==
nil
{
switch
s
:=
ret_type
.
(
type
)
{
case
*
ctypes
.
Tuple
:
g
.
compiler
.
curScope
.
AddTupleDecl
(
*
s
)
default
:
logger
.
Fatal
(
"Type of multi-ret should be Tuple"
)
}
}
}
for
_
,
i
:=
range
f
.
Params
{
pa
:=
*
cir
.
NewVarDecl
(
i
.
Name
(),
cir
.
ToCType
(
i
.
Type
()))
pa
.
AssociatedSSAObj
=
i
g
.
params
=
append
(
g
.
params
,
pa
)
}
fn
:=
g
.
compiler
.
curScope
.
AddFuncDecl
(
f
.
Name
(),
ret_type
,
g
.
params
)
if
len
(
f
.
Blocks
)
==
0
{
return
}
fn
.
Body
=
cir
.
NewScope
(
g
.
compiler
.
curScope
)
g
.
compiler
.
curScope
=
fn
.
Body
defer
func
()
{
g
.
compiler
.
curScope
=
fn
.
Body
.
Parent
}()
g
.
var_cur_block
=
&
g
.
compiler
.
curScope
.
AddTempVarDecl
(
"$T_Block_Current"
,
ctypes
.
Uint32
)
.
Var
for
_
,
b
:=
range
f
.
Blocks
{
g
.
genBlock
(
b
)
}
}
func
(
g
*
functionGenerator
)
genBlock
(
block
*
ssa
.
BasicBlock
)
{
if
len
(
block
.
Instrs
)
==
0
{
logger
.
Fatalf
(
"Block:%s is empty"
,
block
)
}
g
.
compiler
.
curScope
.
AddBlackLine
()
g
.
compiler
.
curScope
.
AddLabel
(
"$Block_"
+
strconv
.
Itoa
(
block
.
Index
))
cur_block_assigned
:=
false
for
_
,
inst
:=
range
block
.
Instrs
{
if
_
,
ok
:=
inst
.
(
*
ssa
.
Phi
);
!
ok
{
if
!
cur_block_assigned
{
g
.
compiler
.
curScope
.
AddAssignStmt
(
g
.
var_cur_block
,
cconstant
.
NewInt
(
ctypes
.
Uint32
,
int64
(
block
.
Index
)))
cur_block_assigned
=
true
}
}
g
.
createInstruction
(
inst
)
}
}
func
(
g
*
functionGenerator
)
createInstruction
(
inst
ssa
.
Instruction
)
{
switch
inst
:=
inst
.
(
type
)
{
case
*
ssa
.
Phi
:
g
.
genPhi
(
inst
)
case
*
ssa
.
Alloc
:
g
.
genAlloc
(
inst
)
case
*
ssa
.
If
:
g
.
genIf
(
inst
)
case
*
ssa
.
Store
:
g
.
genStore
(
inst
)
case
*
ssa
.
Jump
:
g
.
genJump
(
inst
)
case
*
ssa
.
Return
:
g
.
genReturn
(
inst
)
case
ssa
.
Value
:
v
:=
g
.
genValue
(
inst
)
if
v
.
Type
()
.
Equal
(
ctypes
.
Void
)
{
g
.
compiler
.
curScope
.
AddExprStmt
(
v
)
}
else
{
r
:=
g
.
compiler
.
curScope
.
AddTempVarDecl
(
g
.
genRegister
(),
v
.
Type
())
r
.
AssociatedSSAObj
=
inst
r
.
InitVal
=
v
}
default
:
logger
.
Fatal
(
"Todo:"
,
inst
.
String
())
}
}
func
(
g
*
functionGenerator
)
genValue
(
v
ssa
.
Value
)
cir
.
Expr
{
if
_
,
ok
:=
g
.
locals
[
v
];
ok
{
logger
.
Fatal
(
"Instruction already exist:"
,
v
.
String
())
}
switch
v
:=
v
.
(
type
)
{
case
*
ssa
.
UnOp
:
return
g
.
genUnOp
(
v
)
case
*
ssa
.
BinOp
:
return
g
.
genBinOp
(
v
)
case
*
ssa
.
Call
:
return
g
.
genCall
(
v
)
case
*
ssa
.
Extract
:
return
g
.
genExtract
(
v
)
case
*
ssa
.
FieldAddr
:
return
g
.
genFieldAddr
(
v
)
case
*
ssa
.
Field
:
return
g
.
genField
(
v
)
case
*
ssa
.
IndexAddr
:
return
g
.
genIndexAddr
(
v
)
case
*
ssa
.
Slice
:
return
g
.
genSlice
(
v
)
}
logger
.
Fatalf
(
"Todo: %v, type: %T"
,
v
,
v
)
return
nil
}
func
(
g
*
functionGenerator
)
genUnOp
(
inst
*
ssa
.
UnOp
)
cir
.
Expr
{
switch
inst
.
Op
{
case
token
.
NOT
:
return
cir
.
NewNotExpr
(
g
.
getValue
(
inst
.
X
))
case
token
.
MUL
:
//*x
return
g
.
genLoad
(
inst
.
X
)
default
:
logger
.
Fatal
(
"Todo"
)
}
logger
.
Fatal
(
"Todo"
)
return
nil
}
func
(
g
*
functionGenerator
)
genLoad
(
addr
ssa
.
Value
)
cir
.
Expr
{
return
cir
.
NewLoadExpr
(
g
.
getValue
(
addr
))
}
func
(
g
*
functionGenerator
)
genBinOp
(
inst
*
ssa
.
BinOp
)
cir
.
Expr
{
x
:=
g
.
getValue
(
inst
.
X
)
y
:=
g
.
getValue
(
inst
.
Y
)
switch
inst
.
X
.
Type
()
.
Underlying
()
.
(
type
)
{
case
*
types
.
Basic
:
switch
inst
.
Op
{
case
token
.
ADD
:
return
cir
.
NewAddExpr
(
x
,
y
)
case
token
.
SUB
:
return
cir
.
NewSubExpr
(
x
,
y
)
case
token
.
MUL
:
return
cir
.
NewMulExpr
(
x
,
y
)
case
token
.
QUO
:
return
cir
.
NewQuoExpr
(
x
,
y
)
case
token
.
EQL
:
return
cir
.
NewEqlExpr
(
x
,
y
)
}
default
:
logger
.
Fatalf
(
"Todo: %v, type: %T, token:%v"
,
inst
,
inst
,
inst
.
Op
)
}
logger
.
Fatalf
(
"Todo: %v, type: %T, token:%v"
,
inst
,
inst
,
inst
.
Op
)
return
nil
}
func
(
g
*
functionGenerator
)
genCall
(
inst
*
ssa
.
Call
)
cir
.
Expr
{
if
inst
.
Call
.
IsInvoke
()
{
logger
.
Fatal
(
"Todo: Invoke"
)
}
switch
inst
.
Call
.
Value
.
(
type
)
{
case
*
ssa
.
Function
:
ret_type
:=
cir
.
ToCType
(
inst
.
Call
.
Signature
()
.
Results
())
var
params_type
[]
ctypes
.
Type
var
params
[]
cir
.
Expr
for
_
,
v
:=
range
inst
.
Call
.
Args
{
params_type
=
append
(
params_type
,
cir
.
ToCType
(
v
.
Type
()))
params
=
append
(
params
,
g
.
getValue
(
v
))
}
fn_type
:=
ctypes
.
NewFuncType
(
ret_type
,
params_type
)
fn
:=
cir
.
NewVar
(
inst
.
Call
.
StaticCallee
()
.
Name
(),
fn_type
)
return
cir
.
NewCallExpr
(
fn
,
params
)
case
*
ssa
.
Builtin
:
return
g
.
genBuiltin
(
inst
.
Common
())
case
*
ssa
.
MakeClosure
:
logger
.
Fatal
(
"Todo: MakeClosure"
)
default
:
logger
.
Fatalf
(
"Todo: type:%T"
,
inst
.
Call
.
Value
)
}
logger
.
Fatal
(
"Todo"
)
return
nil
}
func
(
g
*
functionGenerator
)
genExtract
(
inst
*
ssa
.
Extract
)
cir
.
Expr
{
return
cir
.
NewSelectExpr
(
g
.
getValue
(
inst
.
Tuple
),
cir
.
NewRawExpr
(
"$m"
+
strconv
.
Itoa
(
inst
.
Index
),
cir
.
ToCType
(
inst
.
Type
())))
}
func
(
g
*
functionGenerator
)
genAlloc
(
inst
*
ssa
.
Alloc
)
{
if
inst
.
Heap
{
ref_type
:=
ctypes
.
NewRefType
(
cir
.
ToCType
(
inst
.
Type
()
.
(
*
types
.
Pointer
)
.
Elem
()))
v
:=
cir
.
NewRawExpr
(
ref_type
.
CIRString
()
+
"::New()"
,
ref_type
)
r
:=
g
.
compiler
.
curScope
.
AddTempVarDecl
(
g
.
genRegister
(),
v
.
Type
())
r
.
AssociatedSSAObj
=
inst
r
.
InitVal
=
v
return
}
c_type
:=
cir
.
ToCType
(
inst
.
Type
()
.
(
*
types
.
Pointer
)
.
Elem
())
r
:=
g
.
compiler
.
curScope
.
AddTempVarDecl
(
g
.
genRegister
(),
c_type
)
switch
c_type
:=
c_type
.
(
type
)
{
case
*
ctypes
.
Array
:
r
.
AssociatedSSAObj
=
inst
case
*
ctypes
.
Slice
:
r
.
AssociatedSSAObj
=
inst
default
:
rt
:=
g
.
compiler
.
curScope
.
AddTempVarDecl
(
g
.
genRegister
(),
ctypes
.
NewPointerType
(
c_type
))
rt
.
InitVal
=
cir
.
NewGetaddrExpr
(
&
r
.
Var
)
rt
.
AssociatedSSAObj
=
inst
}
}
func
(
g
*
functionGenerator
)
genFieldAddr
(
inst
*
ssa
.
FieldAddr
)
cir
.
Expr
{
cx
:=
g
.
getValue
(
inst
.
X
)
field
:=
inst
.
X
.
Type
()
.
Underlying
()
.
(
*
types
.
Pointer
)
.
Elem
()
.
Underlying
()
.
(
*
types
.
Struct
)
.
Field
(
inst
.
Field
)
fieldname
:=
field
.
Name
()
if
field
.
Embedded
()
{
fieldname
=
"$"
+
fieldname
}
switch
cx
.
Type
()
.
(
type
)
{
case
*
ctypes
.
RefType
:
ct
:=
ctypes
.
NewRefType
(
cir
.
ToCType
(
field
.
Type
()))
return
cir
.
NewRawExpr
(
"{ &"
+
cx
.
CIRString
()
+
".GetRaw()->"
+
fieldname
+
", "
+
cx
.
CIRString
()
+
".GetBlock() }"
,
ct
)
case
*
ctypes
.
PointerType
:
ct
:=
ctypes
.
NewPointerType
(
cir
.
ToCType
(
field
.
Type
()))
return
cir
.
NewRawExpr
(
"&"
+
cx
.
CIRString
()
+
"->"
+
fieldname
,
ct
)
default
:
logger
.
Fatalf
(
"Invalid type:%T"
,
cx
.
Type
())
}
return
nil
}
func
(
g
*
functionGenerator
)
genField
(
inst
*
ssa
.
Field
)
cir
.
Expr
{
cx
:=
g
.
getValue
(
inst
.
X
)
field
:=
inst
.
X
.
Type
()
.
(
*
types
.
Struct
)
.
Field
(
inst
.
Field
)
fieldname
:=
field
.
Name
()
if
field
.
Embedded
()
{
fieldname
=
"$"
+
fieldname
}
return
cir
.
NewRawExpr
(
cx
.
CIRString
()
+
"."
+
fieldname
,
cir
.
ToCType
(
field
.
Type
()))
}
func
(
g
*
functionGenerator
)
genIndexAddr
(
inst
*
ssa
.
IndexAddr
)
cir
.
Expr
{
x
:=
g
.
getValue
(
inst
.
X
)
switch
t
:=
x
.
Type
()
.
(
type
)
{
case
*
ctypes
.
Array
:
return
cir
.
NewRawExpr
(
x
.
CIRString
()
+
".At("
+
g
.
getValue
(
inst
.
Index
)
.
CIRString
()
+
")"
,
ctypes
.
NewPointerType
(
t
.
GetElem
()))
case
*
ctypes
.
Slice
:
return
cir
.
NewRawExpr
(
"{ "
+
x
.
CIRString
()
+
".At("
+
g
.
getValue
(
inst
.
Index
)
.
CIRString
()
+
"), "
+
x
.
CIRString
()
+
".GetBlock() }"
,
ctypes
.
NewRefType
(
t
.
GetElem
()))
case
*
ctypes
.
PointerType
:
switch
t
:=
t
.
Base
.
(
type
)
{
case
*
ctypes
.
Array
:
return
cir
.
NewRawExpr
(
x
.
CIRString
()
+
"->At("
+
g
.
getValue
(
inst
.
Index
)
.
CIRString
()
+
")"
,
ctypes
.
NewPointerType
(
t
.
GetElem
()))
case
*
ctypes
.
Slice
:
return
cir
.
NewRawExpr
(
"{ "
+
x
.
CIRString
()
+
"->At("
+
g
.
getValue
(
inst
.
Index
)
.
CIRString
()
+
"), "
+
x
.
CIRString
()
+
"->GetBlock() }"
,
ctypes
.
NewRefType
(
t
.
GetElem
()))
default
:
logger
.
Fatalf
(
"Todo: genIndexAddr(), %T %s"
,
x
.
Type
(),
inst
)
}
case
*
ctypes
.
RefType
:
switch
t
:=
t
.
Base
.
(
type
)
{
case
*
ctypes
.
Array
:
return
cir
.
NewRawExpr
(
"{ "
+
x
.
CIRString
()
+
".GetRaw()->At("
+
g
.
getValue
(
inst
.
Index
)
.
CIRString
()
+
"), "
+
x
.
CIRString
()
+
".GetBlock() }"
,
ctypes
.
NewRefType
(
t
.
GetElem
()))
case
*
ctypes
.
Slice
:
return
cir
.
NewRawExpr
(
"{ "
+
x
.
CIRString
()
+
".GetRaw()->At("
+
g
.
getValue
(
inst
.
Index
)
.
CIRString
()
+
"), "
+
x
.
CIRString
()
+
".GetRaw()->GetBlock() }"
,
ctypes
.
NewRefType
(
t
.
GetElem
()))
}
default
:
logger
.
Fatalf
(
"Todo: genIndexAddr(), %T %s"
,
x
.
Type
(),
inst
)
}
return
nil
}
func
(
g
*
functionGenerator
)
genSlice
(
inst
*
ssa
.
Slice
)
cir
.
Expr
{
x
:=
g
.
getValue
(
inst
.
X
)
switch
t
:=
x
.
Type
()
.
(
type
)
{
case
*
ctypes
.
Array
:
logger
.
Fatal
(
"Shouldn't have ctypes.Array here!"
)
case
*
ctypes
.
Slice
:
var
low
,
high
cir
.
Expr
if
inst
.
Low
!=
nil
{
low
=
g
.
getValue
(
inst
.
Low
)
}
else
{
low
=
cconstant
.
NewInt
(
ctypes
.
Int64
,
0
)
}
if
inst
.
High
!=
nil
{
high
=
g
.
getValue
(
inst
.
High
)
}
else
{
high
=
cir
.
NewRawExpr
(
x
.
CIRString
()
+
".Len()"
,
ctypes
.
Uint64
)
}
s
:=
x
.
CIRString
()
+
".Sub("
s
+=
low
.
CIRString
()
+
", "
s
+=
high
.
CIRString
()
+
")"
return
cir
.
NewRawExpr
(
s
,
ctypes
.
NewSlice
(
t
.
GetElem
()))
case
*
ctypes
.
StringVar
:
var
low
,
high
cir
.
Expr
if
inst
.
Low
!=
nil
{
low
=
g
.
getValue
(
inst
.
Low
)
}
else
{
low
=
cconstant
.
NewInt
(
ctypes
.
Int64
,
0
)
}
if
inst
.
High
!=
nil
{
high
=
g
.
getValue
(
inst
.
High
)
}
else
{
high
=
cir
.
NewRawExpr
(
x
.
CIRString
()
+
".Len()"
,
ctypes
.
Uint64
)
}
s
:=
x
.
CIRString
()
+
".Sub("
s
+=
low
.
CIRString
()
+
", "
s
+=
high
.
CIRString
()
+
")"
return
cir
.
NewRawExpr
(
s
,
&
ctypes
.
StringVar
{})
case
*
ctypes
.
StringLit
:
r
:=
g
.
compiler
.
curScope
.
AddTempVarDecl
(
g
.
genRegister
(),
&
ctypes
.
StringVar
{})
r
.
InitVal
=
x
var
low
,
high
cir
.
Expr
if
inst
.
Low
!=
nil
{
low
=
g
.
getValue
(
inst
.
Low
)
}
else
{
low
=
cconstant
.
NewInt
(
ctypes
.
Int64
,
0
)
}
if
inst
.
High
!=
nil
{
high
=
g
.
getValue
(
inst
.
High
)
}
else
{
high
=
cir
.
NewRawExpr
(
r
.
Var
.
CIRString
()
+
".Len()"
,
ctypes
.
Uint64
)
}
s
:=
r
.
Var
.
CIRString
()
+
".Sub("
s
+=
low
.
CIRString
()
+
", "
s
+=
high
.
CIRString
()
+
")"
return
cir
.
NewRawExpr
(
s
,
&
ctypes
.
StringVar
{})
case
*
ctypes
.
RefType
:
switch
t
:=
t
.
Base
.
(
type
)
{
case
*
ctypes
.
Array
:
var
low
,
high
cir
.
Expr
if
inst
.
Low
!=
nil
{
low
=
g
.
getValue
(
inst
.
Low
)
}
else
{
low
=
cconstant
.
NewInt
(
ctypes
.
Int64
,
0
)
}
if
inst
.
High
!=
nil
{
high
=
g
.
getValue
(
inst
.
High
)
}
else
{
high
=
cir
.
NewRawExpr
(
x
.
CIRString
()
+
".GetRaw()->Len()"
,
ctypes
.
Uint64
)
}
slice_len
:=
cir
.
NewSubExpr
(
high
,
low
)
slice_cap
:=
cir
.
NewSubExpr
(
cir
.
NewRawExpr
(
x
.
CIRString
()
+
".GetRaw()->Len()"
,
ctypes
.
Uint64
),
low
)
s
:=
"{ "
s
+=
x
.
CIRString
()
+
".GetRaw()->At("
s
+=
low
.
CIRString
()
+
"), "
s
+=
x
.
CIRString
()
+
".GetBlock(), "
s
+=
slice_len
.
CIRString
()
+
", "
s
+=
slice_cap
.
CIRString
()
+
" }"
return
cir
.
NewRawExpr
(
s
,
ctypes
.
NewSlice
(
t
.
GetElem
()))
case
*
ctypes
.
Slice
:
var
low
,
high
cir
.
Expr
if
inst
.
Low
!=
nil
{
low
=
g
.
getValue
(
inst
.
Low
)
}
else
{
low
=
cconstant
.
NewInt
(
ctypes
.
Int64
,
0
)
}
if
inst
.
High
!=
nil
{
high
=
g
.
getValue
(
inst
.
High
)
}
else
{
high
=
cir
.
NewRawExpr
(
x
.
CIRString
()
+
".GetRaw()->Len()"
,
ctypes
.
Uint64
)
}
s
:=
x
.
CIRString
()
+
".GetRaw()->Sub("
s
+=
low
.
CIRString
()
+
", "
s
+=
high
.
CIRString
()
+
")"
return
cir
.
NewRawExpr
(
s
,
ctypes
.
NewSlice
(
t
.
GetElem
()))
default
:
logger
.
Fatalf
(
"Todo: genSlice(), %T %s"
,
x
.
Type
(),
inst
)
}
default
:
logger
.
Fatalf
(
"Todo: genSlice(), %T %s"
,
x
.
Type
(),
inst
)
}
return
nil
}
func
(
g
*
functionGenerator
)
genBuiltin
(
call
*
ssa
.
CallCommon
)
cir
.
Expr
{
switch
call
.
Value
.
Name
()
{
case
"print"
,
"println"
:
var
args
[]
cir
.
Expr
args
=
append
(
args
,
nil
)
var
arg_type
[]
ctypes
.
Type
var
f
string
for
_
,
arg
:=
range
call
.
Args
{
if
len
(
args
)
>
1
{
f
+=
" "
}
arg
:=
g
.
getValue
(
arg
)
switch
arg
.
Type
()
.
(
type
)
{
case
*
ctypes
.
StringLit
:
arg_type
=
append
(
arg_type
,
&
ctypes
.
StringLit
{})
f
+=
"%s"
args
=
append
(
args
,
cir
.
NewRawExpr
(
arg
.
CIRString
(),
&
ctypes
.
StringLit
{}))
case
*
ctypes
.
StringVar
:
arg_type
=
append
(
arg_type
,
&
ctypes
.
StringVar
{})
f
+=
"%s"
args
=
append
(
args
,
cir
.
NewRawExpr
(
arg
.
CIRString
()
+
".GetRaw()"
,
&
ctypes
.
StringVar
{}))
case
*
ctypes
.
BoolType
:
case
*
ctypes
.
IntType
:
arg_type
=
append
(
arg_type
,
ctypes
.
Int64
)
f
+=
"%d"
args
=
append
(
args
,
arg
)
case
*
ctypes
.
FloatType
:
arg_type
=
append
(
arg_type
,
ctypes
.
Double
)
f
+=
"%lf"
args
=
append
(
args
,
arg
)
default
:
logger
.
Fatalf
(
"Todo: print(%s)"
,
arg
.
Type
()
.
CIRString
())
}
}
if
call
.
Value
.
Name
()
==
"println"
{
f
+=
"
\\
n"
}
args
[
0
]
=
cconstant
.
NewStringLit
(
f
)
fn_type
:=
ctypes
.
NewFuncType
(
ctypes
.
Void
,
arg_type
)
function
:=
cir
.
NewVar
(
"printf"
,
fn_type
)
expr
:=
cir
.
NewCallExpr
(
function
,
args
)
return
expr
case
"append"
:
var
args
[]
cir
.
Expr
var
args_type
[]
ctypes
.
Type
for
_
,
arg
:=
range
call
.
Args
{
arg
:=
g
.
getValue
(
arg
)
args
=
append
(
args
,
arg
)
args_type
=
append
(
args_type
,
arg
.
Type
())
}
fn_type
:=
ctypes
.
NewFuncType
(
cir
.
ToCType
(
call
.
Value
.
(
*
ssa
.
Builtin
)
.
Type
()
.
(
*
types
.
Signature
)
.
Results
()),
args_type
)
function
:=
cir
.
NewVar
(
"$wartc::Append"
,
fn_type
)
return
cir
.
NewCallExpr
(
function
,
args
)
}
logger
.
Fatal
(
"Todo:"
,
call
.
Value
)
return
nil
}
//func (g *functionGenerator) genPrint(v cir.Expr) cir.Expr {
// var args []cir.Expr
// var fn_type ctypes.Type
// switch v.Type().(type) {
// case *ctypes.StringType:
// args = append(args, cconstant.NewString("%s"))
// args = append(args, v)
// fn_type = ctypes.NewFuncType(ctypes.Void, []ctypes.Type{&ctypes.StringType{}, &ctypes.StringType{}})
//
// case *ctypes.BoolType:
// case *ctypes.IntType:
// args = append(args, cconstant.NewString("%d"))
// args = append(args, v)
// fn_type = ctypes.NewFuncType(ctypes.Void, []ctypes.Type{&ctypes.StringType{}, ctypes.Int64})
//
// case *ctypes.FloatType:
// args = append(args, cconstant.NewString("%lf"))
// args = append(args, v)
// fn_type = ctypes.NewFuncType(ctypes.Void, []ctypes.Type{&ctypes.StringType{}, ctypes.Double})
//
// default:
// logger.Fatalf("Todo: print(%s)", v.Type().Name())
// return nil
// }
// fn := cir.NewVar("printf", fn_type)
// expr := cir.NewCallExpr(fn, args)
// return expr
//}
func
(
g
*
functionGenerator
)
genPhi
(
inst
*
ssa
.
Phi
)
{
r
:=
&
g
.
compiler
.
curScope
.
AddTempVarDecl
(
g
.
genRegister
(),
cir
.
ToCType
(
inst
.
Type
()))
.
Var
r
.
AssociatedSSAObj
=
inst
var
edges
[]
cir
.
PhiEdge
for
i
,
v
:=
range
inst
.
Edges
{
var
e
cir
.
PhiEdge
e
.
Incoming
=
inst
.
Block
()
.
Preds
[
i
]
.
Index
e
.
Value
=
g
.
getValue
(
v
)
edges
=
append
(
edges
,
e
)
}
g
.
compiler
.
curScope
.
AddPhiStmt
(
g
.
var_cur_block
,
r
,
edges
)
}
func
(
g
*
functionGenerator
)
genRegister
()
string
{
defer
func
()
{
g
.
cur_local_id
++
}()
return
"$T_"
+
strconv
.
Itoa
(
g
.
cur_local_id
)
}
func
(
g
*
functionGenerator
)
genReturn
(
inst
*
ssa
.
Return
)
{
var
ret
[]
cir
.
Expr
for
_
,
v
:=
range
inst
.
Results
{
ret
=
append
(
ret
,
g
.
getValue
(
v
))
}
g
.
compiler
.
curScope
.
AddReturnStmt
(
ret
)
}
func
(
g
*
functionGenerator
)
genIf
(
inst
*
ssa
.
If
)
{
var
succs
[
2
]
int
succs
[
0
]
=
inst
.
Block
()
.
Succs
[
0
]
.
Index
succs
[
1
]
=
inst
.
Block
()
.
Succs
[
1
]
.
Index
g
.
compiler
.
curScope
.
AddIfStmt
(
g
.
getValue
(
inst
.
Cond
),
succs
)
}
func
(
g
*
functionGenerator
)
genStore
(
inst
*
ssa
.
Store
)
{
g
.
compiler
.
curScope
.
AddStoreStmt
(
g
.
getValue
(
inst
.
Addr
),
g
.
getValue
(
inst
.
Val
))
}
func
(
g
*
functionGenerator
)
genJump
(
inst
*
ssa
.
Jump
)
{
g
.
compiler
.
curScope
.
AddJumpStmt
(
"$Block_"
+
strconv
.
Itoa
(
inst
.
Block
()
.
Succs
[
0
]
.
Index
))
}
internal/backends/compiler_c/compile_global.go
0 → 100644
浏览文件 @
f939ef4d
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler_c
import
(
"github.com/wa-lang/wa/internal/backends/compiler_c/cir"
"github.com/wa-lang/wa/internal/backends/compiler_c/cir/ctypes"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/types"
)
func
(
p
*
CompilerC
)
compileGlobal
(
g
*
ssa
.
Global
)
{
c_type
:=
cir
.
ToCType
(
g
.
Type
()
.
(
*
types
.
Pointer
)
.
Elem
())
switch
c_type
.
(
type
)
{
case
*
ctypes
.
Array
:
p
.
curScope
.
AddLocalVarDecl
(
g
.
Name
(),
c_type
)
.
Var
.
AssociatedSSAObj
=
g
default
:
c_name
:=
"$Global_"
+
g
.
Name
()
c_var
:=
&
p
.
curScope
.
AddLocalVarDecl
(
c_name
,
c_type
)
.
Var
w_var_decl
:=
p
.
curScope
.
AddLocalVarDecl
(
g
.
Name
(),
ctypes
.
NewPointerType
(
c_type
))
w_var_decl
.
InitVal
=
cir
.
NewGetaddrExpr
(
c_var
)
w_var_decl
.
Var
.
AssociatedSSAObj
=
g
}
}
internal/backends/compiler_c/compile_type.go
0 → 100644
浏览文件 @
f939ef4d
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler_c
import
(
"github.com/wa-lang/wa/internal/backends/compiler_c/cir"
"github.com/wa-lang/wa/internal/logger"
"github.com/wa-lang/wa/internal/ssa"
"github.com/wa-lang/wa/internal/types"
)
func
(
p
*
CompilerC
)
compileType
(
t
*
ssa
.
Type
)
{
switch
typ
:=
t
.
Type
()
.
(
type
)
{
case
*
types
.
Named
:
switch
utyp
:=
typ
.
Underlying
()
.
(
type
)
{
case
*
types
.
Basic
:
var
v
[]
cir
.
Var
bt
:=
cir
.
ToCType
(
utyp
)
v
=
append
(
v
,
*
cir
.
NewVar
(
"$"
+
bt
.
CIRString
(),
bt
))
p
.
curScope
.
AddStructDecl
(
t
.
Name
(),
v
)
case
*
types
.
Struct
:
var
vs
[]
cir
.
Var
for
i
:=
0
;
i
<
utyp
.
NumFields
();
i
++
{
f
:=
utyp
.
Field
(
i
)
var
v
cir
.
Var
bt
:=
cir
.
ToCType
(
f
.
Type
())
if
f
.
Embedded
()
{
v
=
*
cir
.
NewVar
(
"$"
+
bt
.
CIRString
(),
bt
)
}
else
{
v
=
*
cir
.
NewVar
(
f
.
Name
(),
bt
)
}
vs
=
append
(
vs
,
v
)
}
p
.
curScope
.
AddStructDecl
(
t
.
Name
(),
vs
)
case
*
types
.
Interface
:
logger
.
Fatalf
(
"Todo: %T"
,
utyp
)
}
default
:
logger
.
Fatalf
(
"Todo: %T"
,
typ
)
}
}
internal/backends/compiler_c/compiler_c.go
0 → 100644
浏览文件 @
f939ef4d
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler_c
import
(
"github.com/wa-lang/wa/internal/backends/compiler_c/cir"
"github.com/wa-lang/wa/internal/ssa"
)
type
CompilerC
struct
{
ssaPkg
*
ssa
.
Package
curScope
*
cir
.
Scope
}
func
(
p
*
CompilerC
)
CompilePackage
(
ssaPkg
*
ssa
.
Package
)
{
p
.
ssaPkg
=
ssaPkg
p
.
curScope
=
cir
.
NewScope
(
nil
)
var
ts
[]
*
ssa
.
Type
var
cs
[]
*
ssa
.
NamedConst
var
gs
[]
*
ssa
.
Global
var
fns
[]
*
ssa
.
Function
for
_
,
m
:=
range
p
.
ssaPkg
.
Members
{
switch
member
:=
m
.
(
type
)
{
case
*
ssa
.
Type
:
ts
=
append
(
ts
,
member
)
case
*
ssa
.
NamedConst
:
cs
=
append
(
cs
,
member
)
case
*
ssa
.
Global
:
gs
=
append
(
gs
,
member
)
case
*
ssa
.
Function
:
fns
=
append
(
fns
,
member
)
default
:
panic
(
"Unreachable"
)
}
}
for
_
,
t
:=
range
ts
{
p
.
compileType
(
t
)
}
for
_
,
c
:=
range
cs
{
p
.
compileConst
(
c
)
}
for
_
,
g
:=
range
gs
{
p
.
compileGlobal
(
g
)
}
for
_
,
fn
:=
range
fns
{
newFunctionGenerator
(
p
)
.
genFunction
(
fn
)
}
}
func
(
p
*
CompilerC
)
String
()
string
{
return
p
.
curScope
.
CIRString
()
}
/*
func (p *CompilerC) getMangledDefName(ident *ast.Ident) (mangled string) {
obj, ok := p.pkg.Info.Defs[ident]
if !ok {
return fmt.Sprintf("ugo_%s_%s_pos%d", p.pkg.Pkg.Name(), ident.Name, ident.NamePos)
}
scope := obj.Parent()
if scope == types.Universe {
return fmt.Sprintf("ugo_%s_%s", "builtin", ident.Name)
}
if scope.Parent() == types.Universe {
return fmt.Sprintf("ugo_%s_%s", p.pkg.Pkg.Name(), ident.Name)
}
return fmt.Sprintf("ugo_%s_%s_pos%d", p.pkg.Pkg.Name(), ident.Name, obj.Pos())
}
func (p *CompilerC) getMangledUseName(ident *ast.Ident) (mangled string) {
obj, ok := p.pkg.Info.Uses[ident]
if !ok {
obj, ok = p.pkg.Info.Defs[ident]
if !ok {
return fmt.Sprintf("ugo_%s_%s_pos%d", p.pkg.Pkg.Name(), ident.Name, ident.NamePos)
}
}
scope := obj.Parent()
if scope == types.Universe {
return fmt.Sprintf("ugo_%s_%s", "builtin", ident.Name)
}
if scope.Parent() == types.Universe {
return fmt.Sprintf("ugo_%s_%s", p.pkg.Pkg.Name(), ident.Name)
}
return fmt.Sprintf("%s_pos%d", ident.Name, obj.Pos())
} //*/
func
(
p
*
CompilerC
)
EnterScope
(
name
string
)
{
s
:=
p
.
curScope
.
AddScope
()
p
.
curScope
=
s
}
func
(
p
*
CompilerC
)
LeaveScope
()
{
if
p
.
curScope
.
Parent
==
nil
{
return
}
p
.
curScope
=
p
.
curScope
.
Parent
}
internal/backends/compiler_c/compiler_util.go
0 → 100644
浏览文件 @
f939ef4d
// 版权 @2021 凹语言 作者。保留所有权利。
package
compiler_c
main.go
浏览文件 @
f939ef4d
...
...
@@ -214,6 +214,24 @@ func main() {
return
nil
},
},
{
Name
:
"cir"
,
Usage
:
"print cir code"
,
Action
:
func
(
c
*
cli
.
Context
)
error
{
if
c
.
NArg
()
==
0
{
fmt
.
Fprintf
(
os
.
Stderr
,
"no input file"
)
os
.
Exit
(
1
)
}
ctx
:=
app
.
NewApp
(
build_Options
(
c
))
err
:=
ctx
.
CIR
(
c
.
Args
()
.
First
())
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
return
nil
},
},
{
Name
:
"asm"
,
Usage
:
"parse Wa and print ouput assembly code"
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录