clang_decl.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_
  6. #include <concepts>
  7. #include "clang/AST/Decl.h"
  8. #include "common/hashtable_key_context.h"
  9. #include "common/ostream.h"
  10. #include "toolchain/base/canonical_value_store.h"
  11. #include "toolchain/sem_ir/ids.h"
  12. namespace Carbon::SemIR {
  13. // A key describing a Clang declaration that can be looked up in the value
  14. // store. This is a `clang::Decl*` pointing to a canonical declaration, plus any
  15. // other information that affects the mapping into Carbon. Currently this
  16. // includes the number of imported parameters for a function with default
  17. // arguments.
  18. //
  19. // A canonical declaration pointer is used so that we can perform direct address
  20. // comparisons and hash this structure based on its contents.
  21. struct ClangDeclKey : public Printable<ClangDeclKey> {
  22. // Information about how to form the Carbon function signature from the Clang
  23. // function declaration.
  24. struct Signature {
  25. enum Kind : int8_t {
  26. // A normal function signature: each C++ parameter maps into a Carbon
  27. // parameter.
  28. Normal,
  29. // A function signature taking a tuple pattern that contains the C++
  30. // parameters. This is used when importing a constructor that is used for
  31. // list initialization from a Carbon tuple.
  32. TuplePattern,
  33. };
  34. // The kind of function signature being imported.
  35. Kind kind = Normal;
  36. // The number of parameters to import. This can be less than the number of
  37. // parameters in the Clang declaration if the Clang declaration has default
  38. // arguments. Excludes the implicit object parameter, if there is one.
  39. int32_t num_params = -1;
  40. friend auto operator==(const Signature& lhs, const Signature& rhs)
  41. -> bool = default;
  42. };
  43. // For declaration classes that are unrelated to FunctionDecl, no parameter
  44. // count is expected.
  45. template <typename DeclT>
  46. requires(std::derived_from<DeclT, clang::Decl> &&
  47. !std::derived_from<clang::FunctionDecl, DeclT> &&
  48. !std::derived_from<DeclT, clang::FunctionDecl>)
  49. explicit ClangDeclKey(DeclT* decl)
  50. : ClangDeclKey(decl, Signature{}, UncheckedTag()) {}
  51. // For declaration classes that are derived from FunctionDecl, a parameter
  52. // count is required.
  53. static auto ForFunctionDecl(clang::FunctionDecl* decl, Signature signature)
  54. -> ClangDeclKey {
  55. return ClangDeclKey(decl, signature, UncheckedTag());
  56. }
  57. // Factory function for clang declaration that is dynamically known to not be
  58. // a function declaration.
  59. static auto ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey {
  60. CARBON_CHECK(!isa<clang::FunctionDecl>(decl));
  61. return ClangDeclKey(decl, Signature{}, UncheckedTag());
  62. }
  63. auto Print(llvm::raw_ostream& out) const -> void;
  64. auto operator==(const ClangDeclKey& rhs) const -> bool {
  65. return decl == rhs.decl && signature == rhs.signature;
  66. }
  67. // Hashing for ClangDecl. See common/hashing.h.
  68. friend auto CarbonHashValue(const ClangDeclKey& value, uint64_t seed)
  69. -> HashCode {
  70. // Manual hashing support is required because `Signature` has padding.
  71. return HashValue(std::tuple{value.decl, value.signature.num_params,
  72. value.signature.kind},
  73. seed);
  74. }
  75. // The Clang declaration pointing to the Clang AST.
  76. // TODO: Ensure we can easily serialize/deserialize this. Consider
  77. // `clang::LazyDeclPtr`.
  78. clang::Decl* decl;
  79. // The parameters to import for a function declaration. Otherwise a
  80. // default-constructed value.
  81. Signature signature;
  82. private:
  83. struct UncheckedTag {
  84. explicit UncheckedTag() = default;
  85. };
  86. ClangDeclKey(clang::Decl* decl, Signature signature, UncheckedTag /*_*/)
  87. : decl(decl->getCanonicalDecl()), signature(signature) {}
  88. };
  89. // A Clang declaration mapped to a Carbon instruction.
  90. //
  91. // Instances of this type are managed by a `ClangDeclStore`, which ensures that
  92. // a single `ClangDecl` exists for each `ClangDeclKey` used.
  93. struct ClangDecl : public Printable<ClangDecl> {
  94. auto Print(llvm::raw_ostream& out) const -> void;
  95. // The key by which this declaration can be looked up.
  96. ClangDeclKey key;
  97. // The instruction the Clang declaration is mapped to.
  98. InstId inst_id;
  99. auto GetAsKey() const -> ClangDeclKey { return key; }
  100. };
  101. // Canonical storage for `ClangDecl`s. Provides bidirectional mapping
  102. // between `ClangDeclId`s and `InstId`s.
  103. class ClangDeclStore {
  104. public:
  105. explicit ClangDeclStore(CheckIRId check_ir_id);
  106. // Adds a `ClangDecl`, returning an ID to reference it.
  107. auto Add(ClangDecl value) -> ClangDeclId;
  108. // Looks up a `ClangDecl` by `ClangDeclId`.
  109. auto Get(ClangDeclId id) const -> const ClangDecl& { return values_.Get(id); }
  110. // Looks up a `ClangDeclId` by `ClangDeclKey`.
  111. auto Lookup(ClangDeclKey key) const -> ClangDeclId;
  112. // Looks up a `ClangDeclId` by `InstId`.
  113. auto Lookup(InstId inst_id) const -> ClangDeclId;
  114. auto OutputYaml() const -> Yaml::OutputMapping;
  115. auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
  116. -> void;
  117. private:
  118. // Canonical storage for `ClangDecl`s. Allows mapping from a
  119. // `ClangDeclId` to an `InstId`.
  120. CanonicalValueStore<ClangDeclId, ClangDeclKey, Tag<CheckIRId>, ClangDecl>
  121. values_;
  122. // Map from `InstId` to `ClangDeclId`.
  123. Map<InstId, ClangDeclId> inst_id_to_clang_decl_id_;
  124. };
  125. } // namespace Carbon::SemIR
  126. #endif // CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_