Coverage Report

Created: 2026-01-09 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/shaderc/third_party/spirv-tools/source/opt/constants.cpp
Line
Count
Source
1
// Copyright (c) 2017 Google Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "source/opt/constants.h"
16
17
#include <vector>
18
19
#include "source/opt/ir_context.h"
20
21
namespace spvtools {
22
namespace opt {
23
namespace analysis {
24
25
232
float Constant::GetFloat() const {
26
232
  assert(type()->AsFloat() != nullptr && type()->AsFloat()->width() == 32);
27
28
232
  if (const FloatConstant* fc = AsFloatConstant()) {
29
232
    return fc->GetFloatValue();
30
232
  } else {
31
0
    assert(AsNullConstant() && "Must be a floating point constant.");
32
0
    return 0.0f;
33
0
  }
34
232
}
35
36
0
double Constant::GetDouble() const {
37
0
  assert(type()->AsFloat() != nullptr && type()->AsFloat()->width() == 64);
38
39
0
  if (const FloatConstant* fc = AsFloatConstant()) {
40
0
    return fc->GetDoubleValue();
41
0
  } else {
42
0
    assert(AsNullConstant() && "Must be a floating point constant.");
43
0
    return 0.0;
44
0
  }
45
0
}
46
47
0
double Constant::GetValueAsDouble() const {
48
0
  assert(type()->AsFloat() != nullptr);
49
0
  if (type()->AsFloat()->width() == 32) {
50
0
    return GetFloat();
51
0
  } else {
52
0
    assert(type()->AsFloat()->width() == 64);
53
0
    return GetDouble();
54
0
  }
55
0
}
56
57
108
uint32_t Constant::GetU32() const {
58
108
  assert(type()->AsInteger() != nullptr);
59
108
  assert(type()->AsInteger()->width() == 32);
60
61
108
  if (const IntConstant* ic = AsIntConstant()) {
62
108
    return ic->GetU32BitValue();
63
108
  } else {
64
0
    assert(AsNullConstant() && "Must be an integer constant.");
65
0
    return 0u;
66
0
  }
67
108
}
68
69
44
uint64_t Constant::GetU64() const {
70
44
  assert(type()->AsInteger() != nullptr);
71
44
  assert(type()->AsInteger()->width() == 64);
72
73
44
  if (const IntConstant* ic = AsIntConstant()) {
74
44
    return ic->GetU64BitValue();
75
44
  } else {
76
0
    assert(AsNullConstant() && "Must be an integer constant.");
77
0
    return 0u;
78
0
  }
79
44
}
80
81
0
int32_t Constant::GetS32() const {
82
0
  assert(type()->AsInteger() != nullptr);
83
0
  assert(type()->AsInteger()->width() == 32);
84
85
0
  if (const IntConstant* ic = AsIntConstant()) {
86
0
    return ic->GetS32BitValue();
87
0
  } else {
88
0
    assert(AsNullConstant() && "Must be an integer constant.");
89
0
    return 0;
90
0
  }
91
0
}
92
93
0
int64_t Constant::GetS64() const {
94
0
  assert(type()->AsInteger() != nullptr);
95
0
  assert(type()->AsInteger()->width() == 64);
96
97
0
  if (const IntConstant* ic = AsIntConstant()) {
98
0
    return ic->GetS64BitValue();
99
0
  } else {
100
0
    assert(AsNullConstant() && "Must be an integer constant.");
101
0
    return 0;
102
0
  }
103
0
}
104
105
3.47k
uint64_t Constant::GetZeroExtendedValue() const {
106
3.47k
  const auto* int_type = type()->AsInteger();
107
3.47k
  assert(int_type != nullptr);
108
3.47k
  const auto width = int_type->width();
109
3.47k
  assert(width <= 64);
110
111
3.47k
  uint64_t value = 0;
112
3.47k
  if (const IntConstant* ic = AsIntConstant()) {
113
3.47k
    if (width <= 32) {
114
3.47k
      value = ic->GetU32BitValue();
115
3.47k
    } else {
116
0
      value = ic->GetU64BitValue();
117
0
    }
118
3.47k
  } else {
119
0
    assert(AsNullConstant() && "Must be an integer constant.");
120
0
  }
121
3.47k
  return value;
122
3.47k
}
123
124
2.04k
int64_t Constant::GetSignExtendedValue() const {
125
2.04k
  const auto* int_type = type()->AsInteger();
126
2.04k
  assert(int_type != nullptr);
127
2.04k
  const auto width = int_type->width();
128
2.04k
  assert(width <= 64);
129
130
2.04k
  int64_t value = 0;
131
2.04k
  if (const IntConstant* ic = AsIntConstant()) {
132
2.04k
    if (width <= 32) {
133
      // Let the C++ compiler do the sign extension.
134
2.04k
      value = int64_t(ic->GetS32BitValue());
135
2.04k
    } else {
136
4
      value = ic->GetS64BitValue();
137
4
    }
138
2.04k
  } else {
139
0
    assert(AsNullConstant() && "Must be an integer constant.");
140
0
  }
141
2.04k
  return value;
142
2.04k
}
143
144
228
ConstantManager::ConstantManager(IRContext* ctx) : ctx_(ctx) {
145
  // Populate the constant table with values from constant declarations in the
146
  // module.  The values of each OpConstant declaration is the identity
147
  // assignment (i.e., each constant is its own value).
148
2.89k
  for (const auto& inst : ctx_->module()->GetConstants()) {
149
2.89k
    MapInst(inst);
150
2.89k
  }
151
228
}
152
153
5.03k
Type* ConstantManager::GetType(const Instruction* inst) const {
154
5.03k
  return context()->get_type_mgr()->GetType(inst->type_id());
155
5.03k
}
156
157
std::vector<const Constant*> ConstantManager::GetOperandConstants(
158
62.9k
    const Instruction* inst) const {
159
62.9k
  std::vector<const Constant*> constants;
160
62.9k
  constants.reserve(inst->NumInOperands());
161
198k
  for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
162
135k
    const Operand* operand = &inst->GetInOperand(i);
163
135k
    if (operand->type != SPV_OPERAND_TYPE_ID) {
164
17.9k
      constants.push_back(nullptr);
165
117k
    } else {
166
117k
      uint32_t id = operand->words[0];
167
117k
      const analysis::Constant* constant = FindDeclaredConstant(id);
168
117k
      constants.push_back(constant);
169
117k
    }
170
135k
  }
171
62.9k
  return constants;
172
62.9k
}
173
174
uint32_t ConstantManager::FindDeclaredConstant(const Constant* c,
175
1.43k
                                               uint32_t type_id) const {
176
1.43k
  c = FindConstant(c);
177
1.43k
  if (c == nullptr) {
178
0
    return 0;
179
0
  }
180
181
1.43k
  for (auto range = const_val_to_id_.equal_range(c);
182
1.43k
       range.first != range.second; ++range.first) {
183
1.31k
    Instruction* const_def =
184
1.31k
        context()->get_def_use_mgr()->GetDef(range.first->second);
185
1.31k
    if (type_id == 0 || const_def->type_id() == type_id) {
186
1.31k
      return range.first->second;
187
1.31k
    }
188
1.31k
  }
189
124
  return 0;
190
1.43k
}
191
192
std::vector<const Constant*> ConstantManager::GetConstantsFromIds(
193
598
    const std::vector<uint32_t>& ids) const {
194
598
  std::vector<const Constant*> constants;
195
1.73k
  for (uint32_t id : ids) {
196
1.73k
    if (const Constant* c = FindDeclaredConstant(id)) {
197
1.73k
      constants.push_back(c);
198
1.73k
    } else {
199
0
      return {};
200
0
    }
201
1.73k
  }
202
598
  return constants;
203
598
}
204
205
Instruction* ConstantManager::BuildInstructionAndAddToModule(
206
124
    const Constant* new_const, Module::inst_iterator* pos, uint32_t type_id) {
207
  // TODO(1841): Handle id overflow.
208
124
  uint32_t new_id = context()->TakeNextId();
209
124
  if (new_id == 0) {
210
0
    return nullptr;
211
0
  }
212
213
124
  auto new_inst = CreateInstruction(new_id, new_const, type_id);
214
124
  if (!new_inst) {
215
0
    return nullptr;
216
0
  }
217
124
  auto* new_inst_ptr = new_inst.get();
218
124
  *pos = pos->InsertBefore(std::move(new_inst));
219
124
  ++(*pos);
220
124
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
221
124
    context()->get_def_use_mgr()->AnalyzeInstDefUse(new_inst_ptr);
222
124
  MapConstantToInst(new_const, new_inst_ptr);
223
124
  return new_inst_ptr;
224
124
}
225
226
Instruction* ConstantManager::GetDefiningInstruction(
227
952
    const Constant* c, uint32_t type_id, Module::inst_iterator* pos) {
228
952
  uint32_t decl_id = FindDeclaredConstant(c, type_id);
229
952
  if (decl_id == 0) {
230
124
    auto iter = context()->types_values_end();
231
124
    if (pos == nullptr) pos = &iter;
232
124
    return BuildInstructionAndAddToModule(c, pos, type_id);
233
828
  } else {
234
828
    auto def = context()->get_def_use_mgr()->GetDef(decl_id);
235
828
    assert(def != nullptr);
236
828
    assert((type_id == 0 || def->type_id() == type_id) &&
237
828
           "This constant already has an instruction with a different type.");
238
828
    return def;
239
828
  }
240
952
}
241
242
std::unique_ptr<Constant> ConstantManager::CreateConstant(
243
5.66k
    const Type* type, const std::vector<uint32_t>& literal_words_or_ids) const {
244
5.66k
  if (literal_words_or_ids.size() == 0) {
245
    // Constant declared with OpConstantNull
246
0
    return MakeUnique<NullConstant>(type);
247
5.66k
  } else if (auto* bt = type->AsBool()) {
248
190
    assert(literal_words_or_ids.size() == 1 &&
249
190
           "Bool constant should be declared with one operand");
250
190
    return MakeUnique<BoolConstant>(bt, literal_words_or_ids.front());
251
5.47k
  } else if (auto* it = type->AsInteger()) {
252
3.56k
    return MakeUnique<IntConstant>(it, literal_words_or_ids);
253
3.56k
  } else if (auto* ft = type->AsFloat()) {
254
1.31k
    return MakeUnique<FloatConstant>(ft, literal_words_or_ids);
255
1.31k
  } else if (auto* vt = type->AsVector()) {
256
468
    auto components = GetConstantsFromIds(literal_words_or_ids);
257
468
    if (components.empty()) return nullptr;
258
    // All components of VectorConstant must be of type Bool, Integer or Float.
259
468
    if (!std::all_of(components.begin(), components.end(),
260
1.34k
                     [](const Constant* c) {
261
1.34k
                       if (c->type()->AsBool() || c->type()->AsInteger() ||
262
1.34k
                           c->type()->AsFloat()) {
263
1.34k
                         return true;
264
1.34k
                       } else {
265
0
                         return false;
266
0
                       }
267
1.34k
                     }))
268
0
      return nullptr;
269
    // All components of VectorConstant must be in the same type.
270
468
    const auto* component_type = components.front()->type();
271
468
    if (!std::all_of(components.begin(), components.end(),
272
1.34k
                     [&component_type](const Constant* c) {
273
1.34k
                       if (c->type() == component_type) return true;
274
0
                       return false;
275
1.34k
                     }))
276
0
      return nullptr;
277
468
    return MakeUnique<VectorConstant>(vt, components);
278
468
  } else if (auto* mt = type->AsMatrix()) {
279
18
    auto components = GetConstantsFromIds(literal_words_or_ids);
280
18
    if (components.empty()) return nullptr;
281
18
    return MakeUnique<MatrixConstant>(mt, components);
282
112
  } else if (auto* st = type->AsStruct()) {
283
104
    auto components = GetConstantsFromIds(literal_words_or_ids);
284
104
    if (components.empty()) return nullptr;
285
104
    return MakeUnique<StructConstant>(st, components);
286
104
  } else if (auto* at = type->AsArray()) {
287
8
    auto components = GetConstantsFromIds(literal_words_or_ids);
288
8
    if (components.empty()) return nullptr;
289
8
    return MakeUnique<ArrayConstant>(at, components);
290
8
  } else {
291
0
    return nullptr;
292
0
  }
293
5.66k
}
294
295
4.94k
const Constant* ConstantManager::GetConstantFromInst(const Instruction* inst) {
296
4.94k
  std::vector<uint32_t> literal_words_or_ids;
297
298
  // Collect the constant defining literals or component ids.
299
10.7k
  for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
300
5.85k
    literal_words_or_ids.insert(literal_words_or_ids.end(),
301
5.85k
                                inst->GetInOperand(i).words.begin(),
302
5.85k
                                inst->GetInOperand(i).words.end());
303
5.85k
  }
304
305
4.94k
  switch (inst->opcode()) {
306
    // OpConstant{True|False} have the value embedded in the opcode. So they
307
    // are not handled by the for-loop above. Here we add the value explicitly.
308
16
    case spv::Op::OpConstantTrue:
309
16
      literal_words_or_ids.push_back(true);
310
16
      break;
311
12
    case spv::Op::OpConstantFalse:
312
12
      literal_words_or_ids.push_back(false);
313
12
      break;
314
0
    case spv::Op::OpConstantNull:
315
4.39k
    case spv::Op::OpConstant:
316
4.88k
    case spv::Op::OpConstantComposite:
317
4.88k
    case spv::Op::OpSpecConstantComposite:
318
4.88k
    case spv::Op::OpSpecConstantCompositeReplicateEXT:
319
4.88k
      break;
320
36
    default:
321
36
      return nullptr;
322
4.94k
  }
323
324
4.91k
  return GetConstant(GetType(inst), literal_words_or_ids);
325
4.94k
}
326
327
std::unique_ptr<Instruction> ConstantManager::CreateInstruction(
328
124
    uint32_t id, const Constant* c, uint32_t type_id) const {
329
124
  uint32_t type =
330
124
      (type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id;
331
124
  if (c->AsNullConstant()) {
332
0
    return MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, type, id,
333
0
                                   std::initializer_list<Operand>{});
334
124
  } else if (const BoolConstant* bc = c->AsBoolConstant()) {
335
52
    return MakeUnique<Instruction>(
336
52
        context(),
337
52
        bc->value() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse, type,
338
52
        id, std::initializer_list<Operand>{});
339
72
  } else if (const IntConstant* ic = c->AsIntConstant()) {
340
18
    return MakeUnique<Instruction>(
341
18
        context(), spv::Op::OpConstant, type, id,
342
18
        std::initializer_list<Operand>{
343
18
            Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
344
18
                    ic->words())});
345
54
  } else if (const FloatConstant* fc = c->AsFloatConstant()) {
346
0
    return MakeUnique<Instruction>(
347
0
        context(), spv::Op::OpConstant, type, id,
348
0
        std::initializer_list<Operand>{
349
0
            Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
350
0
                    fc->words())});
351
54
  } else if (const CompositeConstant* cc = c->AsCompositeConstant()) {
352
54
    return CreateCompositeInstruction(id, cc, type_id);
353
54
  } else {
354
0
    return nullptr;
355
0
  }
