-
Notifications
You must be signed in to change notification settings - Fork 78
/
block_term.go
140 lines (114 loc) · 5.26 KB
/
block_term.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package ir
import (
"github.com/llir/llvm/ir/constant"
"github.com/llir/llvm/ir/value"
)
// --- [ Terminators ] ---------------------------------------------------------
// ~~~ [ ret ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewRet sets the terminator of the basic block to a new ret terminator based
// on the given return value. A nil return value indicates a void return.
func (block *Block) NewRet(x value.Value) *TermRet {
term := NewRet(x)
block.Term = term
return term
}
// ~~~ [ br ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewBr sets the terminator of the basic block to a new unconditional br
// terminator based on the given target basic block.
func (block *Block) NewBr(target *Block) *TermBr {
term := NewBr(target)
block.Term = term
return term
}
// ~~~ [ conditional br ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewCondBr sets the terminator of the basic block to a new conditional br
// terminator based on the given branching condition and conditional target
// basic blocks.
func (block *Block) NewCondBr(cond value.Value, targetTrue, targetFalse *Block) *TermCondBr {
term := NewCondBr(cond, targetTrue, targetFalse)
block.Term = term
return term
}
// ~~~ [ switch ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewSwitch sets the terminator of the basic block to a new switch terminator
// based on the given control variable, default target basic block and switch
// cases.
func (block *Block) NewSwitch(x value.Value, targetDefault *Block, cases ...*Case) *TermSwitch {
term := NewSwitch(x, targetDefault, cases...)
block.Term = term
return term
}
// ~~~ [ indirectbr ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewIndirectBr sets the terminator of the basic block to a new indirectbr
// terminator based on the given target address (derived from a blockaddress
// constant) and set of valid target basic blocks.
func (block *Block) NewIndirectBr(addr constant.Constant, validTargets ...*Block) *TermIndirectBr {
term := NewIndirectBr(addr, validTargets...)
block.Term = term
return term
}
// ~~~ [ invoke ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewInvoke sets the terminator of the basic block to a new invoke terminator
// based on the given invokee, function arguments and control flow return points
// for normal and exceptional execution.
//
// TODO: specify the set of underlying types of invokee.
func (block *Block) NewInvoke(invokee value.Value, args []value.Value, normalRetTarget, exceptionRetTarget *Block) *TermInvoke {
term := NewInvoke(invokee, args, normalRetTarget, exceptionRetTarget)
block.Term = term
return term
}
// ~~~ [ callbr ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewCallBr sets the terminator of the basic block to a new callbr terminator
// based on the given callee, function arguments and control flow return points
// for normal and exceptional execution.
//
// TODO: specify the set of underlying types of callee.
func (block *Block) NewCallBr(callee value.Value, args []value.Value, normalRetTarget *Block, otherRetTargets ...*Block) *TermCallBr {
term := NewCallBr(callee, args, normalRetTarget, otherRetTargets...)
block.Term = term
return term
}
// ~~~ [ resume ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewResume sets the terminator of the basic block to a new resume terminator
// based on the given exception argument to propagate.
func (block *Block) NewResume(x value.Value) *TermResume {
term := NewResume(x)
block.Term = term
return term
}
// ~~~ [ catchswitch ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewCatchSwitch sets the terminator of the basic block to a new catchswitch
// terminator based on the given parent exception pad, exception handlers and
// optional default unwind target. If defaultUnwindTarget is nil, catchswitch
// unwinds to caller function.
func (block *Block) NewCatchSwitch(parentPad ExceptionPad, handlers []*Block, defaultUnwindTarget *Block) *TermCatchSwitch {
term := NewCatchSwitch(parentPad, handlers, defaultUnwindTarget)
block.Term = term
return term
}
// ~~~ [ catchret ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewCatchRet sets the terminator of the basic block to a new catchret
// terminator based on the given exit catchpad and target basic block.
func (block *Block) NewCatchRet(catchPad *InstCatchPad, target *Block) *TermCatchRet {
term := NewCatchRet(catchPad, target)
block.Term = term
return term
}
// ~~~ [ cleanupret ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewCleanupRet sets the terminator of the basic block to a new cleanupret
// terminator based on the given exit cleanuppad and optional unwind target. If
// unwindTarget is nil, cleanupret unwinds to caller function.
func (block *Block) NewCleanupRet(cleanupPad *InstCleanupPad, unwindTarget *Block) *TermCleanupRet {
term := NewCleanupRet(cleanupPad, unwindTarget)
block.Term = term
return term
}
// ~~~ [ unreachable ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NewUnreachable sets the terminator of the basic block to a new unreachable
// terminator.
func (block *Block) NewUnreachable() *TermUnreachable {
term := NewUnreachable()
block.Term = term
return term
}