Untested for loop generation
This commit is contained in:
parent
789ffa85d2
commit
e4c6089b62
@ -97,6 +97,8 @@ func (this *generator) generateExpressionAny (expression entity.Expression) (reg
|
|||||||
return this.generateMatch(expression, resultModeAny)
|
return this.generateMatch(expression, resultModeAny)
|
||||||
case *entity.Loop:
|
case *entity.Loop:
|
||||||
return this.generateLoop(expression, resultModeAny)
|
return this.generateLoop(expression, resultModeAny)
|
||||||
|
case *entity.For:
|
||||||
|
return this.generateFor(expression, resultModeAny)
|
||||||
|
|
||||||
// we get nothing from these
|
// we get nothing from these
|
||||||
case *entity.Assignment:
|
case *entity.Assignment:
|
||||||
@ -236,6 +238,9 @@ func (this *generator) generateExpressionLoc (expression entity.Expression) (llv
|
|||||||
case *entity.Loop:
|
case *entity.Loop:
|
||||||
loc, _, err := this.generateLoop(expression, resultModeLoc)
|
loc, _, err := this.generateLoop(expression, resultModeLoc)
|
||||||
return loc, err
|
return loc, err
|
||||||
|
case *entity.For:
|
||||||
|
loc, _, err := this.generateFor(expression, resultModeLoc)
|
||||||
|
return loc, err
|
||||||
case *entity.LiteralArray:
|
case *entity.LiteralArray:
|
||||||
return this.generateLiteralArrayLoc(expression, nil)
|
return this.generateLiteralArrayLoc(expression, nil)
|
||||||
case *entity.LiteralString:
|
case *entity.LiteralString:
|
||||||
|
@ -3,7 +3,7 @@ package generator
|
|||||||
// import "fmt"
|
// import "fmt"
|
||||||
import "git.tebibyte.media/fspl/fspl/llvm"
|
import "git.tebibyte.media/fspl/fspl/llvm"
|
||||||
import "git.tebibyte.media/fspl/fspl/entity"
|
import "git.tebibyte.media/fspl/fspl/entity"
|
||||||
// import "git.tebibyte.media/fspl/fspl/analyzer"
|
import "git.tebibyte.media/fspl/fspl/analyzer"
|
||||||
|
|
||||||
func (this *generator) generateBlock (block *entity.Block, mode resultMode) (llvm.Value, bool, error) {
|
func (this *generator) generateBlock (block *entity.Block, mode resultMode) (llvm.Value, bool, error) {
|
||||||
if len(block.Steps) == 0 { return nil, false, nil }
|
if len(block.Steps) == 0 { return nil, false, nil }
|
||||||
@ -196,26 +196,103 @@ func (this *generator) generateLoop (loop *entity.Loop, mode resultMode) (llvm.V
|
|||||||
Target: exit,
|
Target: exit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// FIXME: loopEntry needs to have a list of phi nodes, it's probably
|
||||||
|
// completely broken
|
||||||
return loopEntry.value, loopEntry.loc, nil
|
return loopEntry.value, loopEntry.loc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *generator) generateFor (loop *entity.For, mode resultMode) (llvm.Value, bool, error) {
|
func (this *generator) generateFor (loop *entity.For, mode resultMode) (llvm.Value, bool, error) {
|
||||||
irIndexType, err := this.blockManager.generateTypeIndex()
|
irIndexType, err := this.generateTypeIndex()
|
||||||
if err != nil { return nil, false, err }
|
if err != nil { return nil, false, err }
|
||||||
|
|
||||||
// element index
|
// element index
|
||||||
var irIndex llvm.Value
|
var irIndexLoc llvm.Value
|
||||||
if loop.Index != nil {
|
if loop.Index != nil {
|
||||||
irIndex, err = this.blockManager.addDeclaration (
|
irIndexLoc, err = this.blockManager.addDeclaration (
|
||||||
loop.Index, llvm.NewConstZeroInitializer(irIndexType))
|
loop.Index, llvm.NewConstZeroInitializer(irIndexType))
|
||||||
if err != nil { return nil, false, err }
|
if err != nil { return nil, false, err }
|
||||||
|
} else {
|
||||||
|
irIndexLoc = this.blockManager.newAllocaFront(irIndexType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// element value
|
// element value
|
||||||
irElement, err := this.blockManager.addDeclaration(loop.Element, nil)
|
irElementLoc, err := this.blockManager.addDeclaration(loop.Element, nil)
|
||||||
|
if err != nil { return nil, false, err }
|
||||||
|
irElementType, err := this.generateType(loop.Element.Type())
|
||||||
|
if err != nil { return nil, false, err }
|
||||||
|
|
||||||
|
// source slice/array
|
||||||
|
irOverLoc, err := this.generateExpressionLoc(loop.Over)
|
||||||
|
if err != nil { return nil, false, err }
|
||||||
|
irOverType, err := this.generateType(loop.Over.Type())
|
||||||
|
if err != nil { return nil, false, err }
|
||||||
|
baseOverType := analyzer.ReduceToBase(loop.Over.Type())
|
||||||
|
array, isArray := baseOverType.(*entity.TypeArray)
|
||||||
|
|
||||||
|
previous := this.blockManager.Block
|
||||||
|
header := this.blockManager.newBlock()
|
||||||
|
body := this.blockManager.newBlock()
|
||||||
|
exit := this.blockManager.newBlock()
|
||||||
|
previous.NewBr(header)
|
||||||
|
this.blockManager.Block = header
|
||||||
|
|
||||||
|
loopEntry := this.blockManager.pushLoop(mode)
|
||||||
|
defer this.blockManager.popLoop()
|
||||||
|
|
||||||
|
// check bounds
|
||||||
|
var irLength llvm.Value
|
||||||
|
if isArray {
|
||||||
|
irLength = llvm.NewConstInt(irIndexType, int64(array.Length))
|
||||||
|
} else {
|
||||||
|
irLength = this.blockManager.NewLoad (
|
||||||
|
irIndexType,
|
||||||
|
this.getSliceLengthFieldLoc(irOverLoc, irOverType))
|
||||||
|
}
|
||||||
|
this.blockManager.NewCondBr (
|
||||||
|
this.blockManager.NewICmp (
|
||||||
|
llvm.IPredicateULT,
|
||||||
|
this.blockManager.NewLoad(irIndexType, irIndexLoc),
|
||||||
|
irLength),
|
||||||
|
body, exit)
|
||||||
|
|
||||||
|
this.blockManager.Block = body
|
||||||
|
|
||||||
|
// set element
|
||||||
|
var irDataLoc llvm.Value
|
||||||
|
if isArray {
|
||||||
|
irDataLoc = irOverLoc
|
||||||
|
} else {
|
||||||
|
irDataLoc = this.blockManager.NewLoad (
|
||||||
|
llvm.Pointer,
|
||||||
|
this.getSliceDataFieldLoc(irOverLoc, irOverType))
|
||||||
|
}
|
||||||
|
this.blockManager.NewStore (
|
||||||
|
this.blockManager.NewGetElementPtr (
|
||||||
|
irElementType, irDataLoc,
|
||||||
|
llvm.NewConstInt(llvm.I32, 0),
|
||||||
|
this.blockManager.NewLoad(irIndexType, irIndexLoc)),
|
||||||
|
irElementLoc)
|
||||||
|
|
||||||
|
_, _, err = this.generateExpressionAny(loop.Body)
|
||||||
if err != nil { return nil, false, err }
|
if err != nil { return nil, false, err }
|
||||||
|
|
||||||
// TODO
|
this.blockManager.NewBr(body)
|
||||||
|
if !this.blockManager.Terminated() {
|
||||||
previous := this.
|
// increment index
|
||||||
|
this.blockManager.NewStore (
|
||||||
|
this.blockManager.NewAdd (
|
||||||
|
this.blockManager.NewLoad(irIndexType, irIndexLoc),
|
||||||
|
llvm.NewConstInt(irIndexType, 1)),
|
||||||
|
irIndexLoc)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blockManager.Block = exit
|
||||||
|
if loopEntry.stub != nil {
|
||||||
|
loopEntry.stub.SetTerminator(&llvm.TerminatorBr {
|
||||||
|
Target: exit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// FIXME: loopEntry needs to have a list of phi nodes, it's probably
|
||||||
|
// completely broken
|
||||||
|
return loopEntry.value, loopEntry.loc, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user