aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm16/include/llvm/IR/Module.h
blob: 433d4832966fcfe388d199063fe2b1261bd6679d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===- llvm/Module.h - C++ class to represent a VM module -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// @file
/// Module.h This file contains the declarations for the Module class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_IR_MODULE_H
#define LLVM_IR_MODULE_H

#include "llvm-c/Types.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalIFunc.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/IR/SymbolTableListTraits.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/CodeGen.h"
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <vector>

namespace llvm {

class Error;
class FunctionType;
class GVMaterializer;
class LLVMContext;
class MemoryBuffer;
class ModuleSummaryIndex;
class RandomNumberGenerator;
class StructType;
class VersionTuple;

/// A Module instance is used to store all the information related to an
/// LLVM module. Modules are the top level container of all other LLVM
/// Intermediate Representation (IR) objects. Each module directly contains a
/// list of globals variables, a list of functions, a list of libraries (or
/// other modules) this module depends on, a symbol table, and various data
/// about the target's characteristics.
///
/// A module maintains a GlobalList object that is used to hold all
/// constant references to global variables in the module.  When a global
/// variable is destroyed, it should have no entries in the GlobalList.
/// The main container class for the LLVM Intermediate Representation.
class LLVM_EXTERNAL_VISIBILITY Module {
  /// @name Types And Enumerations
  /// @{
public:
  /// The type for the list of global variables.
  using GlobalListType = SymbolTableList<GlobalVariable>;
  /// The type for the list of functions.
  using FunctionListType = SymbolTableList<Function>;
  /// The type for the list of aliases.
  using AliasListType = SymbolTableList<GlobalAlias>;
  /// The type for the list of ifuncs.
  using IFuncListType = SymbolTableList<GlobalIFunc>;
  /// The type for the list of named metadata.
  using NamedMDListType = ilist<NamedMDNode>;
  /// The type of the comdat "symbol" table.
  using ComdatSymTabType = StringMap<Comdat>;
  /// The type for mapping names to named metadata.
  using NamedMDSymTabType = StringMap<NamedMDNode *>;

  /// The Global Variable iterator.
  using global_iterator = GlobalListType::iterator;
  /// The Global Variable constant iterator.
  using const_global_iterator = GlobalListType::const_iterator;

  /// The Function iterators.
  using iterator = FunctionListType::iterator;
  /// The Function constant iterator
  using const_iterator = FunctionListType::const_iterator;

  /// The Function reverse iterator.
  using reverse_iterator = FunctionListType::reverse_iterator;
  /// The Function constant reverse iterator.
  using const_reverse_iterator = FunctionListType::const_reverse_iterator;

  /// The Global Alias iterators.
  using alias_iterator = AliasListType::iterator;
  /// The Global Alias constant iterator
  using const_alias_iterator = AliasListType::const_iterator;

  /// The Global IFunc iterators.
  using ifunc_iterator = IFuncListType::iterator;
  /// The Global IFunc constant iterator
  using const_ifunc_iterator = IFuncListType::const_iterator;

  /// The named metadata iterators.
  using named_metadata_iterator = NamedMDListType::iterator;
  /// The named metadata constant iterators.
  using const_named_metadata_iterator = NamedMDListType::const_iterator;

  /// This enumeration defines the supported behaviors of module flags.
  enum ModFlagBehavior {
    /// Emits an error if two values disagree, otherwise the resulting value is
    /// that of the operands.
    Error = 1,

    /// Emits a warning if two values disagree. The result value will be the
    /// operand for the flag from the first module being linked.
    Warning = 2,

    /// Adds a requirement that another module flag be present and have a
    /// specified value after linking is performed. The value must be a metadata
    /// pair, where the first element of the pair is the ID of the module flag
    /// to be restricted, and the second element of the pair is the value the
    /// module flag should be restricted to. This behavior can be used to
    /// restrict the allowable results (via triggering of an error) of linking
    /// IDs with the **Override** behavior.
    Require = 3,

    /// Uses the specified value, regardless of the behavior or value of the
    /// other module. If both modules specify **Override**, but the values
    /// differ, an error will be emitted.
    Override = 4,

    /// Appends the two values, which are required to be metadata nodes.
    Append = 5,

    /// Appends the two values, which are required to be metadata
    /// nodes. However, duplicate entries in the second list are dropped
    /// during the append operation.
    AppendUnique = 6,

