convert.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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_CHECK_CONVERT_H_
  5. #define CARBON_TOOLCHAIN_CHECK_CONVERT_H_
  6. #include "toolchain/check/context.h"
  7. #include "toolchain/check/pending_block.h"
  8. #include "toolchain/sem_ir/entity_with_params_base.h"
  9. #include "toolchain/sem_ir/ids.h"
  10. namespace Carbon::Check {
  11. // Description of the target of a conversion.
  12. struct ConversionTarget {
  13. enum Kind : int8_t {
  14. // Convert to a value of type `type_id`.
  15. Value,
  16. // Convert to either a value or a reference of type `type_id`.
  17. ValueOrRef,
  18. // Convert to a durable reference of type `type_id`.
  19. DurableRef,
  20. // Convert to a reference of type `type_id`, for use as the argument to a
  21. // C++ thunk.
  22. CppThunkRef,
  23. // Convert for an explicit `as` cast. This allows any expression category
  24. // as the result, and uses the `As` interface instead of the `ImplicitAs`
  25. // interface.
  26. ExplicitAs,
  27. // Convert for an explicit `unsafe as` cast. This allows any expression
  28. // category as the result, and uses the `UnsafeAs` interface instead of the
  29. // `As` or `ImplicitAs` interface.
  30. ExplicitUnsafeAs,
  31. // The result of the conversion is discarded. It can't be an initializing
  32. // expression, but can be anything else.
  33. Discarded,
  34. // Convert to an initializer for the object denoted by `init_id`.
  35. Initializer,
  36. // Convert to an initializer for the object denoted by `init_id`,
  37. // including a final destination store if needed.
  38. FullInitializer,
  39. Last = FullInitializer
  40. };
  41. // The kind of the target for this conversion.
  42. Kind kind;
  43. // The target type for the conversion.
  44. SemIR::TypeId type_id;
  45. // For an initializer, the object being initialized.
  46. SemIR::InstId init_id = SemIR::InstId::None;
  47. // For an initializer, a block of pending instructions that are needed to
  48. // form the value of `init_id`, and that can be discarded if no
  49. // initialization is needed.
  50. PendingBlock* init_block = nullptr;
  51. // Whether failure of conversion is an error and is diagnosed to the user.
  52. // When looking for a possible conversion but with graceful fallback, diagnose
  53. // should be false.
  54. bool diagnose = true;
  55. // Are we converting this value into an initializer for an object?
  56. auto is_initializer() const -> bool {
  57. return kind == Initializer || kind == FullInitializer;
  58. }
  59. // Is this some kind of explicit `as` conversion?
  60. auto is_explicit_as() const -> bool {
  61. return kind == ExplicitAs || kind == ExplicitUnsafeAs;
  62. }
  63. };
  64. // Convert a value to another type and expression category.
  65. // TODO: The `vtable_id` parameter is too much of a special case here, and
  66. // should be removed - once partial classes are implemented, the vtable pointer
  67. // initialization will be done not in this conversion, but during initialization
  68. // of the object of non-partial class type from the object of partial class
  69. // type.
  70. auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
  71. ConversionTarget target,
  72. SemIR::ClassType* vtable_class_type = nullptr) -> SemIR::InstId;
  73. // Performs initialization of `target_id` from `value_id`. Returns the
  74. // possibly-converted initializing expression, which should be assigned to the
  75. // target using a suitable node for the kind of initialization.
  76. auto Initialize(Context& context, SemIR::LocId loc_id, SemIR::InstId target_id,
  77. SemIR::InstId value_id) -> SemIR::InstId;
  78. // Convert the given expression to a value expression of the same type.
  79. auto ConvertToValueExpr(Context& context, SemIR::InstId expr_id)
  80. -> SemIR::InstId;
  81. // Convert the given expression to a value or reference expression of the same
  82. // type.
  83. auto ConvertToValueOrRefExpr(Context& context, SemIR::InstId expr_id)
  84. -> SemIR::InstId;
  85. // Converts `expr_id` to a value expression of type `type_id`.
  86. auto ConvertToValueOfType(Context& context, SemIR::LocId loc_id,
  87. SemIR::InstId expr_id, SemIR::TypeId type_id)
  88. -> SemIR::InstId;
  89. // Convert the given expression to a value or reference expression of the given
  90. // type.
  91. auto ConvertToValueOrRefOfType(Context& context, SemIR::LocId loc_id,
  92. SemIR::InstId expr_id, SemIR::TypeId type_id)
  93. -> SemIR::InstId;
  94. // Attempted to convert `expr_id` to a value expression of type `type_id`, with
  95. // graceful failure, which does not result in diagnostics. An ErrorInst
  96. // instruction is still returned on failure.
  97. auto TryConvertToValueOfType(Context& context, SemIR::LocId loc_id,
  98. SemIR::InstId expr_id, SemIR::TypeId type_id)
  99. -> SemIR::InstId;
  100. // Converts `value_id` to a value expression of type `bool`.
  101. auto ConvertToBoolValue(Context& context, SemIR::LocId loc_id,
  102. SemIR::InstId value_id) -> SemIR::InstId;
  103. // Converts `value_id` to type `type_id` for an `as` expression.
  104. auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
  105. SemIR::InstId value_id, SemIR::TypeId type_id,
  106. bool unsafe) -> SemIR::InstId;
  107. // Implicitly converts a set of arguments to match the parameter types in a
  108. // function call. Returns a block containing the converted implicit and explicit
  109. // argument values for runtime parameters.
  110. auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
  111. SemIR::InstId self_id,
  112. llvm::ArrayRef<SemIR::InstId> arg_refs,
  113. SemIR::InstId return_slot_arg_id,
  114. const SemIR::Function& callee,
  115. SemIR::SpecificId callee_specific_id)
  116. -> SemIR::InstBlockId;
  117. // A type that has been converted for use as a type expression.
  118. struct TypeExpr {
  119. static const TypeExpr None;
  120. // The converted expression of type `type`, or `ErrorInst::InstId`.
  121. SemIR::TypeInstId inst_id;
  122. // The corresponding type, or `ErrorInst::TypeId`.
  123. SemIR::TypeId type_id;
  124. };
  125. constexpr inline TypeExpr TypeExpr::None = {.inst_id = SemIR::TypeInstId::None,
  126. .type_id = SemIR::TypeId::None};
  127. // Converts an expression for use as a type.
  128. //
  129. // If `diagnose` is true, errors are diagnosed to the user. Set it to false when
  130. // looking to see if a conversion is possible but with graceful fallback.
  131. //
  132. // TODO: Most of the callers of this function discard the `inst_id` and lose
  133. // track of the conversion. In most cases we should be retaining that as the
  134. // operand of some downstream instruction.
  135. auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id,
  136. bool diagnose = true) -> TypeExpr;
  137. // Handles an expression whose result value is unused.
  138. auto DiscardExpr(Context& context, SemIR::InstId expr_id) -> void;
  139. } // namespace Carbon::Check
  140. #endif // CARBON_TOOLCHAIN_CHECK_CONVERT_H_