356
124
}
357
358
std::unique_ptr<Instruction> ConstantManager::CreateCompositeInstruction(
359
54
    uint32_t result_id, const CompositeConstant* cc, uint32_t type_id) const {
360
54
  std::vector<Operand> operands;
361
54
  Instruction* type_inst = context()->get_def_use_mgr()->GetDef(type_id);
362
54
  uint32_t component_index = 0;
363
180
  for (const Constant* component_const : cc->GetComponents()) {
364
180
    uint32_t component_type_id = 0;
365
180
    if (type_inst && type_inst->opcode() == spv::Op::OpTypeStruct) {
366
144
      component_type_id = type_inst->GetSingleWordInOperand(component_index);
367
144
    } else if (type_inst && type_inst->opcode() == spv::Op::OpTypeArray) {
368
0
      component_type_id = type_inst->GetSingleWordInOperand(0);
369
0
    }
370
180
    uint32_t id = FindDeclaredConstant(component_const, component_type_id);
371
372
180
    if (id == 0) {
373
      // Cannot get the id of the component constant, while all components
374
      // should have been added to the module prior to the composite constant.
375
      // Cannot create OpConstantComposite instruction in this case.
376
0
      return nullptr;
377
0
    }
378
180
    operands.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
379
180
                          std::initializer_list<uint32_t>{id});
380
180
    component_index++;
381
180
  }