    /// Takes the max of the two values, which are required to be integers.
    Max = 7,

    /// Takes the min of the two values, which are required to be integers.
    Min = 8,

    // Markers:
    ModFlagBehaviorFirstVal = Error,
    ModFlagBehaviorLastVal = Min
  };

  /// Checks if Metadata represents a valid ModFlagBehavior, and stores the
  /// converted result in MFB.
  static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB);

  /// Check if the given module flag metadata represents a valid module flag,
  /// and store the flag behavior, the key string and the value metadata.
  static bool isValidModuleFlag(const MDNode &ModFlag, ModFlagBehavior &MFB,
                                MDString *&Key, Metadata *&Val);

  struct ModuleFlagEntry {
    ModFlagBehavior Behavior;
    MDString *Key;
    Metadata *Val;

    ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V)
        : Behavior(B), Key(K), Val(V) {}
  };

/// @}
/// @name Member Variables
/// @{
private:
  LLVMContext &Context;           ///< The LLVMContext from which types and
                                  ///< constants are allocated.
  GlobalListType GlobalList;      ///< The Global Variables in the module
  FunctionListType FunctionList;  ///< The Functions in the module
  AliasListType AliasList;        ///< The Aliases in the module
  IFuncListType IFuncList;        ///< The IFuncs in the module
  NamedMDListType NamedMDList;    ///< The named metadata in the module
  std::string GlobalScopeAsm;     ///< Inline Asm at global scope.
  std::unique_ptr<ValueSymbolTable> ValSymTab; ///< Symbol table for values
  ComdatSymTabType ComdatSymTab;  ///< Symbol table for COMDATs
  std::unique_ptr<MemoryBuffer>
  OwnedMemoryBuffer;              ///< Memory buffer directly owned by this
                                  ///< module, for legacy clients only.
  std::unique_ptr<GVMaterializer>
  Materializer;                   ///< Used to materialize GlobalValues
  std::string ModuleID;           ///< Human readable identifier for the module
  std::string SourceFileName;     ///< Original source file name for module,
                                  ///< recorded in bitcode.
  std::string TargetTriple;       ///< Platform target triple Module compiled on
                                  ///< Format: (arch)(sub)-(vendor)-(sys0-(abi)
  NamedMDSymTabType NamedMDSymTab;  ///< NamedMDNode names.
  DataLayout DL;                  ///< DataLayout associated with the module
  StringMap<unsigned>
      CurrentIntrinsicIds; ///< Keep track of the current unique id count for
                           ///< the specified intrinsic basename.
  DenseMap<std::pair<Intrinsic::ID, const FunctionType *>, unsigned>
      UniquedIntrinsicNames; ///< Keep track of uniqued names of intrinsics
                             ///< based on unnamed types. The combination of
                             ///< ID and FunctionType maps to the extension that
                             ///< is used to make the intrinsic name unique.

  friend class Constant;

/// @}
/// @name Constructors
/// @{
public:
  /// The Module constructor. Note that there is no default constructor. You
  /// must provide a name for the module upon construction.
  explicit Module(StringRef ModuleID, LLVMContext& C);
  /// The module destructor. This will dropAllReferences.
  ~Module();

