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
33extern "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
43enum lp_exec_mask_break_type {
44   LP_EXEC_MASK_BREAK_TYPE_LOOP,
45   LP_EXEC_MASK_BREAK_TYPE_SWITCH
46};
47
48struct 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
104void lp_exec_mask_function_init(struct lp_exec_mask *mask, int function_idx);
105void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context *bld);
106void lp_exec_mask_fini(struct lp_exec_mask *mask);
107void lp_exec_mask_store(struct lp_exec_mask *mask,
108                        struct lp_build_context *bld_store,
109                        LLVMValueRef val,
110                        LLVMValueRef dst_ptr);
111void lp_exec_mask_update(struct lp_exec_mask *mask);
112void lp_exec_bgnloop_post_phi(struct lp_exec_mask *mask);
113void lp_exec_bgnloop(struct lp_exec_mask *mask, bool load_mask);
114void lp_exec_endloop(struct gallivm_state *gallivm,
115                     struct lp_exec_mask *mask);
116void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
117                            LLVMValueRef val);
118void lp_exec_mask_cond_invert(struct lp_exec_mask *mask);
119void lp_exec_mask_cond_pop(struct lp_exec_mask *mask);
120void lp_exec_continue(struct lp_exec_mask *mask);
121
122void lp_exec_break(struct lp_exec_mask *mask, int *pc, bool break_always);
123
124#ifdef __cplusplus
125}
126#endif
127
128#endif
129