-
Notifications
You must be signed in to change notification settings - Fork 1
/
boolean_operator.go
92 lines (83 loc) · 3.44 KB
/
boolean_operator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*---------------------------------------------------------------------------------------------
* Copyright (c) Peter Bjorklund. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/
package generate_ir
import (
"fmt"
"github.com/llir/llvm/ir"
"github.com/llir/llvm/ir/constant"
"github.com/llir/llvm/ir/enum"
"github.com/llir/llvm/ir/types"
"github.com/llir/llvm/ir/value"
decorated "github.com/swamp/compiler/src/decorated/expression"
dectype "github.com/swamp/compiler/src/decorated/types"
"log"
)
func booleanIntToIPred(operatorType decorated.BooleanOperatorType) enum.IPred {
switch operatorType {
case decorated.BooleanEqual:
return enum.IPredEQ
case decorated.BooleanNotEqual:
return enum.IPredNE
case decorated.BooleanLess:
return enum.IPredSLT
case decorated.BooleanLessOrEqual:
return enum.IPredSLE
case decorated.BooleanGreater:
return enum.IPredSGT
case decorated.BooleanGreaterOrEqual:
return enum.IPredSGE
default:
panic(fmt.Errorf("not allowed int operator type"))
}
return 0
}
func generateBinaryOperatorBooleanResult(operator *decorated.BooleanOperator, genContext *generateContext) (value.Value, error) {
leftVar, leftErr := generateExpression(operator.Left(), false, genContext)
if leftErr != nil {
return nil, leftErr
}
rightVar, rightErr := generateExpression(operator.Right(), false, genContext)
if rightErr != nil {
return nil, rightErr
}
unaliasedTypeLeft := dectype.UnaliasWithResolveInvoker(operator.Left().Type())
foundPrimitive, _ := unaliasedTypeLeft.(*dectype.PrimitiveAtom)
if foundPrimitive == nil {
foundCustomType, _ := unaliasedTypeLeft.(*dectype.CustomTypeAtom)
if foundCustomType == nil {
panic(fmt.Errorf("not implemented binary operator boolean %v", unaliasedTypeLeft.HumanReadable()))
} else {
zeroIndex := constant.NewInt(types.I32, 0)
var indices []value.Value
indices = append(indices, zeroIndex)
indices = append(indices, zeroIndex)
leftPtrToOctet := ir.NewGetElementPtr(types.I8Ptr, leftVar, indices...)
rightPtrToOctet := ir.NewGetElementPtr(types.I8Ptr, rightVar, indices...)
predicate := booleanIntToIPred(operator.OperatorType())
leftOctet := ir.NewLoad(types.I8, leftPtrToOctet)
rightOctet := ir.NewLoad(types.I8, rightPtrToOctet)
ir.NewICmp(predicate, leftOctet, rightOctet)
}
} else if foundPrimitive.AtomName() == "String" {
stringCompare := &ir.Func{} // TODO: Fetch string compare functions
return ir.NewCall(stringCompare, leftVar, rightVar), nil
} else if foundPrimitive.AtomName() == "Int" || foundPrimitive.AtomName() == "Char" || foundPrimitive.AtomName() == "Fixed" {
predicate := booleanIntToIPred(operator.OperatorType())
log.Printf("%T left:%T, right:%T", operator.Left(), leftVar, rightVar)
return ir.NewICmp(predicate, leftVar, rightVar), nil
} else if foundPrimitive.AtomName() == "Bool" {
isNotEqual := genContext.block.NewXor(leftVar, rightVar)
if operator.OperatorType() == decorated.BooleanEqual {
return ir.NewXor(isNotEqual, constant.NewBool(true)), nil
} else if operator.OperatorType() == decorated.BooleanNotEqual {
return isNotEqual, nil
} else {
panic(fmt.Errorf("illegal boolean operator for bool %v", operator))
}
} else {
panic(fmt.Errorf("generate sp: what operator is this for %v", foundPrimitive.AtomName()))
}
panic(fmt.Errorf("unknwon"))
}