/// @}
/// @name Module Level Accessors
/// @{

  /// Get the module identifier which is, essentially, the name of the module.
  /// @returns the module identifier as a string
  const std::string &getModuleIdentifier() const { return ModuleID; }

  /// Returns the number of non-debug IR instructions in the module.
  /// This is equivalent to the sum of the IR instruction counts of each
  /// function contained in the module.
  unsigned getInstructionCount() const;

  /// Get the module's original source file name. When compiling from
  /// bitcode, this is taken from a bitcode record where it was recorded.
  /// For other compiles it is the same as the ModuleID, which would
  /// contain the source file name.
  const std::string &getSourceFileName() const { return SourceFileName; }

  /// Get a short "name" for the module.
  ///
  /// This is useful for debugging or logging. It is essentially a convenience
  /// wrapper around getModuleIdentifier().
  StringRef getName() const { return ModuleID; }

  /// Get the data layout string for the module's target platform. This is
  /// equivalent to getDataLayout()->getStringRepresentation().
  const std::string &getDataLayoutStr() const {
    return DL.getStringRepresentation();
  }

  /// Get the data layout for the module's target platform.
  const DataLayout &getDataLayout() const;

  /// Get the target triple which is a string describing the target host.
  /// @returns a string containing the target triple.
  const std::string &getTargetTriple() const { return TargetTriple; }

  /// Get the global data context.
  /// @returns LLVMContext - a container for LLVM's global information
  LLVMContext &getContext() const { return Context; }

  /// Get any module-scope inline assembly blocks.
  /// @returns a string containing the module-scope inline assembly blocks.
  const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; }

  /// Get a RandomNumberGenerator salted for use with this module. The
  /// RNG can be seeded via -rng-seed=<uint64> and is salted with the
  /// ModuleID and the provided pass salt. The returned RNG should not
  /// be shared across threads or passes.
  ///
  /// A unique RNG per pass ensures a reproducible random stream even
  /// when other randomness consuming passes are added or removed. In
  /// addition, the random stream will be reproducible across LLVM
  /// versions when the pass does not change.
  std::unique_ptr<RandomNumberGenerator> createRNG(const StringRef Name) const;

  /// Return true if size-info optimization remark is enabled, false
  /// otherwise.
  bool shouldEmitInstrCountChangedRemark() {
    return getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled(
        "size-info");
  }

  /// @}
  /// @name Module Level Mutators
  /// @{

  /// Set the module identifier.
  void setModuleIdentifier(StringRef ID) { ModuleID = std::string(ID); }

  /// Set the module's original source file name.
  void setSourceFileName(StringRef Name) { SourceFileName = std::string(Name); }

  /// Set the data layout
  void setDataLayout(StringRef Desc);
  void setDataLayout(const DataLayout &Other);

  /// Set the target triple.
  void setTargetTriple(StringRef T) { TargetTriple = std::string(T); }

  /// Set the module-scope inline assembly blocks.
  /// A trailing newline is added if the input doesn't have one.
  void setModuleInlineAsm(StringRef Asm) {
    GlobalScopeAsm = std::string(Asm);
    if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n')
      GlobalScopeAsm += '\n';
  }

  /// Append to the module-scope inline assembly blocks.
  /// A trailing newline is added if the input doesn't have one.
  void appendModuleInlineAsm(StringRef Asm) {
    GlobalScopeAsm += Asm;
    if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n')
      GlobalScopeAsm += '\n';
  }

/// @}
/// @name Generic Value Accessors
/// @{

  /// Return the global value in the module with the specified name, of
  /// arbitrary type. This method returns null if a global with the specified
  /// name is not found.
  GlobalValue *getNamedValue(StringRef Name) const;

  /// Return the number of global values in the module.
  unsigned getNumNamedValues() const;

  /// Return a unique non-zero ID for the specified metadata kind. This ID is
  /// uniqued across modules in the current LLVMContext.
  unsigned getMDKindID(StringRef Name) const;

  /// Populate client supplied SmallVector with the name for custom metadata IDs
  /// registered in this LLVMContext.
  void getMDKindNames(SmallVectorImpl<StringRef> &Result) const;

  /// Populate client supplied SmallVector with the bundle tags registered in
  /// this LLVMContext.  The bundle tags are ordered by increasing bundle IDs.
  /// \see LLVMContext::getOperandBundleTagID
  void getOperandBundleTags(SmallVectorImpl<StringRef> &Result) const;

  std::vector<StructType *> getIdentifiedStructTypes() const;

  /// Return a unique name for an intrinsic whose mangling is based on an
  /// unnamed type. The Proto represents the function prototype.
  std::string getUniqueIntrinsicName(StringRef BaseName, Intrinsic::ID Id,
                                     const FunctionType *Proto);

