blob: bc831389085fa175923859fc3b375951e7924ad3 [file] [log] [blame]
José Fonseca87837322009-07-27 01:23:15 +01001/**************************************************************************
2 *
José Fonseca9a519ec2009-07-28 08:14:10 +01003 * Copyright 2009 VMware, Inc.
José Fonseca87837322009-07-27 01:23:15 +01004 * 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
José Fonseca87837322009-07-27 01:23:15 +010028/**
José Fonsecac5531f52009-08-21 10:57:48 +010029 * LLVM control flow build helpers.
José Fonseca87837322009-07-27 01:23:15 +010030 *
José Fonsecac5531f52009-08-21 10:57:48 +010031 * @author Jose Fonseca <jfonseca@vmware.com>
José Fonseca87837322009-07-27 01:23:15 +010032 */
33
José Fonseca3d7a8862009-08-21 13:49:10 +010034#include "util/u_debug.h"
José Fonseca8e6b9252009-09-10 11:44:03 +010035#include "util/u_memory.h"
José Fonseca3d7a8862009-08-21 13:49:10 +010036
37#include "lp_bld_type.h"
José Fonsecac5531f52009-08-21 10:57:48 +010038#include "lp_bld_flow.h"
39
40
José Fonseca8e6b9252009-09-10 11:44:03 +010041#define LP_BUILD_FLOW_MAX_VARIABLES 32
42#define LP_BUILD_FLOW_MAX_DEPTH 32
José Fonseca3d7a8862009-08-21 13:49:10 +010043
José Fonseca8e6b9252009-09-10 11:44:03 +010044/**
45 * Enumeration of all possible flow constructs.
46 */
47enum lp_build_flow_construct_kind {
Brian Paulaeb63512009-12-17 14:26:48 -070048 LP_BUILD_FLOW_SCOPE,
José Fonseca8e6b9252009-09-10 11:44:03 +010049 LP_BUILD_FLOW_SKIP,
Brian Paulbaeb3a22010-01-06 17:53:12 -070050 LP_BUILD_FLOW_IF
José Fonseca8e6b9252009-09-10 11:44:03 +010051};
52
53
54/**
55 * Variable declaration scope.
56 */
57struct lp_build_flow_scope
58{
59 /** Number of variables declared in this scope */
60 unsigned num_variables;
61};
62
63
64/**
65 * Early exit. Useful to skip to the end of a function or block when
66 * the execution mask becomes zero or when there is an error condition.
67 */
68struct lp_build_flow_skip
69{
70 /** Block to skip to */
71 LLVMBasicBlockRef block;
72
73 /** Number of variables declared at the beginning */
74 unsigned num_variables;
75
Brian Paulbaeb3a22010-01-06 17:53:12 -070076 LLVMValueRef *phi; /**< array [num_variables] */
77};
78
79
80/**
81 * if/else/endif.
82 */
83struct lp_build_flow_if
84{
85 unsigned num_variables;
86
Brian Paul70b8d592010-01-08 11:01:00 -070087 LLVMValueRef *phi; /**< array [num_variables] */
Brian Paul855d7f52010-01-08 11:32:36 -070088
89 LLVMValueRef condition;
90 LLVMBasicBlockRef entry_block, true_block, false_block, merge_block;
José Fonseca8e6b9252009-09-10 11:44:03 +010091};
92
93
94/**
95 * Union of all possible flow constructs' data
96 */
97union lp_build_flow_construct_data
98{
99 struct lp_build_flow_scope scope;
100 struct lp_build_flow_skip skip;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700101 struct lp_build_flow_if ifthen;
José Fonseca8e6b9252009-09-10 11:44:03 +0100102};
103
104
105/**
106 * Element of the flow construct stack.
107 */
108struct lp_build_flow_construct
109{
110 enum lp_build_flow_construct_kind kind;
111 union lp_build_flow_construct_data data;
112};
113
114
115/**
116 * All necessary data to generate LLVM control flow constructs.
117 *
118 * Besides keeping track of the control flow construct themselves we also
119 * need to keep track of variables in order to generate SSA Phi values.
120 */
121struct lp_build_flow_context
122{
123 LLVMBuilderRef builder;
124
125 /**
126 * Control flow stack.
127 */
128 struct lp_build_flow_construct constructs[LP_BUILD_FLOW_MAX_DEPTH];
129 unsigned num_constructs;
130
131 /**
132 * Variable stack
133 */
134 LLVMValueRef *variables[LP_BUILD_FLOW_MAX_VARIABLES];
135 unsigned num_variables;
136};
137
138
139struct lp_build_flow_context *
140lp_build_flow_create(LLVMBuilderRef builder)
141{
142 struct lp_build_flow_context *flow;
143
144 flow = CALLOC_STRUCT(lp_build_flow_context);
145 if(!flow)
146 return NULL;
147
148 flow->builder = builder;
149
150 return flow;
José Fonseca3d7a8862009-08-21 13:49:10 +0100151}
152
153
154void
José Fonseca8e6b9252009-09-10 11:44:03 +0100155lp_build_flow_destroy(struct lp_build_flow_context *flow)
José Fonseca3d7a8862009-08-21 13:49:10 +0100156{
José Fonseca8e6b9252009-09-10 11:44:03 +0100157 assert(flow->num_constructs == 0);
158 assert(flow->num_variables == 0);
159 FREE(flow);
160}
José Fonseca3d7a8862009-08-21 13:49:10 +0100161
José Fonseca8e6b9252009-09-10 11:44:03 +0100162
Brian Paul4e8d67a2010-01-04 15:22:58 -0700163/**
164 * Begin/push a new flow control construct, such as a loop, skip block
165 * or variable scope.
166 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100167static union lp_build_flow_construct_data *
168lp_build_flow_push(struct lp_build_flow_context *flow,
169 enum lp_build_flow_construct_kind kind)
170{
171 assert(flow->num_constructs < LP_BUILD_FLOW_MAX_DEPTH);
172 if(flow->num_constructs >= LP_BUILD_FLOW_MAX_DEPTH)
173 return NULL;
174
175 flow->constructs[flow->num_constructs].kind = kind;
176 return &flow->constructs[flow->num_constructs++].data;
177}
178
179
Brian Paul4e8d67a2010-01-04 15:22:58 -0700180/**
181 * Return the current/top flow control construct on the stack.
182 * \param kind the expected type of the top-most construct
183 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100184static union lp_build_flow_construct_data *
185lp_build_flow_peek(struct lp_build_flow_context *flow,
186 enum lp_build_flow_construct_kind kind)
187{
188 assert(flow->num_constructs);
189 if(!flow->num_constructs)
190 return NULL;
191
192 assert(flow->constructs[flow->num_constructs - 1].kind == kind);
193 if(flow->constructs[flow->num_constructs - 1].kind != kind)
194 return NULL;
195
196 return &flow->constructs[flow->num_constructs - 1].data;
197}
198
199
Brian Paul4e8d67a2010-01-04 15:22:58 -0700200/**
201 * End/pop the current/top flow control construct on the stack.
202 * \param kind the expected type of the top-most construct
203 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100204static union lp_build_flow_construct_data *
205lp_build_flow_pop(struct lp_build_flow_context *flow,
206 enum lp_build_flow_construct_kind kind)
207{
208 assert(flow->num_constructs);
209 if(!flow->num_constructs)
210 return NULL;
211
212 assert(flow->constructs[flow->num_constructs - 1].kind == kind);
213 if(flow->constructs[flow->num_constructs - 1].kind != kind)
214 return NULL;
215
216 return &flow->constructs[--flow->num_constructs].data;
217}
218
219
220/**
221 * Begin a variable scope.
222 *
223 *
224 */
225void
226lp_build_flow_scope_begin(struct lp_build_flow_context *flow)
227{
228 struct lp_build_flow_scope *scope;
229
Brian Paulaeb63512009-12-17 14:26:48 -0700230 scope = &lp_build_flow_push(flow, LP_BUILD_FLOW_SCOPE)->scope;
José Fonseca8e6b9252009-09-10 11:44:03 +0100231 if(!scope)
232 return;
233
234 scope->num_variables = 0;
235}
236
237
238/**
239 * Declare a variable.
240 *
241 * A variable is a named entity which can have different LLVMValueRef's at
242 * different points of the program. This is relevant for control flow because
Brian Paul4e8d67a2010-01-04 15:22:58 -0700243 * when there are multiple branches to a same location we need to replace
José Fonseca8e6b9252009-09-10 11:44:03 +0100244 * the variable's value with a Phi function as explained in
245 * http://en.wikipedia.org/wiki/Static_single_assignment_form .
246 *
Brian Paul4e8d67a2010-01-04 15:22:58 -0700247 * We keep track of variables by keeping around a pointer to where they're
José Fonseca8e6b9252009-09-10 11:44:03 +0100248 * current.
249 *
250 * There are a few cautions to observe:
251 *
252 * - Variable's value must not be NULL. If there is no initial value then
253 * LLVMGetUndef() should be used.
254 *
255 * - Variable's value must be kept up-to-date. If the variable is going to be
256 * modified by a function then a pointer should be passed so that its value
257 * is accurate. Failure to do this will cause some of the variables'
258 * transient values to be lost, leading to wrong results.
259 *
260 * - A program should be written from top to bottom, by always appending
261 * instructions to the bottom with a single LLVMBuilderRef. Inserting and/or
262 * modifying existing statements will most likely lead to wrong results.
263 *
264 */
265void
266lp_build_flow_scope_declare(struct lp_build_flow_context *flow,
267 LLVMValueRef *variable)
268{
269 struct lp_build_flow_scope *scope;
270
Brian Paulaeb63512009-12-17 14:26:48 -0700271 scope = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SCOPE)->scope;
José Fonseca8e6b9252009-09-10 11:44:03 +0100272 if(!scope)
273 return;
274
275 assert(*variable);
276 if(!*variable)
277 return;
278
279 assert(flow->num_variables < LP_BUILD_FLOW_MAX_VARIABLES);
280 if(flow->num_variables >= LP_BUILD_FLOW_MAX_VARIABLES)
281 return;
282
283 flow->variables[flow->num_variables++] = variable;
284 ++scope->num_variables;
285}
286
287
288void
289lp_build_flow_scope_end(struct lp_build_flow_context *flow)
290{
291 struct lp_build_flow_scope *scope;
292
Brian Paulaeb63512009-12-17 14:26:48 -0700293 scope = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SCOPE)->scope;
José Fonseca8e6b9252009-09-10 11:44:03 +0100294 if(!scope)
295 return;
296
297 assert(flow->num_variables >= scope->num_variables);
298 if(flow->num_variables < scope->num_variables) {
299 flow->num_variables = 0;
300 return;
301 }
302
303 flow->num_variables -= scope->num_variables;
304}
305
306
Brian Paul70b8d592010-01-08 11:01:00 -0700307/**
308 * Note: this function has no dependencies on the flow code and could
309 * be used elsewhere.
310 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100311static LLVMBasicBlockRef
Brian Paul70b8d592010-01-08 11:01:00 -0700312lp_build_insert_new_block(LLVMBuilderRef builder, const char *name)
José Fonseca8e6b9252009-09-10 11:44:03 +0100313{
José Fonseca3d7a8862009-08-21 13:49:10 +0100314 LLVMBasicBlockRef current_block;
315 LLVMBasicBlockRef next_block;
316 LLVMBasicBlockRef new_block;
317
Brian Paul70b8d592010-01-08 11:01:00 -0700318 /* get current basic block */
319 current_block = LLVMGetInsertBlock(builder);
José Fonseca3d7a8862009-08-21 13:49:10 +0100320
Brian Paul70b8d592010-01-08 11:01:00 -0700321 /* check if there's another block after this one */
José Fonseca3d7a8862009-08-21 13:49:10 +0100322 next_block = LLVMGetNextBasicBlock(current_block);
Brian Paul70b8d592010-01-08 11:01:00 -0700323 if (next_block) {
324 /* insert the new block before the next block */
325 new_block = LLVMInsertBasicBlock(next_block, name);
José Fonseca3d7a8862009-08-21 13:49:10 +0100326 }
327 else {
Brian Paul70b8d592010-01-08 11:01:00 -0700328 /* append new block after current block */
José Fonseca3d7a8862009-08-21 13:49:10 +0100329 LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
Brian Paul70b8d592010-01-08 11:01:00 -0700330 new_block = LLVMAppendBasicBlock(function, name);
José Fonseca3d7a8862009-08-21 13:49:10 +0100331 }
332
José Fonseca8e6b9252009-09-10 11:44:03 +0100333 return new_block;
334}
José Fonseca3d7a8862009-08-21 13:49:10 +0100335
Brian Pauldb7f9b02010-01-06 14:11:54 -0700336
Brian Paul70b8d592010-01-08 11:01:00 -0700337static LLVMBasicBlockRef
338lp_build_flow_insert_block(struct lp_build_flow_context *flow)
339{
340 return lp_build_insert_new_block(flow->builder, "");
341}
342
343
Brian Pauldb7f9b02010-01-06 14:11:54 -0700344/**
345 * Begin a "skip" block. Inside this block we can test a condition and
346 * skip to the end of the block if the condition is false.
347 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100348void
349lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
350{
351 struct lp_build_flow_skip *skip;
352 LLVMBuilderRef builder;
353 unsigned i;
354
355 skip = &lp_build_flow_push(flow, LP_BUILD_FLOW_SKIP)->skip;
356 if(!skip)
357 return;
358
Brian Pauldb7f9b02010-01-06 14:11:54 -0700359 /* create new basic block */
José Fonseca8e6b9252009-09-10 11:44:03 +0100360 skip->block = lp_build_flow_insert_block(flow);
Brian Pauldb7f9b02010-01-06 14:11:54 -0700361
José Fonseca8e6b9252009-09-10 11:44:03 +0100362 skip->num_variables = flow->num_variables;
363 if(!skip->num_variables) {
364 skip->phi = NULL;
365 return;
366 }
367
Brian Pauldb7f9b02010-01-06 14:11:54 -0700368 /* Allocate a Phi node for each variable in this skip scope */
José Fonseca8e6b9252009-09-10 11:44:03 +0100369 skip->phi = MALLOC(skip->num_variables * sizeof *skip->phi);
370 if(!skip->phi) {
371 skip->num_variables = 0;
372 return;
373 }
374
375 builder = LLVMCreateBuilder();
376 LLVMPositionBuilderAtEnd(builder, skip->block);
377
Brian Pauldb7f9b02010-01-06 14:11:54 -0700378 /* create a Phi node for each variable */
José Fonseca8e6b9252009-09-10 11:44:03 +0100379 for(i = 0; i < skip->num_variables; ++i)
380 skip->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), "");
381
382 LLVMDisposeBuilder(builder);
383}
384
385
Brian Pauldb7f9b02010-01-06 14:11:54 -0700386/**
387 * Insert code to test a condition and branch to the end of the current
388 * skip block if the condition is true.
389 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100390void
391lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
392 LLVMValueRef cond)
393{
394 struct lp_build_flow_skip *skip;
395 LLVMBasicBlockRef current_block;
396 LLVMBasicBlockRef new_block;
397 unsigned i;
398
399 skip = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SKIP)->skip;
400 if(!skip)
401 return;
402
403 current_block = LLVMGetInsertBlock(flow->builder);
404
405 new_block = lp_build_flow_insert_block(flow);
406
Brian Pauldb7f9b02010-01-06 14:11:54 -0700407 /* for each variable, update the Phi node with a (variable, block) pair */
José Fonseca8e6b9252009-09-10 11:44:03 +0100408 for(i = 0; i < skip->num_variables; ++i) {
409 assert(*flow->variables[i]);
410 LLVMAddIncoming(skip->phi[i], flow->variables[i], &current_block, 1);
411 }
412
Brian Pauldb7f9b02010-01-06 14:11:54 -0700413 /* if cond is true, goto skip->block, else goto new_block */
José Fonseca8e6b9252009-09-10 11:44:03 +0100414 LLVMBuildCondBr(flow->builder, cond, skip->block, new_block);
415
416 LLVMPositionBuilderAtEnd(flow->builder, new_block);
Brian Pauldb7f9b02010-01-06 14:11:54 -0700417}
José Fonseca8e6b9252009-09-10 11:44:03 +0100418
419
420void
421lp_build_flow_skip_end(struct lp_build_flow_context *flow)
422{
423 struct lp_build_flow_skip *skip;
424 LLVMBasicBlockRef current_block;
425 unsigned i;
426
427 skip = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SKIP)->skip;
428 if(!skip)
429 return;
430
431 current_block = LLVMGetInsertBlock(flow->builder);
432
Brian Pauldb7f9b02010-01-06 14:11:54 -0700433 /* add (variable, block) tuples to the phi nodes */
José Fonseca8e6b9252009-09-10 11:44:03 +0100434 for(i = 0; i < skip->num_variables; ++i) {
435 assert(*flow->variables[i]);
436 LLVMAddIncoming(skip->phi[i], flow->variables[i], &current_block, 1);
437 *flow->variables[i] = skip->phi[i];
438 }
439
Brian Pauldb7f9b02010-01-06 14:11:54 -0700440 /* goto block */
José Fonseca8e6b9252009-09-10 11:44:03 +0100441 LLVMBuildBr(flow->builder, skip->block);
442 LLVMPositionBuilderAtEnd(flow->builder, skip->block);
443
444 FREE(skip->phi);
445}
446
447
Brian Paul4e8d67a2010-01-04 15:22:58 -0700448/**
449 * Check if the mask predicate is zero. If so, jump to the end of the block.
450 */
José Fonsecac3c80c52009-09-10 12:01:42 +0100451static void
452lp_build_mask_check(struct lp_build_mask_context *mask)
453{
454 LLVMBuilderRef builder = mask->flow->builder;
455 LLVMValueRef cond;
456
Brian Pauldb7f9b02010-01-06 14:11:54 -0700457 /* cond = (mask == 0) */
José Fonsecac3c80c52009-09-10 12:01:42 +0100458 cond = LLVMBuildICmp(builder,
459 LLVMIntEQ,
460 LLVMBuildBitCast(builder, mask->value, mask->reg_type, ""),
461 LLVMConstNull(mask->reg_type),
462 "");
463
Brian Pauldb7f9b02010-01-06 14:11:54 -0700464 /* if cond, goto end of block */
José Fonsecac3c80c52009-09-10 12:01:42 +0100465 lp_build_flow_skip_cond_break(mask->flow, cond);
466}
467
468
Brian Paul7d9b9772009-12-17 14:22:43 -0700469/**
470 * Begin a section of code which is predicated on a mask.
471 * \param mask the mask context, initialized here
472 * \param flow the flow context
473 * \param type the type of the mask
474 * \param value storage for the mask
475 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100476void
477lp_build_mask_begin(struct lp_build_mask_context *mask,
478 struct lp_build_flow_context *flow,
José Fonsecab4835ea2009-09-14 11:05:06 +0100479 struct lp_type type,
José Fonseca8e6b9252009-09-10 11:44:03 +0100480 LLVMValueRef value)
481{
482 memset(mask, 0, sizeof *mask);
483
484 mask->flow = flow;
485 mask->reg_type = LLVMIntType(type.width * type.length);
486 mask->value = value;
487
488 lp_build_flow_scope_begin(flow);
489 lp_build_flow_scope_declare(flow, &mask->value);
490 lp_build_flow_skip_begin(flow);
José Fonsecac3c80c52009-09-10 12:01:42 +0100491
492 lp_build_mask_check(mask);
José Fonseca8e6b9252009-09-10 11:44:03 +0100493}
494
495
Brian Paul7d9b9772009-12-17 14:22:43 -0700496/**
497 * Update boolean mask with given value (bitwise AND).
498 * Typically used to update the quad's pixel alive/killed mask
499 * after depth testing, alpha testing, TGSI_OPCODE_KIL, etc.
500 */
José Fonseca8e6b9252009-09-10 11:44:03 +0100501void
502lp_build_mask_update(struct lp_build_mask_context *mask,
503 LLVMValueRef value)
504{
José Fonsecac3c80c52009-09-10 12:01:42 +0100505 mask->value = LLVMBuildAnd( mask->flow->builder, mask->value, value, "");
José Fonseca8e6b9252009-09-10 11:44:03 +0100506
José Fonsecac3c80c52009-09-10 12:01:42 +0100507 lp_build_mask_check(mask);
José Fonseca3d7a8862009-08-21 13:49:10 +0100508}
509
510
Brian Paul7d9b9772009-12-17 14:22:43 -0700511/**
512 * End section of code which is predicated on a mask.
513 */
José Fonseca3d7a8862009-08-21 13:49:10 +0100514LLVMValueRef
515lp_build_mask_end(struct lp_build_mask_context *mask)
516{
José Fonseca8e6b9252009-09-10 11:44:03 +0100517 lp_build_flow_skip_end(mask->flow);
518 lp_build_flow_scope_end(mask->flow);
José Fonseca3d7a8862009-08-21 13:49:10 +0100519 return mask->value;
520}
521
522
José Fonseca87837322009-07-27 01:23:15 +0100523
524void
525lp_build_loop_begin(LLVMBuilderRef builder,
526 LLVMValueRef start,
527 struct lp_build_loop_state *state)
528{
529 LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
530 LLVMValueRef function = LLVMGetBasicBlockParent(block);
531
532 state->block = LLVMAppendBasicBlock(function, "loop");
533
534 LLVMBuildBr(builder, state->block);
535
536 LLVMPositionBuilderAtEnd(builder, state->block);
537
538 state->counter = LLVMBuildPhi(builder, LLVMTypeOf(start), "");
539
540 LLVMAddIncoming(state->counter, &start, &block, 1);
541
542}
543
544
545void
546lp_build_loop_end(LLVMBuilderRef builder,
547 LLVMValueRef end,
548 LLVMValueRef step,
549 struct lp_build_loop_state *state)
550{
551 LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
552 LLVMValueRef function = LLVMGetBasicBlockParent(block);
553 LLVMValueRef next;
554 LLVMValueRef cond;
555 LLVMBasicBlockRef after_block;
556
557 if (!step)
558 step = LLVMConstInt(LLVMTypeOf(end), 1, 0);
559
560 next = LLVMBuildAdd(builder, state->counter, step, "");
561
562 cond = LLVMBuildICmp(builder, LLVMIntNE, next, end, "");
563
564 after_block = LLVMAppendBasicBlock(function, "");
565
566 LLVMBuildCondBr(builder, cond, after_block, state->block);
567
568 LLVMAddIncoming(state->counter, &next, &block, 1);
569
570 LLVMPositionBuilderAtEnd(builder, after_block);
571}
572
Brian Paulbaeb3a22010-01-06 17:53:12 -0700573
574
575/*
576 Example of if/then/else building:
577
578 int x;
579 if (cond) {
580 x = 1 + 2;
581 }
582 else {
583 x = 2 + 3;
584 }
585
586 Is built with:
587
Brian Paul70b8d592010-01-08 11:01:00 -0700588 LLVMValueRef x = LLVMGetUndef(); // or something else
589
Brian Paulbaeb3a22010-01-06 17:53:12 -0700590 flow = lp_build_flow_create(builder);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700591
Brian Paul70b8d592010-01-08 11:01:00 -0700592 lp_build_flow_scope_begin(flow);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700593
Brian Paul70b8d592010-01-08 11:01:00 -0700594 // x needs a phi node
595 lp_build_flow_scope_declare(flow, &x);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700596
Brian Paul70b8d592010-01-08 11:01:00 -0700597 lp_build_if(ctx, flow, builder, cond);
598 x = LLVMAdd(1, 2);
599 lp_build_else(ctx);
600 x = LLVMAdd(2, 3);
601 lp_build_endif(ctx);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700602
Brian Paul70b8d592010-01-08 11:01:00 -0700603 lp_build_flow_scope_end(flow);
604
605 lp_build_flow_destroy(flow);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700606 */
607
608
609
610/**
611 * Begin an if/else/endif construct.
612 */
613void
614lp_build_if(struct lp_build_if_state *ctx,
615 struct lp_build_flow_context *flow,
616 LLVMBuilderRef builder,
617 LLVMValueRef condition)
618{
619 LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700620 struct lp_build_flow_if *ifthen;
Brian Paul70b8d592010-01-08 11:01:00 -0700621 unsigned i;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700622
623 memset(ctx, 0, sizeof(*ctx));
624 ctx->builder = builder;
625 ctx->flow = flow;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700626
627 /* push/create new scope */
628 ifthen = &lp_build_flow_push(flow, LP_BUILD_FLOW_IF)->ifthen;
629 assert(ifthen);
630
631 ifthen->num_variables = flow->num_variables;
Brian Paul855d7f52010-01-08 11:32:36 -0700632 ifthen->condition = condition;
633 ifthen->entry_block = block;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700634
Brian Paul70b8d592010-01-08 11:01:00 -0700635 /* create a Phi node for each variable in this flow scope */
636 ifthen->phi = MALLOC(ifthen->num_variables * sizeof(*ifthen->phi));
637 if (!ifthen->phi) {
638 ifthen->num_variables = 0;
639 return;
640 }
641
642 /* create endif/merge basic block for the phi functions */
Brian Paul855d7f52010-01-08 11:32:36 -0700643 ifthen->merge_block = lp_build_insert_new_block(builder, "endif-block");
644 LLVMPositionBuilderAtEnd(builder, ifthen->merge_block);
Brian Paul70b8d592010-01-08 11:01:00 -0700645
646 /* create a phi node for each variable */
Brian Paul5208af72010-01-08 12:47:30 -0700647 for (i = 0; i < flow->num_variables; i++) {
Brian Paul70b8d592010-01-08 11:01:00 -0700648 ifthen->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), "");
649
Brian Paul5208af72010-01-08 12:47:30 -0700650 /* add add the initial value of the var from the entry block */
651 LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->entry_block, 1);
652 }
Brian Paul70b8d592010-01-08 11:01:00 -0700653
654 /* create/insert true_block before merge_block */
Brian Paul855d7f52010-01-08 11:32:36 -0700655 ifthen->true_block = LLVMInsertBasicBlock(ifthen->merge_block, "if-true-block");
Brian Paul70b8d592010-01-08 11:01:00 -0700656
657 /* successive code goes into the true block */
Brian Paul855d7f52010-01-08 11:32:36 -0700658 LLVMPositionBuilderAtEnd(builder, ifthen->true_block);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700659}
660
661
662/**
663 * Begin else-part of a conditional
664 */
665void
666lp_build_else(struct lp_build_if_state *ctx)
667{
Brian Paul70b8d592010-01-08 11:01:00 -0700668 struct lp_build_flow_context *flow = ctx->flow;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700669 struct lp_build_flow_if *ifthen;
Brian Paul70b8d592010-01-08 11:01:00 -0700670 unsigned i;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700671
Brian Paul70b8d592010-01-08 11:01:00 -0700672 ifthen = &lp_build_flow_peek(flow, LP_BUILD_FLOW_IF)->ifthen;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700673 assert(ifthen);
674
Brian Paul70b8d592010-01-08 11:01:00 -0700675 /* for each variable, update the Phi node with a (variable, block) pair */
Brian Paul855d7f52010-01-08 11:32:36 -0700676 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
Brian Paul70b8d592010-01-08 11:01:00 -0700677 for (i = 0; i < flow->num_variables; i++) {
678 assert(*flow->variables[i]);
Brian Paul855d7f52010-01-08 11:32:36 -0700679 LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->true_block, 1);
Brian Paul70b8d592010-01-08 11:01:00 -0700680 }
681
682 /* create/insert false_block before the merge block */
Brian Paul855d7f52010-01-08 11:32:36 -0700683 ifthen->false_block = LLVMInsertBasicBlock(ifthen->merge_block, "if-false-block");
Brian Paul70b8d592010-01-08 11:01:00 -0700684
685 /* successive code goes into the else block */
Brian Paul855d7f52010-01-08 11:32:36 -0700686 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->false_block);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700687}
688
689
690/**
691 * End a conditional.
Brian Paulbaeb3a22010-01-06 17:53:12 -0700692 */
693void
694lp_build_endif(struct lp_build_if_state *ctx)
695{
Brian Paul70b8d592010-01-08 11:01:00 -0700696 struct lp_build_flow_context *flow = ctx->flow;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700697 struct lp_build_flow_if *ifthen;
698 unsigned i;
699
Brian Paul70b8d592010-01-08 11:01:00 -0700700 ifthen = &lp_build_flow_pop(flow, LP_BUILD_FLOW_IF)->ifthen;
Brian Paulbaeb3a22010-01-06 17:53:12 -0700701 assert(ifthen);
702
Brian Paul855d7f52010-01-08 11:32:36 -0700703 if (ifthen->false_block) {
704 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
Brian Paul70b8d592010-01-08 11:01:00 -0700705 /* for each variable, update the Phi node with a (variable, block) pair */
706 for (i = 0; i < flow->num_variables; i++) {
707 assert(*flow->variables[i]);
Brian Paul855d7f52010-01-08 11:32:36 -0700708 LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->false_block, 1);
Brian Paul5208af72010-01-08 12:47:30 -0700709
710 /* replace the variable ref with the phi function */
711 *flow->variables[i] = ifthen->phi[i];
Brian Paulbaeb3a22010-01-06 17:53:12 -0700712 }
Brian Paul70b8d592010-01-08 11:01:00 -0700713 }
714 else {
715 /* no else clause */
Brian Paul855d7f52010-01-08 11:32:36 -0700716 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
Brian Paul70b8d592010-01-08 11:01:00 -0700717 for (i = 0; i < flow->num_variables; i++) {
Brian Paul70b8d592010-01-08 11:01:00 -0700718 assert(*flow->variables[i]);
Brian Paul855d7f52010-01-08 11:32:36 -0700719 LLVMAddIncoming(ifthen->phi[i], flow->variables[i], &ifthen->true_block, 1);
Brian Paul70b8d592010-01-08 11:01:00 -0700720
Brian Paul5208af72010-01-08 12:47:30 -0700721 /* replace the variable ref with the phi function */
722 *flow->variables[i] = ifthen->phi[i];
Brian Paulbaeb3a22010-01-06 17:53:12 -0700723 }
Brian Paulbaeb3a22010-01-06 17:53:12 -0700724 }
725
Brian Paulaf31e652010-01-08 11:20:38 -0700726 FREE(ifthen->phi);
727
Brian Paulbaeb3a22010-01-06 17:53:12 -0700728 /***
Brian Paul70b8d592010-01-08 11:01:00 -0700729 *** Now patch in the various branch instructions.
Brian Paulbaeb3a22010-01-06 17:53:12 -0700730 ***/
731
732 /* Insert the conditional branch instruction at the end of entry_block */
Brian Paul855d7f52010-01-08 11:32:36 -0700733 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->entry_block);
734 if (ifthen->false_block) {
Brian Paulbaeb3a22010-01-06 17:53:12 -0700735 /* we have an else clause */
Brian Paul855d7f52010-01-08 11:32:36 -0700736 LLVMBuildCondBr(ctx->builder, ifthen->condition,
737 ifthen->true_block, ifthen->false_block);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700738 }
739 else {
740 /* no else clause */
Brian Paul855d7f52010-01-08 11:32:36 -0700741 LLVMBuildCondBr(ctx->builder, ifthen->condition,
742 ifthen->true_block, ifthen->merge_block);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700743 }
744
745 /* Append an unconditional Br(anch) instruction on the true_block */
Brian Paul855d7f52010-01-08 11:32:36 -0700746 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->true_block);
747 LLVMBuildBr(ctx->builder, ifthen->merge_block);
748 if (ifthen->false_block) {
Brian Paulbaeb3a22010-01-06 17:53:12 -0700749 /* Append an unconditional Br(anch) instruction on the false_block */
Brian Paul855d7f52010-01-08 11:32:36 -0700750 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->false_block);
751 LLVMBuildBr(ctx->builder, ifthen->merge_block);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700752 }
753
754
Brian Paul855d7f52010-01-08 11:32:36 -0700755 /* Resume building code at end of the ifthen->merge_block */
756 LLVMPositionBuilderAtEnd(ctx->builder, ifthen->merge_block);
Brian Paulbaeb3a22010-01-06 17:53:12 -0700757}