| 170 | } |
| 171 | |
| 172 | uint32_t LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac, |
| 173 | uint32_t curr_type_id, |
| 174 | uint32_t* offset, bool* no_loc, |
| 175 | bool is_patch, bool input) { |
| 176 | analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); |
| 177 | analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr(); |
| 178 | // For tesc, tese and geom input variables, and tesc output variables, |
| 179 | // first array index does not contribute to offset. |
| 180 | auto stage = context()->GetStage(); |
| 181 | bool skip_first_index = false; |
| 182 | if ((input && (stage == spv::ExecutionModel::TessellationControl || |
| 183 | stage == spv::ExecutionModel::TessellationEvaluation || |
| 184 | stage == spv::ExecutionModel::Geometry)) || |
| 185 | (!input && stage == spv::ExecutionModel::TessellationControl)) |
| 186 | skip_first_index = !is_patch; |
| 187 | uint32_t ocnt = 0; |
| 188 | ac->WhileEachInOperand([this, &ocnt, def_use_mgr, deco_mgr, &curr_type_id, |
| 189 | offset, no_loc, |
| 190 | skip_first_index](const uint32_t* opnd) { |
| 191 | if (ocnt >= 1) { |
| 192 | // Skip first index's contribution to offset if indicated |
| 193 | Instruction* curr_type_inst = def_use_mgr->GetDef(curr_type_id); |
| 194 | if (ocnt == 1 && skip_first_index) { |
| 195 | assert(curr_type_inst->opcode() == spv::Op::OpTypeArray && |
| 196 | "unexpected wrapper type"); |
| 197 | const uint32_t kArrayElementTypeInIdx = 0; |
| 198 | curr_type_id = |
| 199 | curr_type_inst->GetSingleWordInOperand(kArrayElementTypeInIdx); |
| 200 | ocnt++; |
| 201 | return true; |
| 202 | } |
| 203 | // If any non-constant index, mark the entire current object and return. |
| 204 | auto idx_inst = def_use_mgr->GetDef(*opnd); |
| 205 | if (idx_inst->opcode() != spv::Op::OpConstant) return false; |
| 206 | // If current type is struct, look for location decoration on member and |
| 207 | // reset offset if found. |
| 208 | auto index = idx_inst->GetSingleWordInOperand(0); |
| 209 | if (curr_type_inst->opcode() == spv::Op::OpTypeStruct) { |
| 210 | uint32_t loc = 0; |
| 211 | bool no_mem_loc = deco_mgr->WhileEachDecoration( |
| 212 | curr_type_id, uint32_t(spv::Decoration::Location), |
| 213 | [&loc, index, no_loc](const Instruction& deco) { |
| 214 | assert(deco.opcode() == spv::Op::OpMemberDecorate && |
| 215 | "unexpected decoration"); |
| 216 | if (deco.GetSingleWordInOperand(kOpDecorateMemberMemberInIdx) == |
| 217 | index) { |
| 218 | loc = |
| 219 | deco.GetSingleWordInOperand(kOpDecorateMemberLocationInIdx); |
| 220 | *no_loc = false; |
| 221 | return false; |
| 222 | } |
| 223 | return true; |
| 224 | }); |
| 225 | if (!no_mem_loc) { |
| 226 | *offset = loc; |
| 227 | curr_type_id = curr_type_inst->GetSingleWordInOperand(index); |
| 228 | ocnt++; |
| 229 | return true; |
no test coverage detected