/// @}
/// @name Function Accessors
/// @{

  /// Look up the specified function in the module symbol table. Four
  /// possibilities:
  ///   1. If it does not exist, add a prototype for the function and return it.
  ///   2. Otherwise, if the existing function has the correct prototype, return
  ///      the existing function.
  ///   3. Finally, the function exists but has the wrong prototype: return the
  ///      function with a constantexpr cast to the right prototype.
  ///
  /// In all cases, the returned value is a FunctionCallee wrapper around the
  /// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or
  /// the bitcast to the function.
  ///
  /// Note: For library calls getOrInsertLibFunc() should be used instead.
  FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T,
                                     AttributeList AttributeList);

  FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T);

  /// Look up the specified function in the module symbol table. If it does not
  /// exist, add a prototype for the function and return it. This function
  /// guarantees to return a constant of pointer to the specified function type
  /// or a ConstantExpr BitCast of that type if the named function has a
  /// different type. This version of the method takes a list of
  /// function arguments, which makes it easier for clients to use.
  template <typename... ArgsTy>
  FunctionCallee getOrInsertFunction(StringRef Name,
                                     AttributeList AttributeList, Type *RetTy,
                                     ArgsTy... Args) {
    SmallVector<Type*, sizeof...(ArgsTy)> ArgTys{Args...};
    return getOrInsertFunction(Name,
                               FunctionType::get(RetTy, ArgTys, false),
                               AttributeList);
  }

  /// Same as above, but without the attributes.
  template <typename... ArgsTy>
  FunctionCallee getOrInsertFunction(StringRef Name, Type *RetTy,
                                     ArgsTy... Args) {
    return getOrInsertFunction(Name, AttributeList{}, RetTy, Args...);
  }

  // Avoid an incorrect ordering that'd otherwise compile incorrectly.
  template <typename... ArgsTy>
  FunctionCallee
  getOrInsertFunction(StringRef Name, AttributeList AttributeList,
                      FunctionType *Invalid, ArgsTy... Args) = delete;

  /// Look up the specified function in the module symbol table. If it does not
  /// exist, return null.
  Function *getFunction(StringRef Name) const;

/// @}
/// @name Global Variable Accessors
/// @{

  /// Look up the specified global variable in the module symbol table. If it
  /// does not exist, return null. If AllowInternal is set to true, this
  /// function will return types that have InternalLinkage. By default, these
  /// types are not returned.
  GlobalVariable *getGlobalVariable(StringRef Name) const {
    return getGlobalVariable(Name, false);
  }

  GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const;

  GlobalVariable *getGlobalVariable(StringRef Name,
                                    bool AllowInternal = false) {
    return static_cast<const Module *>(this)->getGlobalVariable(Name,
                                                                AllowInternal);
  }

  /// Return the global variable in the module with the specified name, of
  /// arbitrary type. This method returns null if a global with the specified
  /// name is not found.
  const GlobalVariable *getNamedGlobal(StringRef Name) const {
    return getGlobalVariable(Name, true);
  }
  GlobalVariable *getNamedGlobal(StringRef Name) {
    return const_cast<GlobalVariable *>(
                       static_cast<const Module *>(this)->getNamedGlobal(Name));
  }

  /// Look up the specified global in the module symbol table.
  /// If it does not exist, invoke a callback to create a declaration of the
  /// global and return it. The global is constantexpr casted to the expected
  /// type if necessary.
  Constant *
  getOrInsertGlobal(StringRef Name, Type *Ty,
                    function_ref<GlobalVariable *()> CreateGlobalCallback);

  /// Look up the specified global in the module symbol table. If required, this
  /// overload constructs the global variable using its constructor's defaults.
  Constant *getOrInsertGlobal(StringRef Name, Type *Ty);

/// @}
/// @name Global Alias Accessors
/// @{

  /// Return the global alias in the module with the specified name, of
  /// arbitrary type. This method returns null if a global with the specified
  /// name is not found.
  GlobalAlias *getNamedAlias(StringRef Name) const;

/// @}
/// @name Global IFunc Accessors
/// @{

  /// Return the global ifunc in the module with the specified name, of
  /// arbitrary type. This method returns null if a global with the specified
  /// name is not found.
  GlobalIFunc *getNamedIFunc(StringRef Name) const;

/// @}
/// @name Named Metadata Accessors
/// @{

  /// Return the first NamedMDNode in the module with the specified name. This
  /// method returns null if a NamedMDNode with the specified name is not found.
  NamedMDNode *getNamedMetadata(const Twine &Name) const;

  /// Return the named MDNode in the module with the specified name. This method
  /// returns a new NamedMDNode if a NamedMDNode with the specified name is not
  /// found.
  NamedMDNode *getOrInsertNamedMetadata(StringRef Name);

  /// Remove the given NamedMDNode from this module and delete it.
  void eraseNamedMetadata(NamedMDNode *NMD);

/// @}
/// @name Comdat Accessors
/// @{

  /// Return the Comdat in the module with the specified name. It is created
  /// if it didn't already exist.
  Comdat *getOrInsertComdat(StringRef Name);

