mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
76 lines
2.7 KiB
C++
76 lines
2.7 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_CHECK_GENERIC_REGION_STACK_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_GENERIC_REGION_STACK_H_
|
|
|
|
#include "common/array_stack.h"
|
|
#include "llvm/ADT/BitmaskEnum.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
|
|
|
|
// A stack of enclosing regions that might be declaring or defining a generic
|
|
// entity. In such a region, we track the generic constructs that are used, such
|
|
// as symbolic constants and types, and instructions that depend on a template
|
|
// parameter.
|
|
//
|
|
// TODO: For now we're just tracking symbolic constants.
|
|
//
|
|
// We split a generic into two regions -- declaration and definition -- because
|
|
// these are in general introduced separately, and substituted into separately.
|
|
// For example, for `class C(T:! type, N:! T) { var x: T; }`, a use such as
|
|
// `C(i32, 0)*` substitutes into just the declaration, whereas a use such as
|
|
// `var x: C(i32, 0) = {.x = 0};` also substitutes into the definition.
|
|
class GenericRegionStack {
|
|
public:
|
|
// Ways in which an instruction can depend on a generic parameter.
|
|
enum class DependencyKind : int8_t {
|
|
None = 0x0,
|
|
// The type of the instruction depends on a checked generic parameter.
|
|
SymbolicType = 0x1,
|
|
// The constant value of the instruction depends on a checked generic
|
|
// parameter.
|
|
SymbolicConstant = 0x2,
|
|
Template = 0x4,
|
|
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Template)
|
|
};
|
|
|
|
// An instruction that depends on a generic parameter in some way.
|
|
struct DependentInst {
|
|
SemIR::InstId inst_id;
|
|
DependencyKind kind;
|
|
};
|
|
|
|
// Pushes a region that might be declaring or defining a generic.
|
|
auto Push() -> void;
|
|
|
|
// Pops a generic region.
|
|
auto Pop() -> void;
|
|
|
|
// Adds an instruction to the list of instructions in the current region that
|
|
// in some way depend on a generic parameter.
|
|
auto AddDependentInst(DependentInst inst) -> void;
|
|
|
|
// Returns the list of dependent instructions in the current generic region.
|
|
auto PeekDependentInsts() -> llvm::ArrayRef<DependentInst>;
|
|
|
|
// Runs verification that the processing cleanly finished.
|
|
auto VerifyOnFinish() const -> void {
|
|
CARBON_CHECK(dependent_insts_stack_.empty(),
|
|
"generic_region_stack still has {0} entries",
|
|
dependent_insts_stack_.all_values_size());
|
|
}
|
|
|
|
private:
|
|
// A stack of symbolic constants for enclosing generic regions.
|
|
ArrayStack<DependentInst> dependent_insts_stack_;
|
|
};
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_GENERIC_REGION_STACK_H_
|