Fixed several cases where the generator would output invalid IR
This commit is contained in:
parent
a7fe9a592b
commit
b0c3839ed9
@ -309,69 +309,66 @@ func (this *Tree) areStructurallyEquivalent (left, right entity.Type) bool {
|
|||||||
// isLocationExpression returns whether or not an expression is a valid location
|
// isLocationExpression returns whether or not an expression is a valid location
|
||||||
// expression.
|
// expression.
|
||||||
func (this *Tree) isLocationExpression (expression entity.Expression) error {
|
func (this *Tree) isLocationExpression (expression entity.Expression) error {
|
||||||
switch expression.(type) {
|
switch expression := expression.(type) {
|
||||||
case *entity.Variable:
|
case *entity.Variable:
|
||||||
return nil
|
return nil
|
||||||
case *entity.Declaration:
|
case *entity.Declaration:
|
||||||
return nil
|
return nil
|
||||||
case *entity.Call:
|
case *entity.Call:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Call).Pos,
|
expression.Pos,
|
||||||
"cannot assign to function call")
|
"cannot assign to function call")
|
||||||
case *entity.MethodCall:
|
case *entity.MethodCall:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.MethodCall).Pos,
|
expression.Pos,
|
||||||
"cannot assign to method call")
|
"cannot assign to method call")
|
||||||
case *entity.Subscript:
|
case *entity.Subscript:
|
||||||
return this.isLocationExpression (
|
return this.isLocationExpression(expression.Slice)
|
||||||
expression.(*entity.Subscript).Slice)
|
|
||||||
case *entity.Slice:
|
case *entity.Slice:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.MethodCall).Pos,
|
expression.Pos,
|
||||||
"cannot assign to slice operation")
|
"cannot assign to slice operation")
|
||||||
case *entity.Dereference:
|
case *entity.Dereference:
|
||||||
return this.isLocationExpression (
|
return this.isLocationExpression(expression.Pointer)
|
||||||
expression.(*entity.Dereference).Pointer)
|
|
||||||
case *entity.Reference:
|
case *entity.Reference:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Reference).Pos,
|
expression.Pos,
|
||||||
"cannot assign to reference operation")
|
"cannot assign to reference operation")
|
||||||
case *entity.ValueCast:
|
case *entity.ValueCast:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.ValueCast).Pos,
|
expression.Pos,
|
||||||
"cannot assign to value cast")
|
"cannot assign to value cast")
|
||||||
case *entity.BitCast:
|
case *entity.BitCast:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.BitCast).Pos,
|
expression.Pos,
|
||||||
"cannot assign to bit cast")
|
"cannot assign to bit cast")
|
||||||
case *entity.Operation:
|
case *entity.Operation:
|
||||||
expression := expression.(*entity.Operation)
|
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.Pos,
|
expression.Pos,
|
||||||
"cannot assign to %v operation",
|
"cannot assign to %v operation",
|
||||||
expression.Operator)
|
expression.Operator)
|
||||||
case *entity.Block:
|
case *entity.Block:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Block).Pos,
|
expression.Pos,
|
||||||
"cannot assign to block")
|
"cannot assign to block")
|
||||||
case *entity.MemberAccess:
|
case *entity.MemberAccess:
|
||||||
return this.isLocationExpression (
|
return this.isLocationExpression (
|
||||||
expression.(*entity.MemberAccess).Source)
|
expression.Source)
|
||||||
case *entity.IfElse:
|
case *entity.IfElse:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Block).Pos,
|
expression.Pos,
|
||||||
"cannot assign to if/else")
|
"cannot assign to if/else")
|
||||||
case *entity.Loop:
|
case *entity.Loop:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Block).Pos,
|
expression.Pos,
|
||||||
"cannot assign to loop")
|
"cannot assign to loop")
|
||||||
case *entity.Break:
|
case *entity.Break:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Block).Pos,
|
expression.Pos,
|
||||||
"cannot assign to break statement")
|
"cannot assign to break statement")
|
||||||
case *entity.Return:
|
case *entity.Return:
|
||||||
return participle.Errorf (
|
return participle.Errorf (
|
||||||
expression.(*entity.Block).Pos,
|
expression.Pos,
|
||||||
"cannot assign to return statement")
|
"cannot assign to return statement")
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprint (
|
panic(fmt.Sprint (
|
||||||
@ -442,9 +439,9 @@ func isFloat (ty entity.Type) bool {
|
|||||||
|
|
||||||
// IsUnsigned returns whether or not the specified type is an unsigned integer.
|
// IsUnsigned returns whether or not the specified type is an unsigned integer.
|
||||||
func IsUnsigned (ty entity.Type) bool {
|
func IsUnsigned (ty entity.Type) bool {
|
||||||
switch ReduceToBase(ty).(type) {
|
switch ty := ReduceToBase(ty).(type) {
|
||||||
case *entity.TypeInt: return ty.(*entity.TypeInt).Signed
|
case *entity.TypeInt: return ty.Signed
|
||||||
case *entity.TypeWord: return ty.(*entity.TypeInt).Signed
|
case *entity.TypeWord: return ty.Signed
|
||||||
default: return false
|
default: return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -614,7 +614,6 @@ func (this *Tree) analyzeIfElse (
|
|||||||
ifelse.False = falseBranch
|
ifelse.False = falseBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
ifelse.Ty = ifelse.True.Type()
|
|
||||||
return ifelse, nil
|
return ifelse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,8 +42,8 @@ func (this *generator) generateExpression (expression entity.Expression) (llvm.V
|
|||||||
return this.generateMethodCall(expression)
|
return this.generateMethodCall(expression)
|
||||||
case *entity.Reference:
|
case *entity.Reference:
|
||||||
return this.generateReference(expression)
|
return this.generateReference(expression)
|
||||||
// case *entity.Length:
|
case *entity.Length:
|
||||||
// return this.generateLength(expression)
|
return this.generateLength(expression)
|
||||||
case *entity.ValueCast:
|
case *entity.ValueCast:
|
||||||
return this.generateValueCast(expression)
|
return this.generateValueCast(expression)
|
||||||
case *entity.BitCast:
|
case *entity.BitCast:
|
||||||
|
|||||||
@ -94,6 +94,48 @@ func (this *generator) generateReference (reference *entity.Reference) (llvm.Val
|
|||||||
return this.generateExpressionLoc(reference.Value)
|
return this.generateExpressionLoc(reference.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *generator) generateLength (length *entity.Length) (llvm.Value, error) {
|
||||||
|
var sizeType *llvm.TypeInt; {
|
||||||
|
ty, err := this.typedef("Index")
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
sizeType = ty.(*llvm.TypeInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
source, err := this.generateExpressionLoc(length.Slice)
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
|
sourceType := analyzer.ReduceToBase(length.Slice.Type())
|
||||||
|
switch sourceType := sourceType.(type) {
|
||||||
|
case *entity.TypeSlice:
|
||||||
|
irSourceType, err := this.generateType(sourceType)
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
|
startFieldAddress := this.blockManager.NewGetElementPtr (
|
||||||
|
irSourceType,
|
||||||
|
source,
|
||||||
|
llvm.NewConstInt(llvm.I32, 0),
|
||||||
|
llvm.NewConstInt(llvm.I32, 1))
|
||||||
|
start := this.blockManager.NewLoad(sizeType, startFieldAddress)
|
||||||
|
|
||||||
|
endFieldAddress := this.blockManager.NewGetElementPtr (
|
||||||
|
irSourceType,
|
||||||
|
source,
|
||||||
|
llvm.NewConstInt(llvm.I32, 0),
|
||||||
|
llvm.NewConstInt(llvm.I32, 2))
|
||||||
|
end := this.blockManager.NewLoad(sizeType, endFieldAddress)
|
||||||
|
|
||||||
|
return this.blockManager.NewSub(end, start), nil
|
||||||
|
|
||||||
|
case *entity.TypeArray:
|
||||||
|
return llvm.NewConstInt(sizeType, int64(sourceType.Length)), nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprint (
|
||||||
|
"BUG: generator can't get length of expression ",
|
||||||
|
length.Slice))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (this *generator) generateValueCast (cast *entity.ValueCast) (llvm.Value, error) {
|
func (this *generator) generateValueCast (cast *entity.ValueCast) (llvm.Value, error) {
|
||||||
generateFrom := func () (llvm.Value, llvm.Type, error) {
|
generateFrom := func () (llvm.Value, llvm.Type, error) {
|
||||||
from, err := this.generateExpression(cast.Value)
|
from, err := this.generateExpression(cast.Value)
|
||||||
@ -553,30 +595,52 @@ func (this *generator) generateIfElse (ifelse *entity.IfElse, loc bool) (llvm.Va
|
|||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
if ifelse.False != nil {
|
if ifelse.False != nil {
|
||||||
falseBlock = this.blockManager.newBlock()
|
if ifelse.Type() == nil {
|
||||||
if loc {
|
falseBlock = this.blockManager.newBlock()
|
||||||
fals, err = this.generateExpressionLoc(ifelse.False)
|
if loc {
|
||||||
|
fals, err = this.generateExpressionLoc(ifelse.False)
|
||||||
|
} else {
|
||||||
|
fals, err = this.generateExpression(ifelse.False)
|
||||||
|
}
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
|
previous.NewCondBr(condition, trueBlock, falseBlock)
|
||||||
|
exitBlock := this.blockManager.newBlock()
|
||||||
|
falseBlock.NewBr(exitBlock)
|
||||||
|
trueBlock.NewBr(exitBlock)
|
||||||
|
return nil, nil
|
||||||
} else {
|
} else {
|
||||||
fals, err = this.generateExpression(ifelse.False)
|
falseBlock = this.blockManager.newBlock()
|
||||||
}
|
if loc {
|
||||||
if err != nil { return nil, err }
|
fals, err = this.generateExpressionLoc(ifelse.False)
|
||||||
|
} else {
|
||||||
|
fals, err = this.generateExpression(ifelse.False)
|
||||||
|
}
|
||||||
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
trueIncoming := &llvm.Incoming {
|
trueIncoming := &llvm.Incoming {
|
||||||
X: tru,
|
X: tru,
|
||||||
Predecessor: trueBlock,
|
Predecessor: trueBlock,
|
||||||
}
|
}
|
||||||
falseIncoming := &llvm.Incoming {
|
falseIncoming := &llvm.Incoming {
|
||||||
X: fals,
|
X: fals,
|
||||||
Predecessor: falseBlock,
|
Predecessor: falseBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
previous.NewCondBr(condition, trueBlock, falseBlock)
|
previous.NewCondBr(condition, trueBlock, falseBlock)
|
||||||
this.blockManager.newBlock()
|
exitBlock := this.blockManager.newBlock()
|
||||||
return this.blockManager.NewPhi(trueIncoming, falseIncoming), nil
|
falseBlock.NewBr(exitBlock)
|
||||||
|
trueBlock.NewBr(exitBlock)
|
||||||
|
return this.blockManager.NewPhi(trueIncoming, falseIncoming), nil
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exitBlock := this.blockManager.newBlock()
|
exitBlock := this.blockManager.newBlock()
|
||||||
falseBlock.NewBr(exitBlock)
|
trueBlock.NewBr(exitBlock)
|
||||||
previous.NewCondBr(condition, trueBlock, falseBlock)
|
if falseBlock == nil {
|
||||||
|
previous.NewCondBr(condition, trueBlock, exitBlock)
|
||||||
|
} else {
|
||||||
|
previous.NewCondBr(condition, trueBlock, falseBlock)
|
||||||
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||