fspl/generator/type.go

138 lines
3.7 KiB
Go

package generator
import "fmt"
import "errors"
import "strings"
import "git.tebibyte.media/fspl/fspl/llvm"
import "git.tebibyte.media/fspl/fspl/entity"
func (this *generator) generateTypeIndex () (*llvm.TypeInt, error) {
ty, err := this.typedef(entity.Key {
Name: "Index",
})
if err != nil { return nil, err }
return ty.(*llvm.TypeInt), nil
}
func (this *generator) generateTypeNamed (ty *entity.TypeNamed) (llvm.Type, error) {
underlying, err := this.typedef(entity.Key {
Unit: ty.Type.Unit(),
Name: ty.Name,
})
if err != nil { return nil, err }
return &llvm.TypeDefined { Source: underlying }, nil
}
func (this *generator) generateTypePointer (ty *entity.TypePointer) (llvm.Type, error) {
return new(llvm.TypePointer), nil
}
func (this *generator) generateTypeSlice (ty *entity.TypeSlice) (llvm.Type, error) {
indexType, err := this.generateTypeIndex()
if err != nil { return nil, err }
return &llvm.TypeStruct {
Fields: []llvm.Type {
/* data */ llvm.Pointer,
/* len */ indexType,
},
}, nil
}
func (this *generator) generateTypeArray (ty *entity.TypeArray) (llvm.Type, error) {
element, err := this.generateType(ty.Element)
if err != nil { return nil, err }
return &llvm.TypeArray {
Length: uint64(ty.Length),
Element: element,
}, nil
}
func (this *generator) generateTypeStruct (ty *entity.TypeStruct) (llvm.Type, error) {
irStruct := &llvm.TypeStruct {
Fields: make([]llvm.Type, len(ty.Members)),
}
for index, member := range ty.Members {
field, err := this.generateType(member.Type())
if err != nil { return nil, err }
irStruct.Fields[index] = field
}
return irStruct, nil
}
func (this *generator) generateTypeInterface (ty *entity.TypeInterface) (llvm.Type, error) {
irStruct := &llvm.TypeStruct {
Fields: make([]llvm.Type, len(ty.Behaviors) + 1),
}
// object pointer
irStruct.Fields[0] = llvm.Pointer
// behaviors
for index := range ty.Behaviors {
irStruct.Fields[index + 1] = llvm.Pointer
}
return irStruct, nil
}
func (this *generator) generateTypeInt (ty *entity.TypeInt) (llvm.Type, error) {
return &llvm.TypeInt { BitSize: uint64(ty.Width) }, nil
}
func (this *generator) generateTypeFloat (ty *entity.TypeFloat) (llvm.Type, error) {
var kind llvm.FloatKind; switch ty.Width {
case 16: kind = llvm.FloatKindHalf
case 32: kind = llvm.FloatKindFloat
case 64: kind = llvm.FloatKindDouble
case 80:
if strings.HasPrefix(this.target.Arch, "x86") {
kind = llvm.FloatKindX86_FP80
} else {
return nil, errors.New(fmt.Sprintln (
ty, "not available on",
this.target.Arch))
}
case 128:
if strings.HasPrefix(this.target.Arch, "ppc") {
kind = llvm.FloatKindPPC_FP128
} else {
kind = llvm.FloatKindFP128
}
default:
return nil, errors.New(fmt.Sprintln (ty, "has invalid width"))
}
return &llvm.TypeFloat { Kind: kind }, nil
}
func (this *generator) generateTypeWord (ty *entity.TypeWord) (llvm.Type, error) {
return &llvm.TypeInt { BitSize: this.target.WordSize }, nil
}
func (this *generator) generateTypeFunction (
signature *entity.Signature,
) (
llvm.Type,
error,
) {
irFunc := &llvm.TypeFunction {
Parameters: make([]llvm.Type, len(signature.Arguments)),
}
ret, err := this.generateType(signature.Return)
if err != nil { return nil, err }
irFunc.Return = ret
for index, argument := range signature.Arguments {
param, err := this.generateType(argument.Type())
if err != nil { return nil, err }
irFunc.Parameters[index] = param
}
return irFunc, nil
}
func getInterface (ty entity.Type) *entity.TypeInterface {
switch ty.(type) {
case *entity.TypeNamed:
return getInterface(ty.(*entity.TypeNamed).Type)
case *entity.TypeInterface:
return ty.(*entity.TypeInterface)
default:
return nil
}
}