mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Track the type as written in BaseDecl and AdaptDecl. (#4564)
Represent the type as an `InstId` rather than as a `TypeId` to preserve how it was written and better support tracking its value in a generic. Add accessors to `Class` to get the base and adapted type to reduce code duplication, and add `TypeStore::GetObjectRepr` to make it easier to map from a type to its possibly-adapted object representation type. In passing, also move `GetIntTypeInfo` and `GetUnqualifiedType` into `TypeStore`. This fixes specifics of generic adapters to properly look at the specific adapted type, and also fixes importing of adapters. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
parent
e0db74a2a1
commit
d6ec885eb3
@@ -99,30 +99,12 @@ static auto EmitAggregateConstant(ConstantContext& context,
|
||||
return ConstantType::get(llvm_type, elements);
|
||||
}
|
||||
|
||||
// For each instruction InstT, there is a function below to convert it to an
|
||||
// `llvm::Constant*`:
|
||||
// For each instruction InstT that can be emitted as a constant, there is a
|
||||
// function below to convert it to an `llvm::Constant*`:
|
||||
//
|
||||
// auto EmitAsConstant(ConstantContext& context, SemIR::InstT inst)
|
||||
// -> llvm::Constant*;
|
||||
|
||||
template <typename InstT>
|
||||
requires(InstT::Kind.constant_kind() == SemIR::InstConstantKind::Never ||
|
||||
InstT::Kind.constant_kind() == SemIR::InstConstantKind::SymbolicOnly)
|
||||
static auto EmitAsConstant(ConstantContext& /*context*/, InstT inst)
|
||||
-> llvm::Constant* {
|
||||
CARBON_FATAL("Unexpected constant instruction kind {0}", inst);
|
||||
}
|
||||
|
||||
// For constants that are always of type `type`, produce the trivial runtime
|
||||
// representation of type `type`.
|
||||
template <typename InstT>
|
||||
requires(InstT::Kind.is_type() == SemIR::InstIsType::Always &&
|
||||
InstT::Kind.constant_kind() != SemIR::InstConstantKind::SymbolicOnly)
|
||||
static auto EmitAsConstant(ConstantContext& context, InstT /*inst*/)
|
||||
-> llvm::Constant* {
|
||||
return context.GetTypeAsValue();
|
||||
}
|
||||
|
||||
// Represent facet values the same as types.
|
||||
static auto EmitAsConstant(ConstantContext& context, SemIR::FacetValue /*inst*/)
|
||||
-> llvm::Constant* {
|
||||
@@ -197,20 +179,6 @@ static auto EmitAsConstant(ConstantContext& context, SemIR::FloatLiteral inst)
|
||||
return llvm::ConstantFP::get(context.GetType(inst.type_id), value);
|
||||
}
|
||||
|
||||
static auto EmitAsConstant(ConstantContext& context,
|
||||
SemIR::InterfaceWitness inst) -> llvm::Constant* {
|
||||
// TODO: For dynamic dispatch, we might want to lower witness tables as
|
||||
// constants.
|
||||
return context.GetUnusedConstant(inst.type_id);
|
||||
}
|
||||
|
||||
static auto EmitAsConstant(ConstantContext& /*context*/,
|
||||
SemIR::ImplDecl /*inst*/) -> llvm::Constant* {
|
||||
// An ImplDecl isn't a value, so this constant value won't ever be used.
|
||||
// It also doesn't even have a type, so we can't use GetUnusedConstant.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static auto EmitAsConstant(ConstantContext& context, SemIR::IntValue inst)
|
||||
-> llvm::Constant* {
|
||||
auto* type = context.GetType(inst.type_id);
|
||||
@@ -226,7 +194,8 @@ static auto EmitAsConstant(ConstantContext& context, SemIR::IntValue inst)
|
||||
|
||||
auto val = context.sem_ir().ints().Get(inst.int_id);
|
||||
int bit_width = int_type->getBitWidth();
|
||||
bool is_signed = context.sem_ir().GetIntTypeInfo(inst.type_id).is_signed;
|
||||
bool is_signed =
|
||||
context.sem_ir().types().GetIntTypeInfo(inst.type_id).is_signed;
|
||||
return llvm::ConstantInt::get(type, is_signed ? val.sextOrTrunc(bit_width)
|
||||
: val.zextOrTrunc(bit_width));
|
||||
}
|
||||
@@ -246,6 +215,28 @@ static auto EmitAsConstant(ConstantContext& /*context*/,
|
||||
CARBON_FATAL("TODO: Add support: {0}", inst);
|
||||
}
|
||||
|
||||
// Tries to emit an LLVM constant value for this constant instruction. Centrally
|
||||
// handles some common cases and then dispatches to the relevant EmitAsConstant
|
||||
// overload based on the type of the instruction for the remaining cases.
|
||||
template <typename InstT>
|
||||
static auto MaybeEmitAsConstant(ConstantContext& context, InstT inst)
|
||||
-> llvm::Constant* {
|
||||
if constexpr (InstT::Kind.constant_kind() == SemIR::InstConstantKind::Never ||
|
||||
InstT::Kind.constant_kind() ==
|
||||
SemIR::InstConstantKind::SymbolicOnly) {
|
||||
CARBON_FATAL("Unexpected constant instruction kind {0}", inst);
|
||||
} else if constexpr (!InstT::Kind.is_lowered()) {
|
||||
// This instruction has a constant value, but that constant value will never
|
||||
// be used by lowering.
|
||||
return nullptr;
|
||||
} else if constexpr (InstT::Kind.is_type() == SemIR::InstIsType::Always) {
|
||||
// All types are lowered to the same value.
|
||||
return context.GetTypeAsValue();
|
||||
} else {
|
||||
return EmitAsConstant(context, inst);
|
||||
}
|
||||
}
|
||||
|
||||
auto LowerConstants(FileContext& file_context,
|
||||
llvm::MutableArrayRef<llvm::Constant*> constants) -> void {
|
||||
ConstantContext context(file_context, constants);
|
||||
@@ -273,10 +264,10 @@ auto LowerConstants(FileContext& file_context,
|
||||
}
|
||||
llvm::Constant* value = nullptr;
|
||||
CARBON_KIND_SWITCH(inst) {
|
||||
#define CARBON_SEM_IR_INST_KIND(Name) \
|
||||
case CARBON_KIND(SemIR::Name const_inst): { \
|
||||
value = EmitAsConstant(context, const_inst); \
|
||||
break; \
|
||||
#define CARBON_SEM_IR_INST_KIND(Name) \
|
||||
case CARBON_KIND(SemIR::Name const_inst): { \
|
||||
value = MaybeEmitAsConstant(context, const_inst); \
|
||||
break; \
|
||||
}
|
||||
#include "toolchain/sem_ir/inst_kind.def"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user