提交 5aebda55 编写于 作者: B Ben Shi

llvm: implement translation of type convertion.

上级 0b1312ab
......@@ -33,6 +33,11 @@ fn main {
test_pointer()
test_convert0()
test_convert1()
test_convert2()
test_convert3()
bye()
}
......@@ -175,3 +180,68 @@ fn new_int() *i32 {
fn set_int(p: *i32) {
*p = 13
}
fn convert_i32_to_i16(a: i32) i16 {
return i16(a)
}
fn convert_i32_to_u16(a: i32) u16 {
return u16(a)
}
fn convert_i16_to_i32(a: i16) i32 {
return i32(a)
}
fn convert_u16_to_i32(a: u16) i32 {
return i32(a)
}
fn test_convert0() {
println(i32(convert_i32_to_i16(65537)))
println(u32(convert_i32_to_u16(65537)))
println(convert_i16_to_i32(100))
println(convert_i16_to_i32(-100))
println(convert_u16_to_i32(100))
println(convert_u16_to_i32(65530))
}
fn convert_f64_to_f32(a: f64) f32 {
return f32(a)
}
fn test_convert1() {
println(float64(convert_f64_to_f32(3.1415926535)))
}
fn convert_i16_to_f64(a: i16) f64 {
return f64(a)
}
fn convert_u16_to_f64(a: u16) f64 {
return f64(a)
}
fn test_convert2() {
println(convert_i16_to_f64(100))
println(convert_i16_to_f64(-100))
println(convert_u16_to_f64(100))
println(convert_u16_to_f64(65530))
}
fn convert_f64_to_i32(a: f64) i32 {
return i32(a)
}
fn convert_f64_to_u32(a: f64) u32 {
return u32(a)
}
fn test_convert3() {
println(convert_f64_to_i32(100.001))
println(convert_f64_to_u32(100.001))
println(convert_f64_to_i32(99.99))
println(convert_f64_to_u32(99.99))
println(convert_f64_to_i32(-100.001))
println(convert_f64_to_u32(-100.001))
}
......@@ -96,6 +96,11 @@ func (p *Compiler) compileValue(val ssa.Value) error {
p.output.WriteString(strconv.Itoa(val.Field))
p.output.WriteString("\n")
case *ssa.Convert:
if err := p.compileConvert(val); err != nil {
return err
}
default:
p.output.WriteString(" ; " + val.Name() + " = " + val.String() + "\n")
// panic("unsupported Value '" + val.Name() + " = " + val.String() + "'")
......@@ -104,6 +109,76 @@ func (p *Compiler) compileValue(val ssa.Value) error {
return nil
}
func (p *Compiler) compileConvert(val *ssa.Convert) error {
frIsFloat, frIsSigned := checkType(val.X.Type())
toIsFloat, toIsSigned := checkType(val.Type())
frSize := getTypeSize(val.X.Type(), p.target)
toSize := getTypeSize(val.Type(), p.target)
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val))
p.output.WriteString(" = ")
switch {
case !frIsFloat && !toIsFloat: // integral type -> integral type
switch {
case frSize == toSize:
p.output.WriteString("add ")
p.output.WriteString(getTypeStr(val.Type(), p.target))
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val.X))
p.output.WriteString(", 0\n")
return nil
case frSize > toSize:
p.output.WriteString("trunc ")
case frSize < toSize:
if !toIsSigned || !frIsSigned {
p.output.WriteString("zext ")
} else {
p.output.WriteString("sext ")
}
default:
panic("unkown type convert: " + val.String())
}
case frIsFloat && toIsFloat: // float point type -> float point type
switch {
case frSize > toSize:
p.output.WriteString("fptrunc ")
case frSize < toSize:
p.output.WriteString("fpext ")
default:
panic("unkown type convert: " + val.String())
}
case !frIsFloat && toIsFloat: // integeral type -> float point type
if frIsSigned {
p.output.WriteString("sitofp ")
} else {
p.output.WriteString("uitofp ")
}
case frIsFloat && !toIsFloat: //float point type -> integral type
if toIsSigned {
p.output.WriteString("fptosi ")
} else {
p.output.WriteString("fptoui ")
}
default:
panic("unkown type convert: " + val.String())
}
p.output.WriteString(getTypeStr(val.X.Type(), p.target))
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val.X))
p.output.WriteString(" to ")
p.output.WriteString(getTypeStr(val.Type(), p.target))
p.output.WriteString("\n")
return nil
}
func (p *Compiler) compileUnOp(val *ssa.UnOp) error {
p.output.WriteString(" ")
p.output.WriteString(getValueStr(val))
......
......@@ -183,7 +183,58 @@ func getTypeStr(ty types.Type, target string) string {
return getTypeStr(t.Underlying(), target)
default:
// TODO: support pointer, array and struct types
panic("unknown type")
}
}
func getTypeSize(ty types.Type, target string) int {
// feasible types on different targets
defInt := map[string]int{
"avr": 2,
"thumb": 2,
"arm": 4,
"aarch64": 8,
"riscv32": 4,
"riscv64": 8,
"x86": 4,
"x86_64": 8,
}
// fixed types
expTy := map[types.BasicKind]int{
types.Bool: 1,
types.UntypedBool: 1,
types.Int8: 1,
types.Uint8: 1,
types.Int16: 2,
types.Uint16: 2,
types.Int32: 4,
types.Uint32: 4,
types.Int64: 8,
types.Uint64: 8,
types.Float32: 4,
types.Float64: 8,
types.UntypedFloat: 4,
}
switch t := ty.(type) {
case *types.Basic:
// return size of a fixed type
if sz, ok := expTy[t.Kind()]; ok {
return sz
}
// return size of a feasible type
switch t.Kind() {
case types.Int, types.Uint, types.UntypedInt:
if sz, ok := defInt[getArch(target)]; ok {
return sz
}
return 8
// should never reach here
default:
panic("unknown basic type")
}
default:
panic("unknown type")
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册