1 /**************************************************************************
3 * Copyright 2010 Luca Barbieri
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
31 #define check(x) do {if(!(x)) return false;} while(0)
33 bool sm4_link_cf_insns(sm4_program
& program
)
35 if(program
.cf_insn_linked
.size())
38 std::vector
<int> cf_insn_linked
;
39 cf_insn_linked
.resize(program
.insns
.size());
40 memset(&cf_insn_linked
[0], 0xff, cf_insn_linked
.size() * sizeof(int));
41 std::vector
<unsigned> cf_stack
;
42 for(unsigned insn_num
= 0; insn_num
< program
.insns
.size(); ++insn_num
)
45 switch(program
.insns
[insn_num
]->opcode
)
48 cf_stack
.push_back(insn_num
);
50 case SM4_OPCODE_ENDLOOP
:
51 check(!cf_stack
.empty());
53 check(program
.insns
[v
]->opcode
== SM4_OPCODE_LOOP
);
54 cf_insn_linked
[v
] = insn_num
;
55 cf_insn_linked
[insn_num
] = v
;
59 case SM4_OPCODE_SWITCH
:
60 cf_insn_linked
[insn_num
] = insn_num
; // later changed
61 cf_stack
.push_back(insn_num
);
65 check(!cf_stack
.empty());
67 if(program
.insns
[insn_num
]->opcode
== SM4_OPCODE_ELSE
)
68 check(program
.insns
[v
]->opcode
== SM4_OPCODE_IF
);
70 check(program
.insns
[v
]->opcode
== SM4_OPCODE_SWITCH
|| program
.insns
[v
]->opcode
== SM4_OPCODE_CASE
);
71 cf_insn_linked
[insn_num
] = cf_insn_linked
[v
]; // later changed
72 cf_insn_linked
[v
] = insn_num
;
73 cf_stack
.back() = insn_num
;
75 case SM4_OPCODE_ENDSWITCH
:
76 case SM4_OPCODE_ENDIF
:
77 check(!cf_stack
.empty());
79 if(program
.insns
[insn_num
]->opcode
== SM4_OPCODE_ENDIF
)
80 check(program
.insns
[v
]->opcode
== SM4_OPCODE_IF
|| program
.insns
[v
]->opcode
== SM4_OPCODE_ELSE
);
82 check(program
.insns
[v
]->opcode
== SM4_OPCODE_SWITCH
|| program
.insns
[v
]->opcode
== SM4_OPCODE_CASE
);
83 cf_insn_linked
[insn_num
] = cf_insn_linked
[v
];
84 cf_insn_linked
[v
] = insn_num
;
89 check(cf_stack
.empty());
90 program
.cf_insn_linked
.swap(cf_insn_linked
);
94 bool sm4_find_labels(sm4_program
& program
)
96 if(program
.labels_found
)
99 std::vector
<int> labels
;
100 for(unsigned insn_num
= 0; insn_num
< program
.insns
.size(); ++insn_num
)
102 switch(program
.insns
[insn_num
]->opcode
)
104 case SM4_OPCODE_LABEL
:
105 if(program
.insns
[insn_num
]->num_ops
> 0)
107 sm4_op
& op
= *program
.insns
[insn_num
]->ops
[0];
108 if(op
.file
== SM4_FILE_LABEL
&& op
.has_simple_index())
110 unsigned idx
= (unsigned)op
.indices
[0].disp
;
111 if(idx
>= labels
.size())
112 labels
.resize(idx
+ 1);
113 labels
[idx
] = insn_num
;
119 program
.label_to_insn_num
.swap(labels
);
120 program
.labels_found
= true;
124 bool sm4_allocate_resource_sampler_pairs(sm4_program
& program
)
126 if(program
.resource_sampler_slots_assigned
)
129 std::set
<std::pair
<int, int> > pairs
;
130 std::set
<int> resinfos
;
132 for(unsigned insn_num
= 0; insn_num
< program
.insns
.size(); ++insn_num
)
136 for(unsigned i
= 0; i
< program
.insns
[insn_num
]->num_ops
; ++i
)
138 sm4_op
* op
= program
.insns
[insn_num
]->ops
[i
].get();
141 if(op
->file
== SM4_FILE_RESOURCE
)
143 if(!op
->has_simple_index() || resource
>= 0)
145 resource
= (int)op
->indices
[0].disp
;
147 if(op
->file
== SM4_FILE_SAMPLER
)
149 if(!op
->has_simple_index() || sampler
>= 0)
151 sampler
= (int)op
->indices
[0].disp
;
156 unsigned opcode
= program
.insns
[insn_num
]->opcode
;
157 if(opcode
== SM4_OPCODE_LD
|| opcode
== SM4_OPCODE_LD_MS
)
159 if(sampler
>= -1 && resource
>= 0)
160 pairs
.insert(std::make_pair(resource
, sampler
));
161 if(opcode
== SM4_OPCODE_RESINFO
)
162 resinfos
.insert(resource
);
165 for(std::set
<std::pair
<int, int> >::iterator i
= pairs
.begin(); i
!= pairs
.end(); ++i
)
167 program
.resource_sampler_to_slot
[*i
] = program
.slot_to_resource
.size();
168 if(!program
.resource_to_slot
.count(i
->first
))
170 program
.resource_to_slot
[i
->first
] = program
.slot_to_resource
.size();
171 resinfos
.erase(i
->first
);
173 program
.slot_to_resource
.push_back(i
->first
);
174 program
.slot_to_sampler
.push_back(i
->second
);
177 for(std::set
<int>::iterator i
= resinfos
.begin(); i
!= resinfos
.end(); ++i
)
179 program
.resource_sampler_to_slot
[std::make_pair(*i
, -1)] = program
.slot_to_resource
.size();
180 program
.resource_to_slot
[*i
] = program
.slot_to_resource
.size();
181 program
.slot_to_resource
.push_back(*i
);
182 program
.slot_to_sampler
.push_back(-1);
184 program
.resource_sampler_slots_assigned
= true;