163 lines
4.5 KiB
Go
163 lines
4.5 KiB
Go
package generator
|
|
|
|
import "fmt"
|
|
import "errors"
|
|
import "github.com/llir/llvm/ir/value"
|
|
import "github.com/llir/llvm/ir/types"
|
|
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
|
|
|
// type pointer struct { TypeName string }
|
|
// func (this *pointer) Name () string { return this.TypeName }
|
|
// func (this *pointer) SetName (name string) { this.TypeName = name }
|
|
// func (*pointer) LLString () string { return "ptr" }
|
|
// func (this *pointer) String () string {
|
|
// if this.TypeName == "" {
|
|
// return this.LLString()
|
|
// } else {
|
|
// return "%" + this.TypeName
|
|
// }
|
|
// }
|
|
// func (*pointer) Equal (ty types.Type) bool {
|
|
// _, isGenericPointer := ty.(*pointer)
|
|
// _, isTypedPointer := ty.(*types.PointerType)
|
|
// return isGenericPointer || isTypedPointer
|
|
// }
|
|
func newPointer () types.Type {
|
|
return types.NewPointer(types.NewInt(8))
|
|
}
|
|
|
|
func (this *generator) generateTypeNamed (ty *entity.TypeNamed) (types.Type, error) {
|
|
return this.typedef(ty.Name)
|
|
}
|
|
|
|
func (this *generator) generateTypePointer (ty *entity.TypePointer) (types.Type, error) {
|
|
return newPointer(), nil
|
|
}
|
|
|
|
func (this *generator) generateTypeSlice (ty *entity.TypeSlice) (types.Type, error) {
|
|
return types.NewStruct (
|
|
/* data */ newPointer(),
|
|
/* len */ types.NewInt(this.target.WordSize)), nil
|
|
}
|
|
|
|
func (this *generator) generateTypeArray (ty *entity.TypeArray) (types.Type, error) {
|
|
element, err := this.generateType(ty.Element)
|
|
if err != nil { return nil, err }
|
|
return types.NewArray(uint64(ty.Length), element), nil
|
|
}
|
|
|
|
func (this *generator) generateTypeStruct (ty *entity.TypeStruct) (types.Type, error) {
|
|
irStruct := &types.StructType {
|
|
Fields: make([]types.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) generateTypeInerface (ty *entity.TypeInterface) (types.Type, error) {
|
|
irStruct := &types.StructType {
|
|
Fields: make([]types.Type, len(ty.Behaviors) + 1),
|
|
}
|
|
// object pointer
|
|
irStruct.Fields[0] = newPointer()
|
|
// behaviors
|
|
for index, behavior := range ty.Behaviors {
|
|
field, err := this.generateTypeFunction(behavior)
|
|
if err != nil { return nil, err }
|
|
irStruct.Fields[index + 1] = field
|
|
}
|
|
return irStruct, nil
|
|
}
|
|
|
|
func (this *generator) generateTypeInt (ty *entity.TypeInt) (types.Type, error) {
|
|
return types.NewInt(uint64(ty.Width)), nil
|
|
}
|
|
|
|
func (this *generator) generateTypeFloat (ty *entity.TypeFloat) (types.Type, error) {
|
|
var kind types.FloatKind; switch ty.Width {
|
|
case 16: kind = types.FloatKindHalf
|
|
case 32: kind = types.FloatKindFloat
|
|
case 64: kind = types.FloatKindDouble
|
|
case 80:
|
|
if this.target.Arch == "x86" {
|
|
kind = types.FloatKindX86_FP80
|
|
} else {
|
|
return nil, errors.New(fmt.Sprintln (
|
|
ty, "not available on",
|
|
this.target.Arch))
|
|
}
|
|
case 128:
|
|
if this.target.Arch == "PowerPC" {
|
|
kind = types.FloatKindPPC_FP128
|
|
} else {
|
|
kind = types.FloatKindFP128
|
|
}
|
|
default:
|
|
return nil, errors.New(fmt.Sprintln (ty, "has invalid width"))
|
|
}
|
|
return &types.FloatType { Kind: kind }, nil
|
|
}
|
|
|
|
func (this *generator) generateTypeWord (ty *entity.TypeWord) (types.Type, error) {
|
|
return types.NewInt(this.target.WordSize), nil
|
|
}
|
|
|
|
func (this *generator) generateTypeFunction (
|
|
signature *entity.Signature,
|
|
) (
|
|
types.Type,
|
|
error,
|
|
) {
|
|
irFunc := &types.FuncType {
|
|
Params: make([]types.Type, len(signature.Arguments)),
|
|
}
|
|
ret, err := this.generateType(signature.Return)
|
|
if err != nil { return nil, err }
|
|
irFunc.RetType = ret
|
|
for index, argument := range signature.Arguments {
|
|
param, err := this.generateType(argument.Type())
|
|
if err != nil { return nil, err }
|
|
irFunc.Params[index] = param
|
|
}
|
|
return types.NewPointer(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
|
|
}
|
|
}
|
|
|
|
type genericPointerWrapper struct {
|
|
underlying value.Value
|
|
ty types.Type
|
|
}
|
|
func genericize (val value.Value) value.Value {
|
|
ty := val.Type()
|
|
if _, ok := ty.(*types.PointerType); ok {
|
|
return &genericPointerWrapper {
|
|
underlying: val,
|
|
ty: newPointer(),
|
|
}
|
|
}
|
|
return val
|
|
}
|
|
func (wrapper *genericPointerWrapper) String () string {
|
|
return wrapper.underlying.String()
|
|
}
|
|
func (wrapper *genericPointerWrapper) Type () types.Type {
|
|
return wrapper.ty
|
|
}
|
|
func (wrapper *genericPointerWrapper) Ident () string {
|
|
return wrapper.underlying.Ident()
|
|
}
|