1 /**************************************************************************
2  *
3  * Copyright 2011-2012 Advanced Micro Devices, Inc.
4  * Copyright 2009 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 #ifndef LP_BLD_IR_COMMON_H
30 #define LP_BLD_IR_COMMON_H
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include "gallivm/lp_bld.h"
37 #include "gallivm/lp_bld_limits.h"
38 
39 /* SM 4.0 says that subroutines can nest 32 deep and
40  * we need one more for our main function */
41 #define LP_MAX_NUM_FUNCS 33
42 
43 enum lp_exec_mask_break_type {
44    LP_EXEC_MASK_BREAK_TYPE_LOOP,
45    LP_EXEC_MASK_BREAK_TYPE_SWITCH
46 };
47 
48 struct lp_exec_mask {
49    struct lp_build_context *bld;
50 
51    boolean has_mask;
52    boolean ret_in_main;
53 
54    LLVMTypeRef int_vec_type;
55 
56    LLVMValueRef exec_mask;
57 
58    LLVMValueRef ret_mask;
59    LLVMValueRef cond_mask;
60    LLVMValueRef switch_mask;         /* current switch exec mask */
61    LLVMValueRef cont_mask;
62    LLVMValueRef break_mask;
63 
64    struct function_ctx {
65       int pc;
66       LLVMValueRef ret_mask;
67 
68       LLVMValueRef cond_stack[LP_MAX_TGSI_NESTING];
69       int cond_stack_size;
70 
71       /* keep track if break belongs to switch or loop */
72       enum lp_exec_mask_break_type break_type_stack[LP_MAX_TGSI_NESTING];
73       enum lp_exec_mask_break_type break_type;
74 
75       struct {
76          LLVMValueRef switch_val;
77          LLVMValueRef switch_mask;
78          LLVMValueRef switch_mask_default;
79          boolean switch_in_default;
80          unsigned switch_pc;
81       } switch_stack[LP_MAX_TGSI_NESTING];
82       int switch_stack_size;
83       LLVMValueRef switch_val;
84       LLVMValueRef switch_mask_default; /* reverse of switch mask used for default */
85       boolean switch_in_default;        /* if switch exec is currently in default */
86       unsigned switch_pc;               /* when used points to default or endswitch-1 */
87 
88       LLVMValueRef loop_limiter;
89       LLVMBasicBlockRef loop_block;
90       LLVMValueRef break_var;
91       struct {
92          LLVMBasicBlockRef loop_block;
93          LLVMValueRef cont_mask;
94          LLVMValueRef break_mask;
95          LLVMValueRef break_var;
96       } loop_stack[LP_MAX_TGSI_NESTING];
97       int loop_stack_size;
98       int bgnloop_stack_size;
99 
100    } *function_stack;
101    int function_stack_size;
102 };
103 
104 void lp_exec_mask_function_init(struct lp_exec_mask *mask, int function_idx);
105 void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context *bld);
106 void lp_exec_mask_fini(struct lp_exec_mask *mask);
107 void lp_exec_mask_store(struct lp_exec_mask *mask,
108                         struct lp_build_context *bld_store,
109                         LLVMValueRef val,
110                         LLVMValueRef dst_ptr);
111 void lp_exec_mask_update(struct lp_exec_mask *mask);
112 void lp_exec_bgnloop_post_phi(struct lp_exec_mask *mask);
113 void lp_exec_bgnloop(struct lp_exec_mask *mask, bool load_mask);
114 void lp_exec_endloop(struct gallivm_state *gallivm,
115                      struct lp_exec_mask *mask);
116 void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
117                             LLVMValueRef val);
118 void lp_exec_mask_cond_invert(struct lp_exec_mask *mask);
119 void lp_exec_mask_cond_pop(struct lp_exec_mask *mask);
120 void lp_exec_continue(struct lp_exec_mask *mask);
121 
122 void lp_exec_break(struct lp_exec_mask *mask, int *pc, bool break_always);
123 
124 #ifdef __cplusplus
125 }
126 #endif
127 
128 #endif
129