mangler.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. #include "toolchain/sem_ir/mangler.h"
  5. #include <string>
  6. #include "common/raw_string_ostream.h"
  7. #include "toolchain/base/kind_switch.h"
  8. #include "toolchain/sem_ir/entry_point.h"
  9. #include "toolchain/sem_ir/ids.h"
  10. #include "toolchain/sem_ir/pattern.h"
  11. #include "toolchain/sem_ir/specific_interface.h"
  12. #include "toolchain/sem_ir/specific_named_constraint.h"
  13. #include "toolchain/sem_ir/typed_insts.h"
  14. namespace Carbon::SemIR {
  15. auto Mangler::MangleNameId(llvm::raw_ostream& os, SemIR::NameId name_id)
  16. -> void {
  17. CARBON_CHECK(name_id.AsIdentifierId().has_value(),
  18. "Mangling non-identifier name {0}", name_id);
  19. os << names().GetAsStringIfIdentifier(name_id);
  20. }
  21. auto Mangler::MangleInverseQualifiedNameScope(llvm::raw_ostream& os,
  22. SemIR::NameScopeId name_scope_id)
  23. -> void {
  24. // Maintain a stack of names for delayed rendering of interface impls.
  25. struct NameEntry {
  26. SemIR::NameScopeId name_scope_id;
  27. SemIR::SpecificId specific_id;
  28. // The prefix emitted before this name component. If '\0', no prefix will be
  29. // emitted.
  30. // - Namespace components are separated by '.'.
  31. // - The two components of an interface are separated by ':'.
  32. char prefix;
  33. };
  34. llvm::SmallVector<NameEntry> names_to_render;
  35. names_to_render.push_back({.name_scope_id = name_scope_id,
  36. .specific_id = SemIR::SpecificId::None,
  37. .prefix = '.'});
  38. while (!names_to_render.empty()) {
  39. auto [name_scope_id, specific_id, prefix] = names_to_render.pop_back_val();
  40. if (!name_scope_id.has_value()) {
  41. // TODO: Include something in the mangling to identify the scope for a
  42. // function-local class, function, or similar. We may need to number
  43. // these within the enclosing function, as their name need not be unique.
  44. os << ":enclosed";
  45. continue;
  46. }
  47. if (prefix) {
  48. os << prefix;
  49. }
  50. if (name_scope_id == SemIR::NameScopeId::Package) {
  51. auto package_id = sem_ir().package_id();
  52. if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) {
  53. os << sem_ir().identifiers().Get(ident_id);
  54. } else {
  55. // TODO: Handle name conflicts between special package names and raw
  56. // identifier package names. Note that any change here will also require
  57. // a change to namespace mangling for imported packages.
  58. os << package_id.AsSpecialName();
  59. }
  60. continue;
  61. }
  62. const auto& name_scope = sem_ir().name_scopes().Get(name_scope_id);
  63. CARBON_KIND_SWITCH(sem_ir().insts().Get(name_scope.inst_id())) {
  64. case CARBON_KIND(SemIR::ImplDecl impl_decl): {
  65. const auto& impl = sem_ir().impls().Get(impl_decl.impl_id);
  66. auto facet_type = insts().GetAs<SemIR::FacetType>(
  67. constant_values().GetConstantInstId(impl.constraint_id));
  68. auto identified_facet_type_id =
  69. sem_ir().identified_facet_types().Lookup(
  70. {.facet_type_id = facet_type.facet_type_id,
  71. .self_const_id =
  72. sem_ir().constant_values().Get(impl.self_id)});
  73. CARBON_CHECK(identified_facet_type_id.has_value(),
  74. "ImplDecl with unidentified facet type constraint");
  75. const auto& identified =
  76. sem_ir().identified_facet_types().Get(identified_facet_type_id);
  77. auto impl_target = identified.impl_as_target_interface();
  78. const auto& interface =
  79. sem_ir().interfaces().Get(impl_target.interface_id);
  80. names_to_render.push_back(
  81. // We mangle names in an interface without `Self` in the specific
  82. // since it would just add noise and `Self` is not part of how you
  83. // name the entities syntactically.
  84. {.name_scope_id = interface.scope_without_self_id,
  85. .specific_id = impl_target.specific_id,
  86. .prefix = ':'});
  87. auto self_const_inst_id =
  88. constant_values().GetConstantInstId(impl.self_id);
  89. auto self_inst = insts().Get(self_const_inst_id);
  90. CARBON_KIND_SWITCH(self_inst) {
  91. case CARBON_KIND(SemIR::ClassType class_type): {
  92. const auto& class_info =
  93. sem_ir().classes().Get(class_type.class_id);
  94. names_to_render.push_back(
  95. {.name_scope_id = class_info.parent_scope_id,
  96. .specific_id = class_type.specific_id,
  97. .prefix = '.'});
  98. MangleUnqualifiedClass(os, class_info, class_type.specific_id);
  99. break;
  100. }
  101. case SemIR::AutoType::Kind:
  102. case SemIR::BoolType::Kind:
  103. case SemIR::BoundMethodType::Kind:
  104. case SemIR::FloatLiteralType::Kind:
  105. case SemIR::IntLiteralType::Kind:
  106. case SemIR::NamespaceType::Kind:
  107. case SemIR::RequireSpecificDefinitionType::Kind:
  108. case SemIR::SpecificFunctionType::Kind:
  109. case SemIR::TypeType::Kind:
  110. case SemIR::VtableType::Kind:
  111. case SemIR::WitnessType::Kind: {
  112. os << self_inst.kind().ir_name();
  113. break;
  114. }
  115. case CARBON_KIND(SemIR::IntType int_type): {
  116. os << (int_type.int_kind == SemIR::IntKind::Signed ? "i" : "u")
  117. << sem_ir().ints().Get(
  118. sem_ir()
  119. .insts()
  120. .GetAs<SemIR::IntValue>(int_type.bit_width_id)
  121. .int_id);
  122. break;
  123. }
  124. default: {
  125. // Fall back to including a fingerprint.
  126. llvm::write_hex(
  127. os, fingerprinter_.GetOrCompute(&sem_ir(), self_const_inst_id),
  128. llvm::HexPrintStyle::Lower, 16);
  129. break;
  130. }
  131. }
  132. // Skip the tail of the loop that adds the parent name scope to the
  133. // stack - the scope in which the impl was defined is not part of the
  134. // mangling, the constraint and interface alone uniquelify identify an
  135. // impl.
  136. continue;
  137. }
  138. case CARBON_KIND(SemIR::ClassDecl class_decl): {
  139. MangleUnqualifiedClass(os, sem_ir().classes().Get(class_decl.class_id),
  140. specific_id);
  141. break;
  142. }
  143. case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
  144. MangleNameId(
  145. os, sem_ir().interfaces().Get(interface_decl.interface_id).name_id);
  146. MangleSpecificId(os, specific_id);
  147. break;
  148. }
  149. case SemIR::Namespace::Kind: {
  150. os << names().GetIRBaseName(name_scope.name_id());
  151. break;
  152. }
  153. default:
  154. CARBON_FATAL("Attempting to mangle unsupported SemIR.");
  155. break;
  156. }
  157. if (!name_scope.is_imported_package()) {
  158. names_to_render.push_back({.name_scope_id = name_scope.parent_scope_id(),
  159. .specific_id = SemIR::SpecificId::None,
  160. .prefix = '.'});
  161. }
  162. }
  163. }
  164. auto Mangler::Mangle(SemIR::FunctionId function_id,
  165. SemIR::SpecificId specific_id) -> std::string {
  166. const auto& function = sem_ir().functions().Get(function_id);
  167. if (SemIR::IsEntryPoint(sem_ir(), function_id)) {
  168. CARBON_CHECK(!specific_id.has_value(), "entry point should not be generic");
  169. return "main";
  170. }
  171. // Clang should emit C++ function declarations for us.
  172. CARBON_CHECK(!function.clang_decl_id.has_value(),
  173. "Shouldn't mangle C++ function");
  174. RawStringOstream os;
  175. os << "_C";
  176. MangleNameId(os, function.name_id);
  177. // For a special function, add a marker to disambiguate.
  178. switch (function.special_function_kind) {
  179. case SemIR::Function::SpecialFunctionKind::None:
  180. case SemIR::Function::SpecialFunctionKind::CppThunk:
  181. break;
  182. case SemIR::Function::SpecialFunctionKind::CoreWitness:
  183. os << ".";
  184. llvm::write_hex(
  185. os, fingerprinter_.GetOrCompute(&sem_ir(), function.self_param_id),
  186. llvm::HexPrintStyle::Lower, 16);
  187. os << ":core";
  188. break;
  189. case SemIR::Function::SpecialFunctionKind::Thunk:
  190. os << ":thunk";
  191. break;
  192. case SemIR::Function::SpecialFunctionKind::Builtin:
  193. CARBON_FATAL("Attempting to mangle declaration of builtin function {0}",
  194. function.builtin_function_kind());
  195. case SemIR::Function::SpecialFunctionKind::HasCppThunk:
  196. CARBON_FATAL("C++ functions should have been handled earlier");
  197. }
  198. // TODO: If the function is private, also include the library name as part of
  199. // the mangling.
  200. MangleInverseQualifiedNameScope(os, function.parent_scope_id);
  201. MangleSpecificId(os, specific_id);
  202. return os.TakeStr();
  203. }
  204. auto Mangler::MangleSpecificId(llvm::raw_ostream& os,
  205. SemIR::SpecificId specific_id) -> void {
  206. // TODO: Add proper support for mangling generic entities. For now we use a
  207. // fingerprint of the specific arguments, which should be stable across files,
  208. // but isn't necessarily stable across toolchain changes.
  209. if (specific_id.has_value()) {
  210. os << ".";
  211. llvm::write_hex(
  212. os,
  213. fingerprinter_.GetOrCompute(
  214. &sem_ir(), sem_ir().specifics().Get(specific_id).args_id),
  215. llvm::HexPrintStyle::Lower, 16);
  216. }
  217. }
  218. auto Mangler::MangleGlobalVariable(SemIR::InstId pattern_id) -> std::string {
  219. // Use the name of the first binding in the variable as its mangled name.
  220. auto var_name_id =
  221. SemIR::GetFirstBindingNameFromPatternId(sem_ir(), pattern_id);
  222. if (!var_name_id.has_value()) {
  223. return std::string();
  224. }
  225. CARBON_CHECK(!sem_ir()
  226. .cpp_global_vars()
  227. .Lookup({.entity_name_id = var_name_id})
  228. .has_value(),
  229. "Mangling a C++ variable");
  230. RawStringOstream os;
  231. os << "_C";
  232. auto var_name = sem_ir().entity_names().Get(var_name_id);
  233. MangleNameId(os, var_name.name_id);
  234. // TODO: If the variable is private, also include the library name as part of
  235. // the mangling.
  236. MangleInverseQualifiedNameScope(os, var_name.parent_scope_id);
  237. return os.TakeStr();
  238. }
  239. auto Mangler::MangleVTable(const SemIR::Class& class_info,
  240. SemIR::SpecificId specific_id) -> std::string {
  241. RawStringOstream os;
  242. os << "_C";
  243. MangleNameId(os, class_info.name_id);
  244. // TODO: If the class is private, also include the library name as part of the
  245. // mangling.
  246. MangleInverseQualifiedNameScope(os, class_info.parent_scope_id);
  247. os << ".$vtable";
  248. MangleSpecificId(os, specific_id);
  249. return os.TakeStr();
  250. }
  251. auto Mangler::MangleUnqualifiedClass(llvm::raw_ostream& os,
  252. const SemIR::Class& class_info,
  253. SemIR::SpecificId specific_id) -> void {
  254. MangleNameId(os, class_info.name_id);
  255. MangleSpecificId(os, specific_id);
  256. }
  257. } // namespace Carbon::SemIR