/// @}
/// @name Module Flags Accessors
/// @{

  /// Returns the module flags in the provided vector.
  void getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const;

  /// Return the corresponding value if Key appears in module flags, otherwise
  /// return null.
  Metadata *getModuleFlag(StringRef Key) const;

  /// Returns the NamedMDNode in the module that represents module-level flags.
  /// This method returns null if there are no module-level flags.
  NamedMDNode *getModuleFlagsMetadata() const;

  /// Returns the NamedMDNode in the module that represents module-level flags.
  /// If module-level flags aren't found, it creates the named metadata that
  /// contains them.
  NamedMDNode *getOrInsertModuleFlagsMetadata();

  /// Add a module-level flag to the module-level flags metadata. It will create
  /// the module-level flags named metadata if it doesn't already exist.
  void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val);
  void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val);
  void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val);
  void addModuleFlag(MDNode *Node);
  /// Like addModuleFlag but replaces the old module flag if it already exists.
  void setModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val);

  /// @}
  /// @name Materialization
  /// @{

  /// Sets the GVMaterializer to GVM. This module must not yet have a
  /// Materializer. To reset the materializer for a module that already has one,
  /// call materializeAll first. Destroying this module will destroy
  /// its materializer without materializing any more GlobalValues. Without
  /// destroying the Module, there is no way to detach or destroy a materializer
  /// without materializing all the GVs it controls, to avoid leaving orphan
  /// unmaterialized GVs.
  void setMaterializer(GVMaterializer *GVM);
  /// Retrieves the GVMaterializer, if any, for this Module.
  GVMaterializer *getMaterializer() const { return Materializer.get(); }
  bool isMaterialized() const { return !getMaterializer(); }

  /// Make sure the GlobalValue is fully read.
  llvm::Error materialize(GlobalValue *GV);

  /// Make sure all GlobalValues in this Module are fully read and clear the
  /// Materializer.
  llvm::Error materializeAll();

  llvm::Error materializeMetadata();

/// @}
/// @name Direct access to the globals list, functions list, and symbol table
/// @{

  /// Get the Module's list of global variables (constant).
  const GlobalListType   &getGlobalList() const       { return GlobalList; }
  /// Get the Module's list of global variables.
  GlobalListType         &getGlobalList()             { return GlobalList; }

  static GlobalListType Module::*getSublistAccess(GlobalVariable*) {
    return &Module::GlobalList;
  }

  /// Get the Module's list of functions (constant).
  const FunctionListType &getFunctionList() const     { return FunctionList; }
  /// Get the Module's list of functions.
  FunctionListType       &getFunctionList()           { return FunctionList; }
  static FunctionListType Module::*getSublistAccess(Function*) {
    return &Module::FunctionList;
  }

  /// Get the Module's list of aliases (constant).
  const AliasListType    &getAliasList() const        { return AliasList; }
  /// Get the Module's list of aliases.
  AliasListType          &getAliasList()              { return AliasList; }

  static AliasListType Module::*getSublistAccess(GlobalAlias*) {
    return &Module::AliasList;
  }

  /// Get the Module's list of ifuncs (constant).
  const IFuncListType    &getIFuncList() const        { return IFuncList; }
  /// Get the Module's list of ifuncs.
  IFuncListType          &getIFuncList()              { return IFuncList; }

  static IFuncListType Module::*getSublistAccess(GlobalIFunc*) {
    return &Module::IFuncList;
  }

  /// Get the Module's list of named metadata (constant).
  const NamedMDListType  &getNamedMDList() const      { return NamedMDList; }
  /// Get the Module's list of named metadata.
  NamedMDListType        &getNamedMDList()            { return NamedMDList; }

  static NamedMDListType Module::*getSublistAccess(NamedMDNode*) {
    return &Module::NamedMDList;
  }

  /// Get the symbol table of global variable and function identifiers
  const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; }
  /// Get the Module's symbol table of global variable and function identifiers.
  ValueSymbolTable       &getValueSymbolTable()       { return *ValSymTab; }

  /// Get the Module's symbol table for COMDATs (constant).
  const ComdatSymTabType &getComdatSymbolTable() const { return ComdatSymTab; }
  /// Get the Module's symbol table for COMDATs.
  ComdatSymTabType &getComdatSymbolTable() { return ComdatSymTab; }

