Coverage Report

Created: 2025-12-03 06:45

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
1.85k
float Constant::GetFloat() const {
26
1.85k
  assert(type()->AsFloat() != nullptr && type()->AsFloat()->width() == 32);
27
28
1.85k
  if (const FloatConstant* fc = AsFloatConstant()) {
29
1.85k
    return fc->GetFloatValue();
30
1.85k
  } else {
31
0
    assert(AsNullConstant() && "Must be a floating point constant.");
32
0
    return 0.0f;
33
0
  }
34
1.85k
}
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
852
uint32_t Constant::GetU32() const {
58
852
  assert(type()->AsInteger() != nullptr);
59
852
  assert(type()->AsInteger()->width() == 32);
60
61
852
  if (const IntConstant* ic = AsIntConstant()) {
62
852
    return ic->GetU32BitValue();
63
852
  } else {
64
0
    assert(AsNullConstant() && "Must be an integer constant.");
65
0
    return 0u;
66
0
  }
67
852
}
68
69
100
uint64_t Constant::GetU64() const {
70
100
  assert(type()->AsInteger() != nullptr);
71
100
  assert(type()->AsInteger()->width() == 64);
72
73
100
  if (const IntConstant* ic = AsIntConstant()) {
74
100
    return ic->GetU64BitValue();
75
100
  } else {
76
0
    assert(AsNullConstant() && "Must be an integer constant.");
77
0
    return 0u;
78
0
  }
79
100
}
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
12.9k
uint64_t Constant::GetZeroExtendedValue() const {
106
12.9k
  const auto* int_type = type()->AsInteger();
107
12.9k
  assert(int_type != nullptr);
108
12.9k
  const auto width = int_type->width();
109
12.9k
  assert(width <= 64);
110
111
12.9k
  uint64_t value = 0;
112
12.9k
  if (const IntConstant* ic = AsIntConstant()) {
113
12.9k
    if (width <= 32) {
114
12.9k
      value = ic->GetU32BitValue();
115
12.9k
    } else {
116
0
      value = ic->GetU64BitValue();
117
0
    }
118
12.9k
  } else {
119
0
    assert(AsNullConstant() && "Must be an integer constant.");
120
0
  }
121
12.9k
  return value;
122
12.9k
}
123
124
8.29k
int64_t Constant::GetSignExtendedValue() const {
125
8.29k
  const auto* int_type = type()->AsInteger();
126
8.29k
  assert(int_type != nullptr);
127
8.29k
  const auto width = int_type->width();
128
8.29k
  assert(width <= 64);
129
130
8.29k
  int64_t value = 0;
131
8.29k
  if (const IntConstant* ic = AsIntConstant()) {
132
8.29k
    if (width <= 32) {
133
      // Let the C++ compiler do the sign extension.
134
8.29k
      value = int64_t(ic->GetS32BitValue());
135
8.29k
    } else {
136
4
      value = ic->GetS64BitValue();
137
4
    }
138
8.29k
  } else {
139
0
    assert(AsNullConstant() && "Must be an integer constant.");
140
0
  }
141
8.29k
  return value;
142
8.29k
}
143
144
1.42k
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
15.3k
  for (const auto& inst : ctx_->module()->GetConstants()) {
149
15.3k
    MapInst(inst);
150
15.3k
  }
151
1.42k
}
152
153
25.4k
Type* ConstantManager::GetType(const Instruction* inst) const {
154
25.4k
  return context()->get_type_mgr()->GetType(inst->type_id());
155
25.4k
}
156
157
std::vector<const Constant*> ConstantManager::GetOperandConstants(
158
317k
    const Instruction* inst) const {
159
317k
  std::vector<const Constant*> constants;
160
317k
  constants.reserve(inst->NumInOperands());
161
1.20M
  for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
162
885k
    const Operand* operand = &inst->GetInOperand(i);
163
885k
    if (operand->type != SPV_OPERAND_TYPE_ID) {
164
165k
      constants.push_back(nullptr);
165
719k
    } else {
166
719k
      uint32_t id = operand->words[0];
167
719k
      const analysis::Constant* constant = FindDeclaredConstant(id);
168
719k
      constants.push_back(constant);
169
719k
    }
170
885k
  }
171
317k
  return constants;
