package generator import "fmt" import "errors" import "strings" import "git.tebibyte.media/sashakoshka/fspl/llvm" import "git.tebibyte.media/sashakoshka/fspl/entity" func (this *generator) generateTypeNamed (ty *entity.TypeNamed) (llvm.Type, error) { return this.typedef(ty.Name) } func (this *generator) generateTypePointer (ty *entity.TypePointer) (llvm.Type, error) { return llvm.Pointer, nil } func (this *generator) generateTypeSlice (ty *entity.TypeSlice) (llvm.Type, error) { indexType, err := this.typedef("Index") 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) generateTypeInerface (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 } }