/// @}
/// @name Global Variable Iteration
/// @{

  global_iterator       global_begin()       { return GlobalList.begin(); }
  const_global_iterator global_begin() const { return GlobalList.begin(); }
  global_iterator       global_end  ()       { return GlobalList.end(); }
  const_global_iterator global_end  () const { return GlobalList.end(); }
  size_t                global_size () const { return GlobalList.size(); }
  bool                  global_empty() const { return GlobalList.empty(); }

  iterator_range<global_iterator> globals() {
    return make_range(global_begin(), global_end());
  }
  iterator_range<const_global_iterator> globals() const {
    return make_range(global_begin(), global_end());
  }

/// @}
/// @name Function Iteration
/// @{

  iterator                begin()       { return FunctionList.begin(); }
  const_iterator          begin() const { return FunctionList.begin(); }
  iterator                end  ()       { return FunctionList.end();   }
  const_iterator          end  () const { return FunctionList.end();   }
  reverse_iterator        rbegin()      { return FunctionList.rbegin(); }
  const_reverse_iterator  rbegin() const{ return FunctionList.rbegin(); }
  reverse_iterator        rend()        { return FunctionList.rend(); }
  const_reverse_iterator  rend() const  { return FunctionList.rend(); }
  size_t                  size() const  { return FunctionList.size(); }
  bool                    empty() const { return FunctionList.empty(); }

  iterator_range<iterator> functions() {
    return make_range(begin(), end());
  }
  iterator_range<const_iterator> functions() const {
    return make_range(begin(), end());
  }

/// @}
/// @name Alias Iteration
/// @{

  alias_iterator       alias_begin()            { return AliasList.begin(); }
  const_alias_iterator alias_begin() const      { return AliasList.begin(); }
  alias_iterator       alias_end  ()            { return AliasList.end();   }
  const_alias_iterator alias_end  () const      { return AliasList.end();   }
  size_t               alias_size () const      { return AliasList.size();  }
  bool                 alias_empty() const      { return AliasList.empty(); }

  iterator_range<alias_iterator> aliases() {
    return make_range(alias_begin(), alias_end());
  }
  iterator_range<const_alias_iterator> aliases() const {
    return make_range(alias_begin(), alias_end());
  }

/// @}
/// @name IFunc Iteration
/// @{

  ifunc_iterator       ifunc_begin()            { return IFuncList.begin(); }
  const_ifunc_iterator ifunc_begin() const      { return IFuncList.begin(); }
  ifunc_iterator       ifunc_end  ()            { return IFuncList.end();   }
  const_ifunc_iterator ifunc_end  () const      { return IFuncList.end();   }
  size_t               ifunc_size () const      { return IFuncList.size();  }
  bool                 ifunc_empty() const      { return IFuncList.empty(); }

  iterator_range<ifunc_iterator> ifuncs() {
    return make_range(ifunc_begin(), ifunc_end());
  }
  iterator_range<const_ifunc_iterator> ifuncs() const {
    return make_range(ifunc_begin(), ifunc_end());
  }

  /// @}
  /// @name Convenience iterators
  /// @{

  using global_object_iterator =
      concat_iterator<GlobalObject, iterator, global_iterator>;
  using const_global_object_iterator =
      concat_iterator<const GlobalObject, const_iterator,
                      const_global_iterator>;

  iterator_range<global_object_iterator> global_objects();
  iterator_range<const_global_object_iterator> global_objects() const;

  using global_value_iterator =
      concat_iterator<GlobalValue, iterator, global_iterator, alias_iterator,
                      ifunc_iterator>;
  using const_global_value_iterator =
      concat_iterator<const GlobalValue, const_iterator, const_global_iterator,
                      const_alias_iterator, const_ifunc_iterator>;

  iterator_range<global_value_iterator> global_values();
  iterator_range<const_global_value_iterator> global_values() const;

  /// @}
  /// @name Named Metadata Iteration
  /// @{

  named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); }
  const_named_metadata_iterator named_metadata_begin() const {
    return NamedMDList.begin();
  }

  named_metadata_iterator named_metadata_end() { return NamedMDList.end(); }
  const_named_metadata_iterator named_metadata_end() const {
    return NamedMDList.end();
  }

  size_t named_metadata_size() const { return NamedMDList.size();  }
  bool named_metadata_empty() const { return NamedMDList.empty(); }

  iterator_range<named_metadata_iterator> named_metadata() {
    return make_range(named_metadata_begin(), named_metadata_end());
  }
  iterator_range<const_named_metadata_iterator> named_metadata() const {
    return make_range(named_metadata_begin(), named_metadata_end());
  }

  /// An iterator for DICompileUnits that skips those marked NoDebug.
  class debug_compile_units_iterator {
    NamedMDNode *CUs;
    unsigned Idx;

    void SkipNoDebugCUs();

  public:
    using iterator_category = std::input_iterator_tag;
    using value_type = DICompileUnit *;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type *;
    using reference = value_type &;

    explicit debug_compile_units_iterator(NamedMDNode *CUs, unsigned Idx)
        : CUs(CUs), Idx(Idx) {
      SkipNoDebugCUs();
    }

    debug_compile_units_iterator &operator++() {
      ++Idx;
      SkipNoDebugCUs();
      return *this;
    }

    debug_compile_units_iterator operator++(int) {
      debug_compile_units_iterator T(*this);
      ++Idx;
      return T;
    }

    bool operator==(const debug_compile_units_iterator &I) const {
      return Idx == I.Idx;
    }

    bool operator!=(const debug_compile_units_iterator &I) const {
      return Idx != I.Idx;
    }

    DICompileUnit *operator*() const;
    DICompileUnit *operator->() const;
  };

  debug_compile_units_iterator debug_compile_units_begin() const {
    auto *CUs = getNamedMetadata("llvm.dbg.cu");
    return debug_compile_units_iterator(CUs, 0);
  }

  debug_compile_units_iterator debug_compile_units_end() const {
    auto *CUs = getNamedMetadata("llvm.dbg.cu");
    return debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0);
  }

  /// Return an iterator for all DICompileUnits listed in this Module's
  /// llvm.dbg.cu named metadata node and aren't explicitly marked as
  /// NoDebug.
  iterator_range<debug_compile_units_iterator> debug_compile_units() const {
    auto *CUs = getNamedMetadata("llvm.dbg.cu");
    return make_range(
        debug_compile_units_iterator(CUs, 0),
        debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0));
  }
