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

Merge branch 'backend_c'

......@@ -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)
......
//
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() {}
//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
}
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
}
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() {}
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
}
*/
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() {}
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
}
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() {}
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
}
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
}
// 版权 @2021 凹语言 作者。保留所有权利。
package compiler_c
import (
"fmt"
"github.com/wa-lang/wa/internal/ssa"
)
func (p *CompilerC) compileConst(c *ssa.NamedConst) {
fmt.Println("Todo")
}
// 版权 @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))
}
// 版权 @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
}
}
// 版权 @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)
}
}
// 版权 @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
}
// 版权 @2021 凹语言 作者。保留所有权利。
package compiler_c
......@@ -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.
先完成此消息的编辑!
想要评论请 注册