Coverage Report

Created: 2025-08-28 07:18

/src/shaderc/third_party/spirv-tools/source/opt/module.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2016 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
#ifndef SOURCE_OPT_MODULE_H_
16
#define SOURCE_OPT_MODULE_H_
17
18
#include <functional>
19
#include <memory>
20
#include <string_view>
21
#include <unordered_map>
22
#include <utility>
23
#include <vector>
24
25
#include "source/opt/function.h"
26
#include "source/opt/instruction.h"
27
#include "source/opt/iterator.h"
28
29
namespace spvtools {
30
namespace opt {
31
32
class IRContext;
33
34
// A struct for containing the module header information.
35
struct ModuleHeader {
36
  uint32_t magic_number;
37
  uint32_t version;
38
  uint32_t generator;
39
  uint32_t bound;
40
  uint32_t schema;
41
};
42
43
// A SPIR-V module. It contains all the information for a SPIR-V module and
44
// serves as the backbone of optimization transformations.
45
class Module {
46
 public:
47
  using iterator = UptrVectorIterator<Function>;
48
  using const_iterator = UptrVectorIterator<Function, true>;
49
  using inst_iterator = InstructionList::iterator;
50
  using const_inst_iterator = InstructionList::const_iterator;
51
52
  // Creates an empty module with zero'd header.
53
1.41k
  Module() : header_({}), contains_debug_info_(false) {}
54
55
  // Sets the header to the given |header|.
56
1.41k
  void SetHeader(const ModuleHeader& header) { header_ = header; }
57
58
  // Sets the Id bound.  The Id bound cannot be set to 0.
59
1.31k
  void SetIdBound(uint32_t bound) {
60
1.31k
    assert(bound != 0);
61
1.31k
    header_.bound = bound;
62
1.31k
  }
63
64
  // Returns the Id bound.
65
2.23k
  uint32_t IdBound() const { return header_.bound; }
66
67
  // Returns the current Id bound and increases it to the next available value.
68
  // If the id bound has already reached its maximum value, then 0 is returned.
69
  // The maximum value for the id bound is obtained from the context.  If there
70
  // is none, then the minimum that limit can be according to the spir-v
71
  // specification.
72
  // TODO(1841): Update the uses to check for a 0 return value.
73
  uint32_t TakeNextIdBound();
74
75
  // Appends a capability instruction to this module.
76
  inline void AddCapability(std::unique_ptr<Instruction> c);
77
78
  // Appends an extension instruction to this module.
79
  inline void AddExtension(std::unique_ptr<Instruction> e);
80
81
  // Appends an extended instruction set instruction to this module.
82
  inline void AddExtInstImport(std::unique_ptr<Instruction> e);
83
84
  // Set the memory model for this module.
85
  inline void SetMemoryModel(std::unique_ptr<Instruction> m);
86
87
  // Set the sampled image addressing mode for this module.
88
  inline void SetSampledImageAddressMode(std::unique_ptr<Instruction> m);
89
90
  // Appends an entry point instruction to this module.
91
  inline void AddEntryPoint(std::unique_ptr<Instruction> e);
92
93
  // Appends an execution mode instruction to this module.
94
  inline void AddExecutionMode(std::unique_ptr<Instruction> e);
95
96
  // Appends a debug 1 instruction (excluding OpLine & OpNoLine) to this module.
97
  // "debug 1" instructions are the ones in layout section 7.a), see section
98
  // 2.4 Logical Layout of a Module from the SPIR-V specification.
99
  inline void AddDebug1Inst(std::unique_ptr<Instruction> d);
100
101
  // Appends a debug 2 instruction (excluding OpLine & OpNoLine) to this module.
102
  // "debug 2" instructions are the ones in layout section 7.b), see section
103
  // 2.4 Logical Layout of a Module from the SPIR-V specification.
104
  inline void AddDebug2Inst(std::unique_ptr<Instruction> d);
105
106
  // Appends a debug 3 instruction (OpModuleProcessed) to this module.
107
  // This is due to decision by the SPIR Working Group, pending publication.
108
  inline void AddDebug3Inst(std::unique_ptr<Instruction> d);
109
110
  // Appends a debug info extension (OpenCL.DebugInfo.100,
111
  // NonSemantic.Shader.DebugInfo.100, or DebugInfo) instruction to this module.
112
  inline void AddExtInstDebugInfo(std::unique_ptr<Instruction> d);
113
114
  // Appends an annotation instruction to this module.
115
  inline void AddAnnotationInst(std::unique_ptr<Instruction> a);
116
117
  // Appends a type-declaration instruction to this module.
118
  inline void AddType(std::unique_ptr<Instruction> t);
119
120
  // Appends a constant, global variable, or OpUndef instruction to this module.
121
  inline void AddGlobalValue(std::unique_ptr<Instruction> v);
122
123
  // Prepends a function declaration to this module.
124
  inline void AddFunctionDeclaration(std::unique_ptr<Function> f);
125
126
  // Appends a function to this module.
127
  inline void AddFunction(std::unique_ptr<Function> f);
128
129
  // Sets |contains_debug_info_| as true.
130
  inline void SetContainsDebugInfo();
131
0
  inline bool ContainsDebugInfo() { return contains_debug_info_; }
132
133
  // Returns a vector of pointers to type-declaration instructions in this
134
  // module.
135
  std::vector<Instruction*> GetTypes();
136
  std::vector<const Instruction*> GetTypes() const;
137
  // Returns a vector of pointers to constant-creation instructions in this
138
  // module.
139
  std::vector<Instruction*> GetConstants();
140
  std::vector<const Instruction*> GetConstants() const;
141
142
  // Return result id of global value with |opcode|, 0 if not present.
143
  uint32_t GetGlobalValue(spv::Op opcode) const;
144
145
  // Add global value with |opcode|, |result_id| and |type_id|
146
  void AddGlobalValue(spv::Op opcode, uint32_t result_id, uint32_t type_id);
147
148
75.7k
  inline uint32_t id_bound() const { return header_.bound; }
149
150
1.81k
  inline uint32_t version() const { return header_.version; }
151
0
  inline uint32_t generator() const { return header_.generator; }
152
0
  inline uint32_t schema() const { return header_.schema; }
153
154
0
  inline void set_version(uint32_t v) { header_.version = v; }
155
156
  // Iterators for capabilities instructions contained in this module.
157
  inline inst_iterator capability_begin();
158
  inline inst_iterator capability_end();
159
  inline IteratorRange<inst_iterator> capabilities();
160
  inline IteratorRange<const_inst_iterator> capabilities() const;
161
162
  // Iterators for ext_inst_imports instructions contained in this module.
163
  inline inst_iterator ext_inst_import_begin();
164
  inline inst_iterator ext_inst_import_end();
165
  inline IteratorRange<inst_iterator> ext_inst_imports();
166
  inline IteratorRange<const_inst_iterator> ext_inst_imports() const;
167
168
  // Return the memory model instruction contained in this module.
169
0
  inline Instruction* GetMemoryModel() { return memory_model_.get(); }
170
0
  inline const Instruction* GetMemoryModel() const {
171
0
    return memory_model_.get();
172
0
  }
173
174
  // Return the sampled image address mode instruction contained in this module.
175
0
  inline Instruction* GetSampledImageAddressMode() {
176
0
    return sampled_image_address_mode_.get();
177
0
  }
178
0
  inline const Instruction* GetSampledImageAddressMode() const {
179
0
    return sampled_image_address_mode_.get();
180
0
  }
181
182
  // There are several kinds of debug instructions, according to where they can
183
  // appear in the logical layout of a module:
184
  //  - Section 7a:  OpString, OpSourceExtension, OpSource, OpSourceContinued
185
  //  - Section 7b:  OpName, OpMemberName
186
  //  - Section 7c:  OpModuleProcessed
187
  //  - Mostly anywhere: OpLine and OpNoLine
188
  //
189
190
  // Iterators for debug 1 instructions (excluding OpLine & OpNoLine) contained
191
  // in this module.  These are for layout section 7a.
192
  inline inst_iterator debug1_begin();
193
  inline inst_iterator debug1_end();
194
  inline IteratorRange<inst_iterator> debugs1();
195
  inline IteratorRange<const_inst_iterator> debugs1() const;
196
197
  // Iterators for debug 2 instructions (excluding OpLine & OpNoLine) contained
198
  // in this module.  These are for layout section 7b.
199
  inline inst_iterator debug2_begin();
200
  inline inst_iterator debug2_end();
201
  inline IteratorRange<inst_iterator> debugs2();
202
  inline IteratorRange<const_inst_iterator> debugs2() const;
203
204
  // Iterators for debug 3 instructions (excluding OpLine & OpNoLine) contained
205
  // in this module.  These are for layout section 7c.
206
  inline inst_iterator debug3_begin();
207
  inline inst_iterator debug3_end();
208
  inline IteratorRange<inst_iterator> debugs3();
209
  inline IteratorRange<const_inst_iterator> debugs3() const;
210
211
  // Iterators for debug info instructions (excluding OpLine & OpNoLine)
212
  // contained in this module.  These are OpExtInst for DebugInfo extension
213
  // placed between section 9 and 10.
214
  inline inst_iterator ext_inst_debuginfo_begin();
215
  inline inst_iterator ext_inst_debuginfo_end();
216
  inline IteratorRange<inst_iterator> ext_inst_debuginfo();
217
  inline IteratorRange<const_inst_iterator> ext_inst_debuginfo() const;
218
219
  // Iterators for entry point instructions contained in this module
220
  inline IteratorRange<inst_iterator> entry_points();
221
  inline IteratorRange<const_inst_iterator> entry_points() const;
222
223
  // Iterators for execution_modes instructions contained in this module.
224
  inline inst_iterator execution_mode_begin();
225
  inline inst_iterator execution_mode_end();
226
  inline IteratorRange<inst_iterator> execution_modes();
227
  inline IteratorRange<const_inst_iterator> execution_modes() const;
228
229
  // Iterators for annotation instructions contained in this module.
230
  inline inst_iterator annotation_begin();
231
  inline inst_iterator annotation_end();
232
  IteratorRange<inst_iterator> annotations();
233
  IteratorRange<const_inst_iterator> annotations() const;
234
235
  // Iterators for extension instructions contained in this module.
236
  inline inst_iterator extension_begin();
237
  inline inst_iterator extension_end();
238
  IteratorRange<inst_iterator> extensions();
239
  IteratorRange<const_inst_iterator> extensions() const;
240
241
  // Iterators for types, constants and global variables instructions.
242
  inline inst_iterator types_values_begin();
243
  inline inst_iterator types_values_end();
244
  inline IteratorRange<inst_iterator> types_values();
245
  inline IteratorRange<const_inst_iterator> types_values() const;
246
247
  // Iterators for functions contained in this module.
248
89.4k
  iterator begin() { return iterator(&functions_, functions_.begin()); }
249
101k
  iterator end() { return iterator(&functions_, functions_.end()); }
250
0
  const_iterator begin() const { return cbegin(); }
251
0
  const_iterator end() const { return cend(); }
252
  inline const_iterator cbegin() const;
253
  inline const_iterator cend() const;
254
255
  // Invokes function |f| on all instructions in this module, and optionally on
256
  // the debug line instructions that precede them.
257
  void ForEachInst(const std::function<void(Instruction*)>& f,
258
                   bool run_on_debug_line_insts = false);
259
  void ForEachInst(const std::function<void(const Instruction*)>& f,
260
                   bool run_on_debug_line_insts = false) const;
261
262
  // Pushes the binary segments for this instruction into the back of *|binary|.
263
  // If |skip_nop| is true and this is a OpNop, do nothing.
264
  void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
265
266
  // Returns 1 more than the maximum Id value mentioned in the module.
267
  uint32_t ComputeIdBound() const;
268
269
  // Returns true if module has capability |cap|
270
  bool HasExplicitCapability(uint32_t cap);
271
272
  // Returns id for OpExtInst instruction for extension |extstr|.
273
  // Returns 0 if not found.
274
  uint32_t GetExtInstImportId(const char* extstr);
275
276
  // Sets the associated context for this module
277
1.41k
  void SetContext(IRContext* c) { context_ = c; }
278
279
  // Gets the associated context for this module
280
387k
  IRContext* context() const { return context_; }
281
282
  // Sets the trailing debug line info to |dbg_line_info|.
283
1.41k
  void SetTrailingDbgLineInfo(std::vector<Instruction>&& dbg_line_info) {
284
1.41k
    trailing_dbg_line_info_ = std::move(dbg_line_info);
285
1.41k
  }
286
287
1.24k
  std::vector<Instruction>& trailing_dbg_line_info() {
288
1.24k
    return trailing_dbg_line_info_;
289
1.24k
  }
290
291
0
  const std::vector<Instruction>& trailing_dbg_line_info() const {
292
0
    return trailing_dbg_line_info_;
293
0
  }
294
295
 private:
296
  ModuleHeader header_;  // Module header
297
298
  // The following fields respect the "Logical Layout of a Module" in
299
  // Section 2.4 of the SPIR-V specification.
300
  IRContext* context_;
301
  InstructionList capabilities_;
302
  InstructionList extensions_;
303
  InstructionList ext_inst_imports_;
304
  // A module only has one memory model instruction.
305
  std::unique_ptr<Instruction> memory_model_;
306
  // A module can only have one optional sampled image addressing mode
307
  std::unique_ptr<Instruction> sampled_image_address_mode_;
308
  InstructionList entry_points_;
309
  InstructionList execution_modes_;
310
  InstructionList debugs1_;
311
  InstructionList debugs2_;
312
  InstructionList debugs3_;
313
  InstructionList ext_inst_debuginfo_;
314
  InstructionList annotations_;
315
  // Type declarations, constants, and global variable declarations.
316
  InstructionList types_values_;
317
  std::vector<std::unique_ptr<Function>> functions_;
318
319
  // If the module ends with Op*Line instruction, they will not be attached to
320
  // any instruction.  We record them here, so they will not be lost.
321
  std::vector<Instruction> trailing_dbg_line_info_;
322
323
  // This module contains DebugScope/DebugNoScope or OpLine/OpNoLine.
324
  bool contains_debug_info_;
325
};
326
327
// Pretty-prints |module| to |str|. Returns |str|.
328
std::ostream& operator<<(std::ostream& str, const Module& module);
329
330
2.16k
inline void Module::AddCapability(std::unique_ptr<Instruction> c) {
331
2.16k
  capabilities_.push_back(std::move(c));
332
2.16k
}
333
334
752
inline void Module::AddExtension(std::unique_ptr<Instruction> e) {
335
752
  extensions_.push_back(std::move(e));
336
752
}
337
338
1.43k
inline void Module::AddExtInstImport(std::unique_ptr<Instruction> e) {
339
1.43k
  ext_inst_imports_.push_back(std::move(e));
340
1.43k
}
341
342
1.41k
inline void Module::SetMemoryModel(std::unique_ptr<Instruction> m) {
343
1.41k
  memory_model_ = std::move(m);
344
1.41k
}
345
346
0
inline void Module::SetSampledImageAddressMode(std::unique_ptr<Instruction> m) {
347
0
  sampled_image_address_mode_ = std::move(m);
348
0
}
349
350
1.41k
inline void Module::AddEntryPoint(std::unique_ptr<Instruction> e) {
351
1.41k
  entry_points_.push_back(std::move(e));
352
1.41k
}
353
354
162
inline void Module::AddExecutionMode(std::unique_ptr<Instruction> e) {
355
162
  execution_modes_.push_back(std::move(e));
356
162
}
357
358
5.12k
inline void Module::AddDebug1Inst(std::unique_ptr<Instruction> d) {
359
5.12k
  debugs1_.push_back(std::move(d));
360
5.12k
}
361
362
23.9k
inline void Module::AddDebug2Inst(std::unique_ptr<Instruction> d) {
363
23.9k
  debugs2_.push_back(std::move(d));
364
23.9k
}
365
366
0
inline void Module::AddDebug3Inst(std::unique_ptr<Instruction> d) {
367
0
  debugs3_.push_back(std::move(d));
368
0
}
369
370
0
inline void Module::AddExtInstDebugInfo(std::unique_ptr<Instruction> d) {
371
0
  ext_inst_debuginfo_.push_back(std::move(d));
372
0
}
373
374
12.2k
inline void Module::AddAnnotationInst(std::unique_ptr<Instruction> a) {
375
12.2k
  annotations_.push_back(std::move(a));
376
12.2k
}
377
378
22.4k
inline void Module::AddType(std::unique_ptr<Instruction> t) {
379
22.4k
  types_values_.push_back(std::move(t));
380
22.4k
}
381
382
15.6k
inline void Module::AddGlobalValue(std::unique_ptr<Instruction> v) {
383
15.6k
  types_values_.push_back(std::move(v));
384
15.6k
}
385
386
0
inline void Module::AddFunctionDeclaration(std::unique_ptr<Function> f) {
387
0
  // function declarations must come before function definitions.
388
0
  functions_.emplace(functions_.begin(), std::move(f));
389
0
}
390
391
2.13k
inline void Module::AddFunction(std::unique_ptr<Function> f) {
392
2.13k
  functions_.emplace_back(std::move(f));
393
2.13k
}
394
395
0
inline void Module::SetContainsDebugInfo() { contains_debug_info_ = true; }
396
397
0
inline Module::inst_iterator Module::capability_begin() {
398
0
  return capabilities_.begin();
399
0
}
400
0
inline Module::inst_iterator Module::capability_end() {
401
0
  return capabilities_.end();
402
0
}
403
404
4.77k
inline IteratorRange<Module::inst_iterator> Module::capabilities() {
405
4.77k
  return make_range(capabilities_.begin(), capabilities_.end());
406
4.77k
}
407
408
0
inline IteratorRange<Module::const_inst_iterator> Module::capabilities() const {
409
0
  return make_range(capabilities_.begin(), capabilities_.end());
410
0
}
411
412
0
inline Module::inst_iterator Module::ext_inst_import_begin() {
413
0
  return ext_inst_imports_.begin();
414
0
}
415
0
inline Module::inst_iterator Module::ext_inst_import_end() {
416
0
  return ext_inst_imports_.end();
417
0
}
418
419
28.9k
inline IteratorRange<Module::inst_iterator> Module::ext_inst_imports() {
420
28.9k
  return make_range(ext_inst_imports_.begin(), ext_inst_imports_.end());
421
28.9k
}
422
423
inline IteratorRange<Module::const_inst_iterator> Module::ext_inst_imports()
424
0
    const {
425
0
  return make_range(ext_inst_imports_.begin(), ext_inst_imports_.end());
426
0
}
427
428
0
inline Module::inst_iterator Module::debug1_begin() { return debugs1_.begin(); }
429
0
inline Module::inst_iterator Module::debug1_end() { return debugs1_.end(); }
430
431
1.24k
inline IteratorRange<Module::inst_iterator> Module::debugs1() {
432
1.24k
  return make_range(debugs1_.begin(), debugs1_.end());
433
1.24k
}
434
435
0
inline IteratorRange<Module::const_inst_iterator> Module::debugs1() const {
436
0
  return make_range(debugs1_.begin(), debugs1_.end());
437
0
}
438
439
10.4k
inline Module::inst_iterator Module::debug2_begin() { return debugs2_.begin(); }
440
0
inline Module::inst_iterator Module::debug2_end() { return debugs2_.end(); }
441
442
6.05k
inline IteratorRange<Module::inst_iterator> Module::debugs2() {
443
6.05k
  return make_range(debugs2_.begin(), debugs2_.end());
444
6.05k
}
445
446
0
inline IteratorRange<Module::const_inst_iterator> Module::debugs2() const {
447
0
  return make_range(debugs2_.begin(), debugs2_.end());
448
0
}
449
450
0
inline Module::inst_iterator Module::debug3_begin() { return debugs3_.begin(); }
451
0
inline Module::inst_iterator Module::debug3_end() { return debugs3_.end(); }
452
453
1.24k
inline IteratorRange<Module::inst_iterator> Module::debugs3() {
454
1.24k
  return make_range(debugs3_.begin(), debugs3_.end());
455
1.24k
}
456
457
0
inline IteratorRange<Module::const_inst_iterator> Module::debugs3() const {
458
0
  return make_range(debugs3_.begin(), debugs3_.end());
459
0
}
460
461
25.6k
inline Module::inst_iterator Module::ext_inst_debuginfo_begin() {
462
25.6k
  return ext_inst_debuginfo_.begin();
463
25.6k
}
464
25.6k
inline Module::inst_iterator Module::ext_inst_debuginfo_end() {
465
25.6k
  return ext_inst_debuginfo_.end();
466
25.6k
}
467
468
37.0k
inline IteratorRange<Module::inst_iterator> Module::ext_inst_debuginfo() {
469
37.0k
  return make_range(ext_inst_debuginfo_.begin(), ext_inst_debuginfo_.end());
470
37.0k
}
471
472
inline IteratorRange<Module::const_inst_iterator> Module::ext_inst_debuginfo()
473
0
    const {
474
0
  return make_range(ext_inst_debuginfo_.begin(), ext_inst_debuginfo_.end());
475
0
}
476
477
58.0k
inline IteratorRange<Module::inst_iterator> Module::entry_points() {
478
58.0k
  return make_range(entry_points_.begin(), entry_points_.end());
479
58.0k
}
480
481
0
inline IteratorRange<Module::const_inst_iterator> Module::entry_points() const {
482
0
  return make_range(entry_points_.begin(), entry_points_.end());
483
0
}
484
485
0
inline Module::inst_iterator Module::execution_mode_begin() {
486
0
  return execution_modes_.begin();
487
0
}
488
0
inline Module::inst_iterator Module::execution_mode_end() {
489
0
  return execution_modes_.end();
490
0
}
491
492
10.4k
inline IteratorRange<Module::inst_iterator> Module::execution_modes() {
493
10.4k
  return make_range(execution_modes_.begin(), execution_modes_.end());
494
10.4k
}
495
496
inline IteratorRange<Module::const_inst_iterator> Module::execution_modes()
497
0
    const {
498
0
  return make_range(execution_modes_.begin(), execution_modes_.end());
499
0
}
500
501
0
inline Module::inst_iterator Module::annotation_begin() {
502
0
  return annotations_.begin();
503
0
}
504
24
inline Module::inst_iterator Module::annotation_end() {
505
24
  return annotations_.end();
506
24
}
507
508
88.7k
inline IteratorRange<Module::inst_iterator> Module::annotations() {
509
88.7k
  return make_range(annotations_.begin(), annotations_.end());
510
88.7k
}
511
512
0
inline IteratorRange<Module::const_inst_iterator> Module::annotations() const {
513
0
  return make_range(annotations_.begin(), annotations_.end());
514
0
}
515
516
0
inline Module::inst_iterator Module::extension_begin() {
517
0
  return extensions_.begin();
518
0
}
519
0
inline Module::inst_iterator Module::extension_end() {
520
0
  return extensions_.end();
521
0
}
522
523
24.4k
inline IteratorRange<Module::inst_iterator> Module::extensions() {
524
24.4k
  return make_range(extensions_.begin(), extensions_.end());
525
24.4k
}
526
527
0
inline IteratorRange<Module::const_inst_iterator> Module::extensions() const {
528
0
  return make_range(extensions_.begin(), extensions_.end());
529
0
}
530
531
2.03k
inline Module::inst_iterator Module::types_values_begin() {
532
2.03k
  return types_values_.begin();
533
2.03k
}
534
535
47.3k
inline Module::inst_iterator Module::types_values_end() {
536
47.3k
  return types_values_.end();
537
47.3k
}
538
539
17.7k
inline IteratorRange<Module::inst_iterator> Module::types_values() {
540
17.7k
  return make_range(types_values_.begin(), types_values_.end());
541
17.7k
}
542
543
0
inline IteratorRange<Module::const_inst_iterator> Module::types_values() const {
544
0
  return make_range(types_values_.begin(), types_values_.end());
545
0
}
546
547
0
inline Module::const_iterator Module::cbegin() const {
548
0
  return const_iterator(&functions_, functions_.cbegin());
549
0
}
550
551
0
inline Module::const_iterator Module::cend() const {
552
0
  return const_iterator(&functions_, functions_.cend());
553
0
}
554
555
}  // namespace opt
556
}  // namespace spvtools
557
558
#endif  // SOURCE_OPT_MODULE_H_