inst.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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/inst.h"
  5. #include <utility>
  6. #include "toolchain/sem_ir/file.h"
  7. namespace Carbon::SemIR {
  8. auto Inst::Print(llvm::raw_ostream& out) const -> void {
  9. out << "{kind: " << kind();
  10. auto print_args = [&](auto info) {
  11. using Info = decltype(info);
  12. if constexpr (Info::NumArgs > 0) {
  13. out << ", arg0: " << FromRaw<typename Info::template ArgType<0>>(arg0_);
  14. }
  15. if constexpr (Info::NumArgs > 1) {
  16. out << ", arg1: " << FromRaw<typename Info::template ArgType<1>>(arg1_);
  17. }
  18. };
  19. switch (kind()) {
  20. #define CARBON_SEM_IR_INST_KIND(Name) \
  21. case Name::Kind: \
  22. print_args(Internal::InstLikeTypeInfo<Name>()); \
  23. break;
  24. #include "toolchain/sem_ir/inst_kind.def"
  25. }
  26. if (type_id_.has_value()) {
  27. out << ", type: " << type_id_;
  28. }
  29. out << "}";
  30. }
  31. // Returns the IdKind of an instruction's argument, or None if there is no
  32. // argument with that index.
  33. template <typename InstKind, int ArgIndex>
  34. static constexpr auto IdKindFor() -> IdKind {
  35. using Info = Internal::InstLikeTypeInfo<InstKind>;
  36. if constexpr (ArgIndex < Info::NumArgs) {
  37. return IdKind::For<typename Info::template ArgType<ArgIndex>>;
  38. } else {
  39. return IdKind::None;
  40. }
  41. }
  42. const std::pair<IdKind, IdKind> Inst::ArgKindTable[] = {
  43. #define CARBON_SEM_IR_INST_KIND(Name) \
  44. {IdKindFor<Name, 0>(), IdKindFor<Name, 1>()},
  45. #include "toolchain/sem_ir/inst_kind.def"
  46. };
  47. InstStore::InstStore(File* file, int32_t reserved_inst_ids)
  48. : file_(file), values_(file->check_ir_id(), reserved_inst_ids) {}
  49. auto InstStore::GetUnattachedType(TypeId type_id) const -> TypeId {
  50. return file_->types().GetUnattachedType(type_id);
  51. }
  52. // Returns whether the imported and local instruction kinds are compatible.
  53. // Instruction kinds are compatible when the kinds are the same, or when the
  54. // imported kind is intentionally transformed into the local kind. For example,
  55. // imports form namespace-like entries in their original IR, and are imported
  56. // as namespaces locally.
  57. static auto HasCompatibleImportedInstKind(InstKind imported_kind,
  58. InstKind local_kind) -> bool {
  59. if (imported_kind == local_kind) {
  60. return true;
  61. }
  62. if (imported_kind == ImportDecl::Kind && local_kind == Namespace::Kind) {
  63. // Namespace node kinds should be a superset of ImportDecl node kinds.
  64. static_assert(
  65. std::is_convertible_v<decltype(ImportDecl::Kind)::TypedNodeId,
  66. decltype(Namespace::Kind)::TypedNodeId>);
  67. return true;
  68. }
  69. return false;
  70. }
  71. auto LocIdAndInst::RuntimeVerified(const File& file, LocId loc_id, Inst inst)
  72. -> LocIdAndInst {
  73. switch (loc_id.kind()) {
  74. case LocId::Kind::ImportIRInstId: {
  75. CARBON_CHECK(!IsSingletonInstKind(inst.kind()),
  76. "Should never import builtins/singletons: {0}", inst);
  77. if (inst.IsOneOf<ImportRefLoaded, ImportRefUnloaded>()) {
  78. // These don't represent the in-use `InstKind`, so should not be
  79. // validated.
  80. break;
  81. }
  82. const auto& import_ir_inst =
  83. file.import_ir_insts().Get(loc_id.import_ir_inst_id());
  84. // We don't require a matching node kind if the location is in C++,
  85. // because there isn't a node.
  86. if (import_ir_inst.ir_id() == ImportIRId::Cpp) {
  87. break;
  88. }
  89. const auto* import_ir =
  90. file.import_irs().Get(import_ir_inst.ir_id()).sem_ir;
  91. auto imported_kind =
  92. import_ir->insts().Get(import_ir_inst.inst_id()).kind();
  93. CARBON_CHECK(HasCompatibleImportedInstKind(imported_kind, inst.kind()),
  94. "Unexpected imported `InstKind` {0} for {1}", imported_kind,
  95. inst);
  96. break;
  97. }
  98. case LocId::Kind::InstId:
  99. // TODO: Figure out right verification.
  100. break;
  101. case LocId::Kind::NodeId: {
  102. auto node_kind = file.parse_tree().node_kind(loc_id.node_id());
  103. CARBON_CHECK(inst.kind().IsAllowedNodeKind(node_kind),
  104. "Unexpected `NodeKind` {0} for {1}", node_kind, inst);
  105. break;
  106. }
  107. case LocId::Kind::None:
  108. break;
  109. }
  110. return LocIdAndInst(loc_id, inst, /*is_unchecked=*/true);
  111. }
  112. } // namespace Carbon::SemIR