172
317k
}
173
174
uint32_t ConstantManager::FindDeclaredConstant(const Constant* c,
175
8.66k
                                               uint32_t type_id) const {
176
8.66k
  c = FindConstant(c);
177
8.66k
  if (c == nullptr) {
178
0
    return 0;
179
0
  }
180
181
8.66k
  for (auto range = const_val_to_id_.equal_range(c);
182
8.66k
       range.first != range.second; ++range.first) {
183
7.58k
    Instruction* const_def =
184
7.58k
        context()->get_def_use_mgr()->GetDef(range.first->second);
185
7.58k
    if (type_id == 0 || const_def->type_id() == type_id) {
186
7.58k
      return range.first->second;
187
7.58k
    }
188
7.58k
  }
189
1.08k
  return 0;
190
8.66k
}
191
192
std::vector<const Constant*> ConstantManager::GetConstantsFromIds(
193
1.90k
    const std::vector<uint32_t>& ids) const {
194
1.90k
  std::vector<const Constant*> constants;
195
5.42k
  for (uint32_t id : ids) {
196
5.42k
    if (const Constant* c = FindDeclaredConstant(id)) {
197
5.42k
      constants.push_back(c);
198
5.42k
    } else {
199
4
      return {};
200
4
    }
201
5.42k
  }
202
1.90k
  return constants;
203
1.90k
}
204
205
Instruction* ConstantManager::BuildInstructionAndAddToModule(
206
1.08k
    const Constant* new_const, Module::inst_iterator* pos, uint32_t type_id) {
207
  // TODO(1841): Handle id overflow.
208
1.08k
  uint32_t new_id = context()->TakeNextId();
209
1.08k
  if (new_id == 0) {
210
0
    return nullptr;
211
0
  }
212
213
1.08k
  auto new_inst = CreateInstruction(new_id, new_const, type_id);
214
1.08k
  if (!new_inst) {
215
0
    return nullptr;
216
0
  }
217
1.08k
  auto* new_inst_ptr = new_inst.get();
218
1.08k
  *pos = pos->InsertBefore(std::move(new_inst));
219
1.08k
  ++(*pos);
220
1.08k
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
221
1.08k
    context()->get_def_use_mgr()->AnalyzeInstDefUse(new_inst_ptr);
222
1.08k
  MapConstantToInst(new_const, new_inst_ptr);
223
1.08k
  return new_inst_ptr;
224
1.08k
}
225
226
Instruction* ConstantManager::GetDefiningInstruction(
227
6.42k
    const Constant* c, uint32_t type_id, Module::inst_iterator* pos) {
228
6.42k
  uint32_t decl_id = FindDeclaredConstant(c, type_id);
229
6.42k
  if (decl_id == 0) {
230
1.08k
    auto iter = context()->types_values_end();
231
1.08k
    if (pos == nullptr) pos = &iter;
232
1.08k
    return BuildInstructionAndAddToModule(c, pos, type_id);
233
5.34k
  } else {
234
5.34k
    auto def = context()->get_def_use_mgr()->GetDef(decl_id);
235
5.34k
    assert(def != nullptr);
236
5.34k
    assert((type_id == 0 || def->type_id() == type_id) &&
237
5.34k
           "This constant already has an instruction with a different type.");
238
5.34k
    return def;
239
5.34k
  }
240
6.42k
}
241
242
std::unique_ptr<Constant> ConstantManager::CreateConstant(
243
30.3k
    const Type* type, const std::vector<uint32_t>& literal_words_or_ids) const {
244
30.3k
  if (literal_words_or_ids.size() == 0) {
245
    // Constant declared with OpConstantNull
246
8
    return MakeUnique<NullConstant>(type);
247
30.3k
  } else if (auto* bt = type->AsBool()) {
248
1.55k
    assert(literal_words_or_ids.size() == 1 &&
249
1.55k
           "Bool constant should be declared with one operand");
250
1.55k
    return MakeUnique<BoolConstant>(bt, literal_words_or_ids.front());
251
28.8k
  } else if (auto* it = type->AsInteger()) {
252
18.1k
    return MakeUnique<IntConstant>(it, literal_words_or_ids);
253
18.1k
  } else if (auto* ft = type->AsFloat()) {
254
8.73k
    return MakeUnique<FloatConstant>(ft, literal_words_or_ids);
255
8.73k
  } else if (auto* vt = type->AsVector()) {
256
1.74k
    auto components = GetConstantsFromIds(literal_words_or_ids);
257
1.74k
    if (components.empty()) return nullptr;
258
    // All components of VectorConstant must be of type Bool, Integer or Float.
259
1.73k
    if (!std::all_of(components.begin(), components.end(),
260
4.93k
                     [](const Constant* c) {
261
4.93k
                       if (c->type()->AsBool() || c->type()->AsInteger() ||
262
4.93k
                           c->type()->AsFloat()) {
263
4.93k
                         return true;
264
4.93k
                       } else {
265
0
                         return false;
266
0
                       }
267
4.93k
                     }))
268
0
      return nullptr;
269
    // All components of VectorConstant must be in the same type.
270
1.73k
    const auto* component_type = components.front()->type();
271
1.73k
    if (!std::all_of(components.begin(), components.end(),
272
4.93k
                     [&component_type](const Constant* c) {
273
4.93k
                       if (c->type() == component_type) return true;
274
0
                       return false;
275
4.93k
                     }))
276
0
      return nullptr;
277
1.73k
    return MakeUnique<VectorConstant>(vt, components);
278
1.73k
  } else if (auto* mt = type->AsMatrix()) {
279
22
    auto components = GetConstantsFromIds(literal_words_or_ids);
280
22
    if (components.empty()) return nullptr;
281
22
    return MakeUnique<MatrixConstant>(mt, components);
282
142
  } else if (auto* st = type->AsStruct()) {
283
110
    auto components = GetConstantsFromIds(literal_words_or_ids);
284
110
    if (components.empty()) return nullptr;
285
110
    return MakeUnique<StructConstant>(st, components);
286
110
  } else if (auto* at = type->AsArray()) {
287
32
    auto components = GetConstantsFromIds(literal_words_or_ids);
288
32
    if (components.empty()) return nullptr;
289
32
    return MakeUnique<ArrayConstant>(at, components);
290
32
  } else {
291
0
    return nullptr;
292
0
  }
293
30.3k
}
294
295
24.3k
const Constant* ConstantManager::GetConstantFromInst(const Instruction* inst) {
296
24.3k
  std::vector<uint32_t> literal_words_or_ids;
297
298
  // Collect the constant defining literals or component ids.
299
51.1k
  for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
300
26.8k
    literal_words_or_ids.insert(literal_words_or_ids.end(),
301
26.8k
                                inst->GetInOperand(i).words.begin(),
302
26.8k
                                inst->GetInOperand(i).words.end());
303
26.8k
  }