/// @}

  /// Destroy ConstantArrays in LLVMContext if they are not used.
  /// ConstantArrays constructed during linking can cause quadratic memory
  /// explosion. Releasing all unused constants can cause a 20% LTO compile-time
  /// slowdown for a large application.
  ///
  /// NOTE: Constants are currently owned by LLVMContext. This can then only
  /// be called where all uses of the LLVMContext are understood.
  void dropTriviallyDeadConstantArrays();

/// @name Utility functions for printing and dumping Module objects
/// @{

  /// Print the module to an output stream with an optional
  /// AssemblyAnnotationWriter.  If \c ShouldPreserveUseListOrder, then include
  /// uselistorder directives so that use-lists can be recreated when reading
  /// the assembly.
  void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW,
             bool ShouldPreserveUseListOrder = false,
             bool IsForDebug = false) const;

  /// Dump the module to stderr (for debugging).
  void dump() const;

  /// This function causes all the subinstructions to "let go" of all references
  /// that they are maintaining.  This allows one to 'delete' a whole class at
  /// a time, even though there may be circular references... first all
  /// references are dropped, and all use counts go to zero.  Then everything
  /// is delete'd for real.  Note that no operations are valid on an object
  /// that has "dropped all references", except operator delete.
  void dropAllReferences();

/// @}
/// @name Utility functions for querying Debug information.
/// @{

  /// Returns the Number of Register ParametersDwarf Version by checking
  /// module flags.
  unsigned getNumberRegisterParameters() const;

  /// Returns the Dwarf Version by checking module flags.
  unsigned getDwarfVersion() const;

  /// Returns the DWARF format by checking module flags.
  bool isDwarf64() const;

  /// Returns the CodeView Version by checking module flags.
  /// Returns zero if not present in module.
  unsigned getCodeViewFlag() const;

/// @}
/// @name Utility functions for querying and setting PIC level
/// @{

  /// Returns the PIC level (small or large model)
  PICLevel::Level getPICLevel() const;

  /// Set the PIC level (small or large model)
  void setPICLevel(PICLevel::Level PL);
/// @}

/// @}
/// @name Utility functions for querying and setting PIE level
/// @{

  /// Returns the PIE level (small or large model)
  PIELevel::Level getPIELevel() const;

  /// Set the PIE level (small or large model)
  void setPIELevel(PIELevel::Level PL);