382
54
  uint32_t type =
383
54
      (type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id;
384
54
  return MakeUnique<Instruction>(context(), spv::Op::OpConstantComposite, type,
385
54
                                 result_id, std::move(operands));
386
54
}
387
388
const Constant* ConstantManager::GetConstant(
389
5.66k
    const Type* type, const std::vector<uint32_t>& literal_words_or_ids) {
390
5.66k
  auto cst = CreateConstant(type, literal_words_or_ids);
391
5.66k
  return cst ? RegisterConstant(std::move(cst)) : nullptr;
392
5.66k
}
393
394
0
const Constant* ConstantManager::GetNullCompositeConstant(const Type* type) {
395
0
  std::vector<uint32_t> literal_words_or_id;
396
397
0
  if (type->AsVector()) {
398
0
    const Type* element_type = type->AsVector()->element_type();
399
0
    const uint32_t null_id = GetNullConstId(element_type);
400
0
    const uint32_t element_count = type->AsVector()->element_count();
401
0
    for (uint32_t i = 0; i < element_count; i++) {
402
0
      literal_words_or_id.push_back(null_id);
403
0
    }
404
0
  } else if (type->AsMatrix()) {
405
0
    const Type* element_type = type->AsMatrix()->element_type();
406
0
    const uint32_t null_id = GetNullConstId(element_type);
407
0
    const uint32_t element_count = type->AsMatrix()->element_count();
408
0
    for (uint32_t i = 0; i < element_count; i++) {
409
0
      literal_words_or_id.push_back(null_id);
410
0
    }
411
0
  } else if (type->AsStruct()) {
412
    // TODO (sfricke-lunarg) add proper struct support
413
0
    return nullptr;
414
0
  } else if (type->AsArray()) {
415
0
    const Type* element_type = type->AsArray()->element_type();
416
0
    const uint32_t null_id = GetNullConstId(element_type);
417
0
    assert(type->AsArray()->length_info().words[0] ==
418
0
               analysis::Array::LengthInfo::kConstant &&
419
0
           "unexpected array length");
420
0
    const uint32_t element_count = type->AsArray()->length_info().words[0];
421
0
    for (uint32_t i = 0; i < element_count; i++) {
422
0
      literal_words_or_id.push_back(null_id);
423
0
    }
424
0
  } else {
425
0
    return nullptr;
426
0
  }
427
428
0
  return GetConstant(type, literal_words_or_id);
429
0
}
430
431
const Constant* ConstantManager::GetNumericVectorConstantWithWords(
432
0
    const Vector* type, const std::vector<uint32_t>& literal_words) {
433
0
  const auto* element_type = type->element_type();
434
0
  uint32_t words_per_element = 0;
435
0
  if (const auto* float_type = element_type->AsFloat())
436
0
    words_per_element = float_type->width() / 32;
437
0
  else if (const auto* int_type = element_type->AsInteger())
438
0
    words_per_element = int_type->width() / 32;
439
0
  else if (element_type->AsBool() != nullptr)
440
0
    words_per_element = 1;
441
442
0
  if (words_per_element != 1 && words_per_element != 2) return nullptr;
443
444
0
  if (words_per_element * type->element_count() !=
445
0
      static_cast<uint32_t>(literal_words.size())) {
446
0
    return nullptr;
447
0
  }
448
449
0
  std::vector<uint32_t> element_ids;
450
0
  for (uint32_t i = 0; i < type->element_count(); ++i) {
451
0
    auto first_word = literal_words.begin() + (words_per_element * i);
452
0
    std::vector<uint32_t> const_data(first_word,
453
0
                                     first_word + words_per_element);
454
0
    const analysis::Constant* element_constant =
455
0
        GetConstant(element_type, const_data);
456
0
    auto element_id = GetDefiningInstruction(element_constant)->result_id();
457
0
    element_ids.push_back(element_id);
458
0
  }
459
460
0
  return GetConstant(type, element_ids);
461
0
}
462
463
0
uint32_t ConstantManager::GetFloatConstId(float val) {
464
0
  const Constant* c = GetFloatConst(val);
465
0
  Instruction* inst = GetDefiningInstruction(c);
466
0
  if (inst == nullptr) return 0;
467
0
  return inst->result_id();
468
0
}
469
470
0
const Constant* ConstantManager::GetFloatConst(float val) {
471
0
  Type* float_type = context()->get_type_mgr()->GetFloatType();
472
0
  utils::FloatProxy<float> v(val);
473
0
  const Constant* c = GetConstant(float_type, v.GetWords());
474
0
  return c;
475
0
}
476
477
0
uint32_t ConstantManager::GetDoubleConstId(double val) {
478
0
  const Constant* c = GetDoubleConst(val);
479
0
  Instruction* inst = GetDefiningInstruction(c);
480
0
  if (inst == nullptr) return 0;
481
0
  return inst->result_id();
482
0
}
483
484
0
const Constant* ConstantManager::GetDoubleConst(double val) {
485
0
  Type* float_type = context()->get_type_mgr()->GetDoubleType();
486
0
  utils::FloatProxy<double> v(val);
487
0
  const Constant* c = GetConstant(float_type, v.GetWords());
488
0
  return c;
489
0
}
490
491
0
uint32_t ConstantManager::GetSIntConstId(int32_t val) {
492
0
  Type* sint_type = context()->get_type_mgr()->GetSIntType();
493
0
  const Constant* c = GetConstant(sint_type, {static_cast<uint32_t>(val)});
494
0
  return GetDefiningInstruction(c)->result_id();
495
0
}
496
497
const Constant* ConstantManager::GetIntConst(uint64_t val, int32_t bitWidth,
498
80
                                             bool isSigned) {
499
80
  Type* int_type = context()->get_type_mgr()->GetIntType(bitWidth, isSigned);
500
501
80
  if (isSigned) {
502
    // Sign extend the value.
503
80
    int32_t num_of_bit_to_ignore = 64 - bitWidth;
504
80
    val = static_cast<int64_t>(val << num_of_bit_to_ignore) >>
505
80
          num_of_bit_to_ignore;
506
80
  } else if (bitWidth < 64) {
507
    // Clear the upper bit that are not used.
508
0
    uint64_t mask = ((1ull << bitWidth) - 1);
509
0
    val &= mask;
510
0
  }
511
512
80
  if (bitWidth <= 32) {
513
80
    return GetConstant(int_type, {static_cast<uint32_t>(val)});
514
80
  }
515
516
  // If the value is more than 32-bit, we need to split the operands into two
517
  // 32-bit integers.
518
0
  return GetConstant(
519
0
      int_type, {static_cast<uint32_t>(val), static_cast<uint32_t>(val >> 32)});
520
80
}
521
522
0
uint32_t ConstantManager::GetUIntConstId(uint32_t val) {
523
0
  Type* uint_type = context()->get_type_mgr()->GetUIntType();
524
0
  const Constant* c = GetConstant(uint_type, {val});
525
0
  return GetDefiningInstruction(c)->result_id();
526
0
}
527
528
0
uint32_t ConstantManager::GetNullConstId(const Type* type) {
529
0
  const Constant* c = GetConstant(type, {});
530
0
  return GetDefiningInstruction(c)->result_id();
531
0
}
532
533
const Constant* ConstantManager::GenerateIntegerConstant(
534
162
    const analysis::Integer* integer_type, uint64_t result) {
535
162
  assert(integer_type != nullptr);
536
537
162
  std::vector<uint32_t> words;
538
162
  if (integer_type->width() == 64) {
539
    // In the 64-bit case, two words are needed to represent the value.
540
0
    words = {static_cast<uint32_t>(result),
541
0
             static_cast<uint32_t>(result >> 32)};
542
162
  } else {
543
    // In all other cases, only a single word is needed.
544
162
    assert(integer_type->width() <= 32);
545
162
    if (integer_type->IsSigned()) {
546
162
      result = utils::SignExtendValue(result, integer_type->width());
547
162
    } else {
548
0
      result = utils::ZeroExtendValue(result, integer_type->width());
549
0
    }
550
162
    words = {static_cast<uint32_t>(result)};
551
162
  }
552
162
  return GetConstant(integer_type, words);
553
162
}
554
555
std::vector<const analysis::Constant*> Constant::GetVectorComponents(
556
0
    analysis::ConstantManager* const_mgr) const {
557
0
  std::vector<const analysis::Constant*> components;
558
0
  const analysis::VectorConstant* a = this->AsVectorConstant();
559
0
  const analysis::Vector* vector_type = this->type()->AsVector();
560
0
  assert(vector_type != nullptr);
561
0
  if (a != nullptr) {
562
0
    for (uint32_t i = 0; i < vector_type->element_count(); ++i) {
563
0
      components.push_back(a->GetComponents()[i]);
564
0
    }
565
0
  } else {
566
0
    const analysis::Type* element_type = vector_type->element_type();
567
0
    const analysis::Constant* element_null_const =
568
0
        const_mgr->GetConstant(element_type, {});
569
0
    for (uint32_t i = 0; i < vector_type->element_count(); ++i) {
570
0
      components.push_back(element_null_const);
571
0
    }
572
0
  }
573
0
  return components;
574
0
}
575
576
}  // namespace analysis
577
}  // namespace opt
578
}  // namespace spvtools