304
305
24.3k
  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
42
    case spv::Op::OpConstantTrue:
309
42
      literal_words_or_ids.push_back(true);
310
42
      break;
311
42
    case spv::Op::OpConstantFalse:
312
42
      literal_words_or_ids.push_back(false);
313
42
      break;
314
0
    case spv::Op::OpConstantNull:
315
22.9k
    case spv::Op::OpConstant:
316
24.1k
    case spv::Op::OpConstantComposite:
317
24.2k
    case spv::Op::OpSpecConstantComposite:
318
24.2k
    case spv::Op::OpSpecConstantCompositeReplicateEXT:
319
24.2k
      break;
320
60
    default:
321
60
      return nullptr;
322
24.3k
  }
323
324
24.2k
  return GetConstant(GetType(inst), literal_words_or_ids);
325
24.3k
}
326
327
std::unique_ptr<Instruction> ConstantManager::CreateInstruction(
328
1.08k
    uint32_t id, const Constant* c, uint32_t type_id) const {
329
1.08k
  uint32_t type =
330
1.08k
      (type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id;
331
1.08k
  if (c->AsNullConstant()) {
332
4
    return MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, type, id,
333
4
                                   std::initializer_list<Operand>{});
334
1.07k
  } else if (const BoolConstant* bc = c->AsBoolConstant()) {
335
546
    return MakeUnique<Instruction>(
336
546
        context(),
337
546
        bc->value() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse, type,
338
546
        id, std::initializer_list<Operand>{});
339
546
  } else if (const IntConstant* ic = c->AsIntConstant()) {
340
170
    return MakeUnique<Instruction>(
341
170
        context(), spv::Op::OpConstant, type, id,
342
170
        std::initializer_list<Operand>{
343
170
            Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
344
170
                    ic->words())});
345
360
  } else if (const FloatConstant* fc = c->AsFloatConstant()) {
346
52
    return MakeUnique<Instruction>(
347
52
        context(), spv::Op::OpConstant, type, id,
348
52
        std::initializer_list<Operand>{
349
52
            Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
350
52
                    fc->words())});
351
308
  } else if (const CompositeConstant* cc = c->AsCompositeConstant()) {
352
308
    return CreateCompositeInstruction(id, cc, type_id);
353
308
  } else {
354
0
    return nullptr;
355
0
  }
356
1.08k
}
357
358
std::unique_ptr<Instruction> ConstantManager::CreateCompositeInstruction(
359
308
    uint32_t result_id, const CompositeConstant* cc, uint32_t type_id) const {
360
308
  std::vector<Operand> operands;
361
308
  Instruction* type_inst = context()->get_def_use_mgr()->GetDef(type_id);
362
308
  uint32_t component_index = 0;
363
832
  for (const Constant* component_const : cc->GetComponents()) {
364
832
    uint32_t component_type_id = 0;
365
832
    if (type_inst && type_inst->opcode() == spv::Op::OpTypeStruct) {
366
128
      component_type_id = type_inst->GetSingleWordInOperand(component_index);
367
704
    } else if (type_inst && type_inst->opcode() == spv::Op::OpTypeArray) {
368
0
      component_type_id = type_inst->GetSingleWordInOperand(0);
369
0
    }
370
832
    uint32_t id = FindDeclaredConstant(component_const, component_type_id);
371
372
832
    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
832
    operands.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
379
832
                          std::initializer_list<uint32_t>{id});
380
832
    component_index++;
381
832
  }