/// @}

  /// @}
  /// @name Utility function for querying and setting code model
  /// @{

  /// Returns the code model (tiny, small, kernel, medium or large model)
  std::optional<CodeModel::Model> getCodeModel() const;

  /// Set the code model (tiny, small, kernel, medium or large)
  void setCodeModel(CodeModel::Model CL);
  /// @}

  /// @name Utility functions for querying and setting PGO summary
  /// @{

  /// Attach profile summary metadata to this module.
  void setProfileSummary(Metadata *M, ProfileSummary::Kind Kind);

  /// Returns profile summary metadata. When IsCS is true, use the context
  /// sensitive profile summary.
  Metadata *getProfileSummary(bool IsCS) const;
  /// @}

  /// Returns whether semantic interposition is to be respected.
  bool getSemanticInterposition() const;

  /// Set whether semantic interposition is to be respected.
  void setSemanticInterposition(bool);

  /// Returns true if PLT should be avoided for RTLib calls.
  bool getRtLibUseGOT() const;

  /// Set that PLT should be avoid for RTLib calls.
  void setRtLibUseGOT();

  /// Get/set whether synthesized functions should get the uwtable attribute.
  UWTableKind getUwtable() const;
  void setUwtable(UWTableKind Kind);

  /// Get/set whether synthesized functions should get the "frame-pointer"
  /// attribute.
  FramePointerKind getFramePointer() const;
  void setFramePointer(FramePointerKind Kind);

  /// Get/set what kind of stack protector guard to use.
  StringRef getStackProtectorGuard() const;
  void setStackProtectorGuard(StringRef Kind);

  /// Get/set which register to use as the stack protector guard register. The
  /// empty string is equivalent to "global". Other values may be "tls" or
  /// "sysreg".
  StringRef getStackProtectorGuardReg() const;
  void setStackProtectorGuardReg(StringRef Reg);

  /// Get/set a symbol to use as the stack protector guard.
  StringRef getStackProtectorGuardSymbol() const;
  void setStackProtectorGuardSymbol(StringRef Symbol);

  /// Get/set what offset from the stack protector to use.
  int getStackProtectorGuardOffset() const;
  void setStackProtectorGuardOffset(int Offset);

  /// Get/set the stack alignment overridden from the default.
  unsigned getOverrideStackAlignment() const;
  void setOverrideStackAlignment(unsigned Align);

  /// @name Utility functions for querying and setting the build SDK version
  /// @{

  /// Attach a build SDK version metadata to this module.
  void setSDKVersion(const VersionTuple &V);

  /// Get the build SDK version metadata.
  ///
  /// An empty version is returned if no such metadata is attached.
  VersionTuple getSDKVersion() const;
  /// @}

  /// Take ownership of the given memory buffer.
  void setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB);

  /// Set the partial sample profile ratio in the profile summary module flag,
  /// if applicable.
  void setPartialSampleProfileRatio(const ModuleSummaryIndex &Index);

  /// Get the target variant triple which is a string describing a variant of
  /// the target host platform. For example, Mac Catalyst can be a variant
  /// target triple for a macOS target.
  /// @returns a string containing the target variant triple.
  StringRef getDarwinTargetVariantTriple() const;

  /// Set the target variant triple which is a string describing a variant of
  /// the target host platform.
  void setDarwinTargetVariantTriple(StringRef T);

  /// Get the target variant version build SDK version metadata.
  ///
  /// An empty version is returned if no such metadata is attached.
  VersionTuple getDarwinTargetVariantSDKVersion() const;

  /// Set the target variant version build SDK version metadata.
  void setDarwinTargetVariantSDKVersion(VersionTuple Version);
};

/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the
/// initializer elements of that global in a SmallVector and return the global
/// itself.
GlobalVariable *collectUsedGlobalVariables(const Module &M,
                                           SmallVectorImpl<GlobalValue *> &Vec,
                                           bool CompilerUsed);

/// An raw_ostream inserter for modules.
inline raw_ostream &operator<<(raw_ostream &O, const Module &M) {
  M.print(O, nullptr);
  return O;
}

// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef)

/* LLVMModuleProviderRef exists for historical reasons, but now just holds a
 * Module.
 */
inline Module *unwrap(LLVMModuleProviderRef MP) {
  return reinterpret_cast<Module*>(MP);
}

} // end namespace llvm

#endif // LLVM_IR_MODULE_H

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif