lp_bld_flow.h revision 630fa2688634365c03edf2a189cf9225899fbcc5
1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/**
29 * LLVM control flow build helpers.
30 *
31 * @author Jose Fonseca <jfonseca@vmware.com>
32 */
33
34#ifndef LP_BLD_FLOW_H
35#define LP_BLD_FLOW_H
36
37
38#include "gallivm/lp_bld.h"
39
40
41struct lp_type;
42
43
44/**
45 * Early exit. Useful to skip to the end of a function or block when
46 * the execution mask becomes zero or when there is an error condition.
47 */
48struct lp_build_skip_context
49{
50   struct gallivm_state *gallivm;
51
52   /** Block to skip to */
53   LLVMBasicBlockRef block;
54};
55
56void
57lp_build_flow_skip_begin(struct lp_build_skip_context *ctx,
58                         struct gallivm_state *gallivm);
59
60void
61lp_build_flow_skip_cond_break(struct lp_build_skip_context *ctx,
62                              LLVMValueRef cond);
63
64void
65lp_build_flow_skip_end(struct lp_build_skip_context *ctx);
66
67
68struct lp_build_mask_context
69{
70   struct lp_build_skip_context skip;
71
72   LLVMTypeRef reg_type;
73
74   LLVMValueRef var;
75};
76
77
78void
79lp_build_mask_begin(struct lp_build_mask_context *mask,
80                    struct gallivm_state *gallivm,
81                    struct lp_type type,
82                    LLVMValueRef value);
83
84LLVMValueRef
85lp_build_mask_value(struct lp_build_mask_context *mask);
86
87/**
88 * Bitwise AND the mask with the given value, if a previous mask was set.
89 */
90void
91lp_build_mask_update(struct lp_build_mask_context *mask,
92                     LLVMValueRef value);
93
94void
95lp_build_mask_check(struct lp_build_mask_context *mask);
96
97LLVMValueRef
98lp_build_mask_end(struct lp_build_mask_context *mask);
99
100
101/**
102 * LLVM's IR doesn't represent for-loops directly. Furthermore it
103 * it requires creating code blocks, branches, phi variables, so it
104 * requires a fair amount of code.
105 *
106 * @sa http://www.llvm.org/docs/tutorial/LangImpl5.html#for
107 */
108struct lp_build_loop_state
109{
110   LLVMBasicBlockRef block;
111   LLVMValueRef counter_var;
112   LLVMValueRef counter;
113   struct gallivm_state *gallivm;
114};
115
116
117void
118lp_build_loop_begin(struct lp_build_loop_state *state,
119                    struct gallivm_state *gallivm,
120                    LLVMValueRef start);
121
122void
123lp_build_loop_end(struct lp_build_loop_state *state,
124                  LLVMValueRef end,
125                  LLVMValueRef step);
126
127void
128lp_build_loop_end_cond(struct lp_build_loop_state *state,
129                       LLVMValueRef end,
130                       LLVMValueRef step,
131                       LLVMIntPredicate cond);
132
133
134/**
135 * Implementation of simple C-style for loops
136 */
137struct lp_build_for_loop_state
138{
139   LLVMBasicBlockRef begin;
140   LLVMBasicBlockRef body;
141   LLVMBasicBlockRef exit;
142   LLVMValueRef counter_var;
143   LLVMValueRef counter;
144   LLVMValueRef step;
145   LLVMIntPredicate cond;
146   LLVMValueRef end;
147   struct gallivm_state *gallivm;
148};
149
150void
151lp_build_for_loop_begin(struct lp_build_for_loop_state *state,
152                        struct gallivm_state *gallivm,
153                        LLVMValueRef start,
154                        LLVMIntPredicate llvm_cond,
155                        LLVMValueRef end,
156                        LLVMValueRef step);
157
158void
159lp_build_for_loop_end(struct lp_build_for_loop_state *state);
160
161
162/**
163 * if/else/endif.
164 */
165struct lp_build_if_state
166{
167   struct gallivm_state *gallivm;
168   LLVMValueRef condition;
169   LLVMBasicBlockRef entry_block;
170   LLVMBasicBlockRef true_block;
171   LLVMBasicBlockRef false_block;
172   LLVMBasicBlockRef merge_block;
173};
174
175
176void
177lp_build_if(struct lp_build_if_state *ctx,
178            struct gallivm_state *gallivm,
179            LLVMValueRef condition);
180
181void
182lp_build_else(struct lp_build_if_state *ctx);
183
184void
185lp_build_endif(struct lp_build_if_state *ctx);
186
187LLVMBasicBlockRef
188lp_build_insert_new_block(struct gallivm_state *gallivm, const char *name);
189
190LLVMValueRef
191lp_build_alloca(struct gallivm_state *gallivm,
192                LLVMTypeRef type,
193                const char *name);
194
195LLVMValueRef
196lp_build_array_alloca(struct gallivm_state *gallivm,
197                      LLVMTypeRef type,
198                      LLVMValueRef count,
199                      const char *name);
200
201#endif /* !LP_BLD_FLOW_H */
202