382
308
  uint32_t type =
383
308
      (type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id;
384
308
  return MakeUnique<Instruction>(context(), spv::Op::OpConstantComposite, type,
385
308
                                 result_id, std::move(operands));
386
308
}
387
388
const Constant* ConstantManager::GetConstant(
389
30.3k
    const Type* type, const std::vector<uint32_t>& literal_words_or_ids) {
390
30.3k
  auto cst = CreateConstant(type, literal_words_or_ids);
391
30.3k
  return cst ? RegisterConstant(std::move(cst)) : nullptr;
392
30.3k
}
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
6
    const Vector* type, const std::vector<uint32_t>& literal_words) {
433
6
  const auto* element_type = type->element_type();
434
6
  uint32_t words_per_element = 0;
435
6
  if (const auto* float_type = element_type->AsFloat())
436
0
    words_per_element = float_type->width() / 32;
437
6
  else if (const auto* int_type = element_type->AsInteger())
438
6
    words_per_element = int_type->width() / 32;
439
0
  else if (element_type->AsBool() != nullptr)
440
0
    words_per_element = 1;
441
442
6
  if (words_per_element != 1 && words_per_element != 2) return nullptr;
443
444
6
  if (words_per_element * type->element_count() !=
445
6
      static_cast<uint32_t>(literal_words.size())) {
446
0
    return nullptr;
447
0
  }
448
449
6
  std::vector<uint32_t> element_ids;
450
18
  for (uint32_t i = 0; i < type->element_count(); ++i) {
451
12
    auto first_word = literal_words.begin() + (words_per_element * i);
452
12
    std::vector<uint32_t> const_data(first_word,
453
12
                                     first_word + words_per_element);
454
12
    const analysis::Constant* element_constant =
455
12
        GetConstant(element_type, const_data);
456
12
    auto element_id = GetDefiningInstruction(element_constant)->result_id();
457
12
    element_ids.push_back(element_id);
458
12
  }
459
460
6
  return GetConstant(type, element_ids);
461
6
}
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
74
const Constant* ConstantManager::GetFloatConst(float val) {
471
74
  Type* float_type = context()->get_type_mgr()->GetFloatType();
472
74
  utils::FloatProxy<float> v(val);
473
74
  const Constant* c = GetConstant(float_type, v.GetWords());
474
74
  return c;
475
74
}
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
624
                                             bool isSigned) {
499
624
  Type* int_type = context()->get_type_mgr()->GetIntType(bitWidth, isSigned);
500
501
624
  if (isSigned) {
502
    // Sign extend the value.
503
624
    int32_t num_of_bit_to_ignore = 64 - bitWidth;
504
624
    val = static_cast<int64_t>(val << num_of_bit_to_ignore) >>
505
624
          num_of_bit_to_ignore;
506
624
  } 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
624
  if (bitWidth <= 32) {
513
624
    return GetConstant(int_type, {static_cast<uint32_t>(val)});
514
624
  }
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
624
}
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
1.29k
    const analysis::Integer* integer_type, uint64_t result) {
535
1.29k
  assert(integer_type != nullptr);
536
537
1.29k
  std::vector<uint32_t> words;
538
1.29k
  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
1.29k
  } else {
543
    // In all other cases, only a single word is needed.
544
1.29k
    assert(integer_type->width() <= 32);
545
1.29k
    if (integer_type->IsSigned()) {
546
1.28k
      result = utils::SignExtendValue(result, integer_type->width());
547
1.28k
    } else {
548
12
      result = utils::ZeroExtendValue(result, integer_type->width());
549
12
    }
550
1.29k
    words = {static_cast<uint32_t>(result)};
551
1.29k
  }
552
1.29k
  return GetConstant(integer_type, words);
553
1.29k
}
554
555
std::vector<const analysis::Constant*> Constant::GetVectorComponents(
556
46
    analysis::ConstantManager* const_mgr) const {
557
46
  std::vector<const analysis::Constant*> components;
558
46
  const analysis::VectorConstant* a = this->AsVectorConstant();
559
46
  const analysis::Vector* vector_type = this->type()->AsVector();
560
46
  assert(vector_type != nullptr);
561
46
  if (a != nullptr) {
562
184
    for (uint32_t i = 0; i < vector_type->element_count(); ++i) {
563
138
      components.push_back(a->GetComponents()[i]);
564
138
    }
565
46
  } 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
46
  return components;
574
46
}
575
576
}  // namespace analysis
577
}  // namespace opt
578
}  // namespace spvtools