Generator understands assigning return/break to things

This commit is contained in:
Sasha Koshka 2024-03-06 16:43:58 -05:00
parent ebc4aacf5b
commit e889a9c49b
1 changed files with 37 additions and 20 deletions

View File

@ -49,6 +49,7 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, mode resultMode) (
var trueBlock, falseBlock *llvm.Block
var tru, fals llvm.Value
var loc bool
var irIncomings []*llvm.Incoming
trueBlock = this.blockManager.newBlock()
exitBlock := this.blockManager.newBlock()
@ -56,7 +57,15 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, mode resultMode) (
tru, loc, err = this.generateExpression(ifelse.True, mode)
if err != nil { return nil, false, err }
if !this.blockManager.Terminated() { this.blockManager.NewBr(exitBlock) }
if !this.blockManager.Terminated() {
if tru != nil {
irIncomings = append(irIncomings, &llvm.Incoming {
X: tru,
Predecessor: this.blockManager.Block,
})
}
this.blockManager.NewBr(exitBlock)
}
if ifelse.False == nil {
// there is no false case
@ -66,9 +75,22 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, mode resultMode) (
} else {
// there is a false case
falseBlock = this.blockManager.newBlock()
fals, _, err = this.generateExpression(ifelse.False, mode)
thisMode := mode
if mode != resultModeAny {
if loc { thisMode = resultModeLoc
} else { thisMode = resultModeVal }
}
fals, _, err = this.generateExpression(ifelse.False, thisMode)
if err != nil { return nil, false, err }
if !this.blockManager.Terminated() { this.blockManager.NewBr(exitBlock) }
if !this.blockManager.Terminated() {
if fals != nil {
irIncomings = append(irIncomings, &llvm.Incoming {
X: fals,
Predecessor: this.blockManager.Block,
})
}
this.blockManager.NewBr(exitBlock)
}
if mode == resultModeAny {
// discard results of statements
@ -78,18 +100,9 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, mode resultMode) (
} else {
// obtain results of statements
// set up phi to capture results
trueIncoming := &llvm.Incoming {
X: tru,
Predecessor: trueBlock,
}
falseIncoming := &llvm.Incoming {
X: fals,
Predecessor: falseBlock,
}
previous.NewCondBr(condition, trueBlock, falseBlock)
this.blockManager.Block = exitBlock
return this.blockManager.NewPhi(trueIncoming, falseIncoming), loc, nil
return this.blockManager.NewPhi(irIncomings...), loc, nil
}
}
}
@ -105,8 +118,8 @@ func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llv
exitBlock := this.blockManager.newBlock()
irHashType := llvm.I64
irCases := make([]*llvm.Case, len(match.Cases))
irIncomings := make([]*llvm.Incoming, len(match.Cases))
irCases := make([]*llvm.Case, len(match.Cases))
irIncomings := []*llvm.Incoming { }
for index, cas := range match.Cases {
// set up ir case
caseBlock := this.blockManager.newBlock()
@ -124,7 +137,7 @@ func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llv
this.blockManager.addDeclaration(cas.Declaration, data)
// generate case expression
thisMode := mode // FIXME this logic isnt in if/else, why??
thisMode := mode
if index != 0 && mode != resultModeAny {
if loc { thisMode = resultModeLoc
} else { thisMode = resultModeVal }
@ -132,11 +145,15 @@ func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llv
caseExpression, thisLoc, err := this.generateExpression(cas.Expression, thisMode)
if err != nil { return nil, false, err }
if index == 0 { loc = thisLoc }
irIncomings[index] = &llvm.Incoming {
X: caseExpression,
Predecessor: caseBlock,
if !this.blockManager.Terminated() {
if caseExpression != nil {
irIncomings = append(irIncomings, &llvm.Incoming {
X: caseExpression,
Predecessor: this.blockManager.Block,
})
}
this.blockManager.NewBr(exitBlock)
}
if !this.blockManager.Terminated() { this.blockManager.NewBr(exitBlock) }
}
// create switch branch