Files
carbon-lang/toolchain/sem_ir/constant.cpp
T
Richard Smith 1349cc1e8e Track on InstKind whether each instruction kind can define a constant. (#3908)
The intent is to use this information in lowering to determine which
kinds of instruction need constant lowering code and which kinds need
runtime lowering code. For now we just validate that we only create
constants with instructions that should be able to form constants.
2024-04-24 16:13:16 +00:00

77 lines
2.9 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
#include "toolchain/sem_ir/constant.h"
#include "toolchain/sem_ir/inst_profile.h"
namespace Carbon::SemIR {
auto ConstantStore::GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId {
// Check that we're allowed to form this kind of constant.
switch (inst.kind().constant_kind()) {
case InstConstantKind::Never:
CARBON_FATAL() << "Should not form a constant from instruction " << inst;
break;
case InstConstantKind::SymbolicOnly:
CARBON_CHECK(is_symbolic)
<< "Should only form a symbolic constant from instruction " << inst;
break;
case InstConstantKind::Conditional:
break;
case InstConstantKind::Always:
CARBON_CHECK(!is_symbolic)
<< "Should only form a template constant from instruction " << inst;
break;
}
// Compute the instruction's profile.
ConstantNode node = {.inst = inst, .constant_id = ConstantId::NotConstant};
llvm::FoldingSetNodeID id;
node.Profile(id, constants_.getContext());
// Check if we have already created this constant.
void* insert_pos;
if (ConstantNode* found = constants_.FindNodeOrInsertPos(id, insert_pos)) {
CARBON_CHECK(found->constant_id.is_constant())
<< "Found non-constant in constant store for " << inst;
CARBON_CHECK(found->constant_id.is_symbolic() == is_symbolic)
<< "Mismatch in phase for constant " << inst;
return found->constant_id;
}
// Create the new inst and insert the new node.
auto inst_id = constants_.getContext()->insts().AddInNoBlock(
LocIdAndInst::Untyped(Parse::NodeId::Invalid, inst));
auto constant_id = is_symbolic
? SemIR::ConstantId::ForSymbolicConstant(inst_id)
: SemIR::ConstantId::ForTemplateConstant(inst_id);
node.constant_id = constant_id;
constants_.InsertNode(new (*allocator_) ConstantNode(node), insert_pos);
// The constant value of any constant instruction is that instruction itself.
constants_.getContext()->constant_values().Set(inst_id, constant_id);
return constant_id;
}
auto ConstantStore::GetAsVector() const -> llvm::SmallVector<InstId, 0> {
llvm::SmallVector<InstId, 0> result;
result.reserve(constants_.size());
for (const ConstantNode& node : constants_) {
result.push_back(node.constant_id.inst_id());
}
// For stability, put the results into index order. This happens to also be
// insertion order.
std::sort(result.begin(), result.end(),
[](InstId a, InstId b) { return a.index < b.index; });
return result;
}
auto ConstantStore::ConstantNode::Profile(llvm::FoldingSetNodeID& id,
File* sem_ir) -> void {
ProfileConstant(id, *sem_ir, inst);
}
} // namespace Carbon::SemIR