package generator import "fmt" import "git.tebibyte.media/fspl/fspl/llvm" import "git.tebibyte.media/fspl/fspl/entity" import "git.tebibyte.media/fspl/fspl/analyzer" func (this *generator) generateVariableLoc (variable *entity.Variable) (llvm.Value, error) { return this.blockManager.variable(variable.Declaration) } func (this *generator) generateDeclarationLoc (declaration *entity.Declaration) (llvm.Value, error) { return this.blockManager.addDeclaration(declaration, nil) } func (this *generator) generateSliceLoc (slice *entity.Slice) (llvm.Value, error) { var start, end, dataAddress llvm.Value var elementType llvm.Type sizeType, err := this.generateTypeIndex() if err != nil { return nil, err } if slice.Start != nil { start, err = this.generateExpressionVal(slice.Start) if err != nil { return nil, err } } if slice.End != nil { end, err = this.generateExpressionVal(slice.End) if err != nil { return nil, err } } sourceType := analyzer.ReduceToBase(slice.Slice.Type()) switch sourceType := sourceType.(type) { case *entity.TypeSlice: source, err := this.generateExpressionLoc(slice.Slice) if err != nil { return nil, err } irSourceType, err := this.generateType(sourceType) if err != nil { return nil, err } elementType, err = this.generateType(sourceType.Element) if err != nil { return nil, err } dataAddressFieldAddress := this.blockManager.NewGetElementPtr ( irSourceType, source, llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, 0)) dataAddress = this.blockManager.NewLoad ( new(llvm.TypePointer), dataAddressFieldAddress) lengthAddress := this.blockManager.NewGetElementPtr ( irSourceType, source, llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, 1)) if end == nil { end = this.blockManager.NewLoad(sizeType, lengthAddress) } case *entity.TypeArray: elementType, err = this.generateType(sourceType.Element) if err != nil { return nil, err } dataAddress, err = this.generateExpressionLoc(slice.Slice) if err != nil { return nil, err } if end == nil { end = llvm.NewConstInt(sizeType, int64(sourceType.Length)) } default: panic(fmt.Sprint ( "BUG: generator can't slice expression ", slice.Slice)) } // figure out starting position and length var length llvm.Value if start == nil { length = end } else { length = this.blockManager.NewSub(end, start) dataAddress = this.blockManager.NewGetElementPtr ( elementType, dataAddress, start) } // create new slice descriptor return this.generateSlice(slice.Type(), dataAddress, length) } func (this *generator) generateSubscriptLoc (subscript *entity.Subscript) (llvm.Value, error) { source, err := this.generateExpressionLoc(subscript.Slice) if err != nil { return nil, err } offset, err := this.generateExpressionVal(subscript.Offset) if err != nil { return nil, err } var elementType entity.Type var dataAddress llvm.Value sourceType := analyzer.ReduceToBase(subscript.Slice.Type()) switch sourceType := sourceType.(type) { case *entity.TypeSlice: irSourceType, err := this.generateType(subscript.Slice.Type()) if err != nil { return nil, err } elementType = sourceType.Element dataAddress = this.getSliceDataAddress(source, irSourceType) case *entity.TypeArray: elementType = sourceType.Element dataAddress = source default: panic(fmt.Sprint ( "BUG: generator can't subscript expression ", subscript.Slice)) } // get element irElementType, err := this.generateType(elementType) if err != nil { return nil, err } return this.blockManager.NewGetElementPtr ( irElementType, dataAddress, offset), nil } func (this *generator) generateDereferenceLoc (dereference *entity.Dereference) (llvm.Value, error) { return this.generateExpressionVal(dereference.Pointer) } func (this *generator) generateMemberAccessLoc (access *entity.MemberAccess) (llvm.Value, error) { source, err := this.generateExpressionLoc(access.Source) if err != nil { return nil, err } switch sourceType := analyzer.ReduceToBase(access.Source.Type()).(type) { case *entity.TypeStruct: irSourceType, err := this.generateType(access.Source.Type()) if err != nil { return nil, err } offset := this.getStructMemberIndex(sourceType, access.Member) return this.blockManager.NewGetElementPtr ( irSourceType, source, llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, int64(offset))), nil case *entity.TypePointer: irSourceType, err := this.generateType(sourceType.Referenced) if err != nil { return nil, err } referencedSourceType := analyzer.ReduceToBase(sourceType.Referenced).(*entity.TypeStruct) offset := this.getStructMemberIndex(referencedSourceType, access.Member) source = this.blockManager.NewLoad(new(llvm.TypePointer), source) return this.blockManager.NewGetElementPtr ( irSourceType, source, llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, int64(offset))), nil default: panic(fmt.Sprint ( "BUG: generator can't access members in expression ", access.Source)) } }