Untested for loop generation

This commit is contained in:
Sasha Koshka 2024-03-20 02:52:01 -04:00
parent 789ffa85d2
commit e4c6089b62
2 changed files with 90 additions and 8 deletions

View File

@ -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:

View File

@ -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
}