Generate match statements
This commit is contained in:
parent
54f69ca786
commit
daea6cb22a
|
@ -117,6 +117,7 @@ func (this *generator) getStructMemberIndex (ty *entity.TypeStruct, name string)
|
|||
}
|
||||
|
||||
func (this *generator) getUnionTypeFieldLoc (union llvm.Value, irType llvm.Type) llvm.Value {
|
||||
irType = llvm.ReduceToBase(irType)
|
||||
return this.blockManager.NewGetElementPtr (
|
||||
irType, union,
|
||||
llvm.NewConstInt(llvm.I32, 0),
|
||||
|
@ -124,6 +125,7 @@ func (this *generator) getUnionTypeFieldLoc (union llvm.Value, irType llvm.Type)
|
|||
}
|
||||
|
||||
func (this *generator) getUnionDataFieldLoc (union llvm.Value, irType llvm.Type) llvm.Value {
|
||||
irType = llvm.ReduceToBase(irType)
|
||||
return this.blockManager.NewGetElementPtr (
|
||||
irType, union,
|
||||
llvm.NewConstInt(llvm.I32, 0),
|
||||
|
|
|
@ -94,8 +94,64 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, mode resultMode) (
|
|||
}
|
||||
}
|
||||
|
||||
func (this *generator) generateMatch (match *entity.Match, mode resultMode) llvm.Value, bool, error) {
|
||||
// TODO
|
||||
func (this *generator) generateMatch (match *entity.Match, mode resultMode) (llvm.Value, bool, error) {
|
||||
var loc bool
|
||||
value, err := this.generateExpressionLoc(match.Value)
|
||||
if err != nil { return nil, false, err }
|
||||
irUnionType, err := this.generateType(match.Value.Type())
|
||||
if err != nil { return nil, false, err }
|
||||
|
||||
previousBlock := this.blockManager.Block
|
||||
exitBlock := this.blockManager.newBlock()
|
||||
irHashType := llvm.I64
|
||||
|
||||
irCases := make([]*llvm.Case, len(match.Cases))
|
||||
irIncomings := make([]*llvm.Incoming, len(match.Cases))
|
||||
for index, cas := range match.Cases {
|
||||
// set up ir case
|
||||
caseBlock := this.blockManager.newBlock()
|
||||
hash := match.CaseOrder[index]
|
||||
irCases[index] = &llvm.Case {
|
||||
X: llvm.NewConstInt(irHashType, int64(hash.Number())),
|
||||
Target: caseBlock,
|
||||
}
|
||||
|
||||
// create casted variable
|
||||
irType, err := this.generateType(cas.Declaration.Type())
|
||||
if err != nil { return nil, false, err }
|
||||
dataFieldLoc := this.getUnionDataFieldLoc(value, irUnionType)
|
||||
data := this.blockManager.NewLoad(irType, dataFieldLoc)
|
||||
this.blockManager.addDeclaration(cas.Declaration, data)
|
||||
|
||||
// generate case expression
|
||||
thisMode := mode // FIXME this logic isnt in if/else, why??
|
||||
if index != 0 && mode != resultModeAny {
|
||||
if loc { thisMode = resultModeLoc
|
||||
} else { thisMode = resultModeVal }
|
||||
}
|
||||
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() { this.blockManager.NewBr(exitBlock) }
|
||||
}
|
||||
|
||||
// create switch branch
|
||||
this.blockManager.Block = previousBlock
|
||||
hashFieldLoc := this.getUnionTypeFieldLoc(value, irUnionType)
|
||||
hash := this.blockManager.NewLoad(irHashType, hashFieldLoc)
|
||||
this.blockManager.NewSwitch(hash, exitBlock, irCases...)
|
||||
|
||||
// discard/obtain results
|
||||
this.blockManager.Block = exitBlock
|
||||
if mode == resultModeAny {
|
||||
return nil, false, nil
|
||||
} else {
|
||||
return this.blockManager.NewPhi(irIncomings...), loc, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (this *generator) generateLoop (loop *entity.Loop, mode resultMode) (llvm.Value, bool, error) {
|
||||
|
|
Loading…
Reference in New Issue