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)
|
||||
case *entity.Loop:
|
||||
return this.generateLoop(expression, resultModeAny)
|
||||
case *entity.For:
|
||||
return this.generateFor(expression, resultModeAny)
|
||||
|
||||
// we get nothing from these
|
||||
case *entity.Assignment:
|
||||
@ -236,6 +238,9 @@ func (this *generator) generateExpressionLoc (expression entity.Expression) (llv
|
||||
case *entity.Loop:
|
||||
loc, _, err := this.generateLoop(expression, resultModeLoc)
|
||||
return loc, err
|
||||
case *entity.For:
|
||||
loc, _, err := this.generateFor(expression, resultModeLoc)
|
||||
return loc, err
|
||||
case *entity.LiteralArray:
|
||||
return this.generateLiteralArrayLoc(expression, nil)
|
||||
case *entity.LiteralString:
|
||||
|
@ -3,7 +3,7 @@ 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"
|
||||
import "git.tebibyte.media/fspl/fspl/analyzer"
|
||||
|
||||
func (this *generator) generateBlock (block *entity.Block, mode resultMode) (llvm.Value, bool, error) {
|
||||
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,
|
||||
})
|
||||
}
|
||||
// FIXME: loopEntry needs to have a list of phi nodes, it's probably
|
||||
// completely broken
|
||||
return loopEntry.value, loopEntry.loc, nil
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
// element index
|
||||
var irIndex llvm.Value
|
||||
var irIndexLoc llvm.Value
|
||||
if loop.Index != nil {
|
||||
irIndex, err = this.blockManager.addDeclaration (
|
||||
irIndexLoc, err = this.blockManager.addDeclaration (
|
||||
loop.Index, llvm.NewConstZeroInitializer(irIndexType))
|
||||
if err != nil { return nil, false, err }
|
||||
} else {
|
||||
irIndexLoc = this.blockManager.newAllocaFront(irIndexType)
|
||||
}
|
||||
|
||||
// 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 }
|
||||
|
||||
// TODO
|
||||
|
||||
previous := this.
|
||||
this.blockManager.NewBr(body)
|
||||
if !this.blockManager.Terminated() {
|
||||
// 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