-
Notifications
You must be signed in to change notification settings - Fork 1
/
case_custom_type.go
105 lines (86 loc) · 3.52 KB
/
case_custom_type.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
93
94
95
96
97
98
99
100
101
102
103
104
105
/*---------------------------------------------------------------------------------------------
* 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/types"
"github.com/llir/llvm/ir/value"
"github.com/swamp/compiler/src/decorated/dtype"
decorated "github.com/swamp/compiler/src/decorated/expression"
"log"
)
func GetIrType(p dtype.Type) types.Type {
return types.I32
}
type customTypeCaseConsequence struct {
Block *ir.Block
Value value.Value
Incoming *ir.Incoming
}
func generateCaseCustomType(caseExpr *decorated.CaseCustomType, genContext *generateContext) (value.Value, error) {
testVar, testErr := generateExpression(caseExpr.Test(), false, genContext)
if testErr != nil {
return nil, testErr
}
var consequenceBlocks []customTypeCaseConsequence
for consequenceIndex, consequence := range caseExpr.Consequences() {
customTypeCaseConsequence := customTypeCaseConsequence{}
fields := consequence.VariantReference().CustomTypeVariant().Fields()
for index, param := range consequence.Parameters() {
field := fields[index]
consequenceParameter := ir.NewGetElementPtr(GetIrType(field.Type()), testVar, constant.NewInt(types.I32, int64(index)))
consequenceParameter.LocalIdent.SetName(param.Identifier().Name())
}
consequenceContext := genContext.NewBlock(fmt.Sprintf("consequnce%d", consequenceIndex))
consequenceValue, caseExprErr := generateExpression(consequence.Expression(), false, consequenceContext)
if caseExprErr != nil {
return nil, caseExprErr
}
if consequenceValue == nil {
panic(fmt.Errorf("this should have been reported as error"))
}
customTypeCaseConsequence.Value = consequenceValue
customTypeCaseConsequence.Block = consequenceContext.block
customTypeCaseConsequence.Incoming = ir.NewIncoming(customTypeCaseConsequence.Value, customTypeCaseConsequence.Block)
consequenceBlocks = append(consequenceBlocks, customTypeCaseConsequence)
}
defaultCase := customTypeCaseConsequence{Block: nil}
var defaultIncoming *ir.Incoming
if caseExpr.DefaultCase() != nil {
defaultBlock := ir.NewBlock("default")
newContext := genContext
newContext.block = defaultBlock
defaultValue, testErr := generateExpression(caseExpr.DefaultCase(), false, genContext)
if testErr != nil {
return nil, testErr
}
defaultCase.Block = defaultBlock
defaultIncoming = ir.NewIncoming(defaultValue, defaultBlock)
}
cases := make([]*ir.Case, len(consequenceBlocks))
for index, consequenceBlock := range consequenceBlocks {
cases[index] = ir.NewCase(constant.NewInt(types.I32, int64(index)), consequenceBlock.Block)
}
genContext.block.NewSwitch(testVar, defaultCase.Block, cases...)
var incomingInfos []*ir.Incoming
if defaultIncoming != nil {
incomingInfos = append(incomingInfos, defaultIncoming)
}
for _, consequenceBlock := range consequenceBlocks {
incoming := ir.NewIncoming(consequenceBlock.Value, consequenceBlock.Block)
if consequenceBlock.Value == nil {
panic("consequenceBlock.Value is nil")
}
if consequenceBlock.Block == nil {
panic("consequenceBlock.Block is nil")
}
incomingInfos = append(incomingInfos, incoming)
}
log.Printf("incoming infos %v", incomingInfos)
phiInstruction := genContext.block.NewPhi(incomingInfos...)
return phiInstruction, nil
}