Abbreviate "representation" -> "repr" (#3464)

Specifically using these abbreviations:
* InitRepr: "initializing representation"
* ObjectRepr: "object representation"
* ValueRepr: "value representation"

As discussed in [#toolchain
discord](https://discord.com/channels/655572317891461132/655578254970716160/1182086098470572143)
and now documented in the [list of
abbreviations](https://docs.google.com/document/d/1RRYMm42osyqhI2LyjrjockYCutQ5dOf8Abu50kTrkX0/edit?resourcekey=0-kHyqOESbOHmzZphUbtLrTw#heading=h.pph7i5m5un7q).
This commit is contained in:
josh11b
2023-12-06 23:11:47 +00:00
committed by GitHub
parent fa07b52b8b
commit e9fc07feee
12 changed files with 187 additions and 229 deletions
+65 -78
View File
@@ -516,7 +516,7 @@ namespace {
//
// - An `AddNestedIncompleteTypes` step adds a task for all incomplete types
// nested within a type to the work list.
// - A `BuildValueRepresentation` step computes the value representation for a
// - A `BuildValueRepr` step computes the value representation for a
// type, once all of its nested types are complete, and marks the type as
// complete.
class TypeCompleter {
@@ -570,31 +570,28 @@ class TypeCompleter {
}
CARBON_CHECK(work_list_.size() >= old_work_list_size)
<< "AddNestedIncompleteTypes should not remove work items";
work_list_[old_work_list_size - 1].phase =
Phase::BuildValueRepresentation;
work_list_[old_work_list_size - 1].phase = Phase::BuildValueRepr;
break;
case Phase::BuildValueRepresentation: {
auto value_rep = BuildValueRepresentation(type_id, inst);
case Phase::BuildValueRepr: {
auto value_rep = BuildValueRepr(type_id, inst);
context_.sem_ir().CompleteType(type_id, value_rep);
CARBON_CHECK(old_work_list_size == work_list_.size())
<< "BuildValueRepresentation should not change work items";
<< "BuildValueRepr should not change work items";
work_list_.pop_back();
// Also complete the value representation type, if necessary. This
// should never fail: the value representation shouldn't require any
// additional nested types to be complete.
if (!context_.sem_ir().IsTypeComplete(value_rep.type_id)) {
work_list_.push_back(
{value_rep.type_id, Phase::BuildValueRepresentation});
work_list_.push_back({value_rep.type_id, Phase::BuildValueRepr});
}
// For a pointer representation, the pointee also needs to be complete.
if (value_rep.kind == SemIR::ValueRepresentation::Pointer) {
if (value_rep.kind == SemIR::ValueRepr::Pointer) {
auto pointee_type_id =
context_.sem_ir().GetPointeeType(value_rep.type_id);
if (!context_.sem_ir().IsTypeComplete(pointee_type_id)) {
work_list_.push_back(
{pointee_type_id, Phase::BuildValueRepresentation});
work_list_.push_back({pointee_type_id, Phase::BuildValueRepr});
}
}
break;
@@ -639,7 +636,7 @@ class TypeCompleter {
}
return false;
}
Push(class_info.object_representation_id);
Push(class_info.object_repr_id);
break;
}
@@ -656,51 +653,47 @@ class TypeCompleter {
// Makes an empty value representation, which is used for types that have no
// state, such as empty structs and tuples.
auto MakeEmptyRepresentation(Parse::NodeId parse_node) const
-> SemIR::ValueRepresentation {
return {.kind = SemIR::ValueRepresentation::None,
auto MakeEmptyValueRepr(Parse::NodeId parse_node) const -> SemIR::ValueRepr {
return {.kind = SemIR::ValueRepr::None,
.type_id = context_.CanonicalizeTupleType(parse_node, {})};
}
// Makes a value representation that uses pass-by-copy, copying the given
// type.
auto MakeCopyRepresentation(
SemIR::TypeId rep_id,
SemIR::ValueRepresentation::AggregateKind aggregate_kind =
SemIR::ValueRepresentation::NotAggregate) const
-> SemIR::ValueRepresentation {
return {.kind = SemIR::ValueRepresentation::Copy,
auto MakeCopyValueRepr(SemIR::TypeId rep_id,
SemIR::ValueRepr::AggregateKind aggregate_kind =
SemIR::ValueRepr::NotAggregate) const
-> SemIR::ValueRepr {
return {.kind = SemIR::ValueRepr::Copy,
.aggregate_kind = aggregate_kind,
.type_id = rep_id};
}
// Makes a value representation that uses pass-by-address with the given
// pointee type.
auto MakePointerRepresentation(
Parse::NodeId parse_node, SemIR::TypeId pointee_id,
SemIR::ValueRepresentation::AggregateKind aggregate_kind =
SemIR::ValueRepresentation::NotAggregate) const
-> SemIR::ValueRepresentation {
auto MakePointerValueRepr(Parse::NodeId parse_node, SemIR::TypeId pointee_id,
SemIR::ValueRepr::AggregateKind aggregate_kind =
SemIR::ValueRepr::NotAggregate) const
-> SemIR::ValueRepr {
// TODO: Should we add `const` qualification to `pointee_id`?
return {.kind = SemIR::ValueRepresentation::Pointer,
return {.kind = SemIR::ValueRepr::Pointer,
.aggregate_kind = aggregate_kind,
.type_id = context_.GetPointerType(parse_node, pointee_id)};
}
// Gets the value representation of a nested type, which should already be
// complete.
auto GetNestedValueRepresentation(SemIR::TypeId nested_type_id) const {
auto GetNestedValueRepr(SemIR::TypeId nested_type_id) const {
CARBON_CHECK(context_.sem_ir().IsTypeComplete(nested_type_id))
<< "Nested type should already be complete";
auto value_rep = context_.sem_ir().GetValueRepresentation(nested_type_id);
CARBON_CHECK(value_rep.kind != SemIR::ValueRepresentation::Unknown)
auto value_rep = context_.sem_ir().GetValueRepr(nested_type_id);
CARBON_CHECK(value_rep.kind != SemIR::ValueRepr::Unknown)
<< "Complete type should have a value representation";
return value_rep;
};
auto BuildCrossRefValueRepresentation(SemIR::TypeId type_id,
SemIR::CrossRef xref) const
-> SemIR::ValueRepresentation {
auto BuildCrossRefValueRepr(SemIR::TypeId type_id, SemIR::CrossRef xref) const
-> SemIR::ValueRepr {
auto xref_inst =
context_.cross_ref_irs().Get(xref.ir_id)->insts().Get(xref.inst_id);
@@ -723,25 +716,25 @@ class TypeCompleter {
case SemIR::BuiltinKind::NamespaceType:
case SemIR::BuiltinKind::FunctionType:
case SemIR::BuiltinKind::BoundMethodType:
return MakeCopyRepresentation(type_id);
return MakeCopyValueRepr(type_id);
case SemIR::BuiltinKind::StringType:
// TODO: Decide on string value semantics. This should probably be a
// custom value representation carrying a pointer and size or
// similar.
return MakePointerRepresentation(Parse::NodeId::Invalid, type_id);
return MakePointerValueRepr(Parse::NodeId::Invalid, type_id);
}
llvm_unreachable("All builtin kinds were handled above");
}
auto BuildStructOrTupleValueRepresentation(Parse::NodeId parse_node,
std::size_t num_elements,
SemIR::TypeId elementwise_rep,
bool same_as_object_rep) const
-> SemIR::ValueRepresentation {
SemIR::ValueRepresentation::AggregateKind aggregate_kind =
same_as_object_rep ? SemIR::ValueRepresentation::ValueAndObjectAggregate
: SemIR::ValueRepresentation::ValueAggregate;
auto BuildStructOrTupleValueRepr(Parse::NodeId parse_node,
std::size_t num_elements,
SemIR::TypeId elementwise_rep,
bool same_as_object_rep) const
-> SemIR::ValueRepr {
SemIR::ValueRepr::AggregateKind aggregate_kind =
same_as_object_rep ? SemIR::ValueRepr::ValueAndObjectAggregate
: SemIR::ValueRepr::ValueAggregate;
if (num_elements == 1) {
// The value representation for a struct or tuple with a single element
@@ -749,21 +742,20 @@ class TypeCompleter {
// element.
// TODO: Consider doing the same whenever `elementwise_rep` is
// sufficiently small.
return MakeCopyRepresentation(elementwise_rep, aggregate_kind);
return MakeCopyValueRepr(elementwise_rep, aggregate_kind);
}
// For a struct or tuple with multiple fields, we use a pointer
// to the elementwise value representation.
return MakePointerRepresentation(parse_node, elementwise_rep,
aggregate_kind);
return MakePointerValueRepr(parse_node, elementwise_rep, aggregate_kind);
}
auto BuildStructTypeValueRepresentation(SemIR::TypeId type_id,
SemIR::StructType struct_type) const
-> SemIR::ValueRepresentation {
auto BuildStructTypeValueRepr(SemIR::TypeId type_id,
SemIR::StructType struct_type) const
-> SemIR::ValueRepr {
// TODO: Share more code with tuples.
auto fields = context_.inst_blocks().Get(struct_type.fields_id);
if (fields.empty()) {
return MakeEmptyRepresentation(struct_type.parse_node);
return MakeEmptyValueRepr(struct_type.parse_node);
}
// Find the value representation for each field, and construct a struct
@@ -773,7 +765,7 @@ class TypeCompleter {
bool same_as_object_rep = true;
for (auto field_id : fields) {
auto field = context_.insts().GetAs<SemIR::StructTypeField>(field_id);
auto field_value_rep = GetNestedValueRepresentation(field.field_type_id);
auto field_value_rep = GetNestedValueRepr(field.field_type_id);
if (field_value_rep.type_id != field.field_type_id) {
same_as_object_rep = false;
field.field_type_id = field_value_rep.type_id;
@@ -787,17 +779,17 @@ class TypeCompleter {
: context_.CanonicalizeStructType(
struct_type.parse_node,
context_.inst_blocks().Add(value_rep_fields));
return BuildStructOrTupleValueRepresentation(
struct_type.parse_node, fields.size(), value_rep, same_as_object_rep);
return BuildStructOrTupleValueRepr(struct_type.parse_node, fields.size(),
value_rep, same_as_object_rep);
}
auto BuildTupleTypeValueRepresentation(SemIR::TypeId type_id,
SemIR::TupleType tuple_type) const
-> SemIR::ValueRepresentation {
auto BuildTupleTypeValueRepr(SemIR::TypeId type_id,
SemIR::TupleType tuple_type) const
-> SemIR::ValueRepr {
// TODO: Share more code with structs.
auto elements = context_.type_blocks().Get(tuple_type.elements_id);
if (elements.empty()) {
return MakeEmptyRepresentation(tuple_type.parse_node);
return MakeEmptyValueRepr(tuple_type.parse_node);
}
// Find the value representation for each element, and construct a tuple
@@ -806,7 +798,7 @@ class TypeCompleter {
value_rep_elements.reserve(elements.size());
bool same_as_object_rep = true;
for (auto element_type_id : elements) {
auto element_value_rep = GetNestedValueRepresentation(element_type_id);
auto element_value_rep = GetNestedValueRepr(element_type_id);
if (element_value_rep.type_id != element_type_id) {
same_as_object_rep = false;
}
@@ -817,14 +809,14 @@ class TypeCompleter {
? type_id
: context_.CanonicalizeTupleType(tuple_type.parse_node,
value_rep_elements);
return BuildStructOrTupleValueRepresentation(
tuple_type.parse_node, elements.size(), value_rep, same_as_object_rep);
return BuildStructOrTupleValueRepr(tuple_type.parse_node, elements.size(),
value_rep, same_as_object_rep);
}
// Builds and returns the value representation for the given type. All nested
// types, as found by AddNestedIncompleteTypes, are known to be complete.
auto BuildValueRepresentation(SemIR::TypeId type_id, SemIR::Inst inst) const
-> SemIR::ValueRepresentation {
auto BuildValueRepr(SemIR::TypeId type_id, SemIR::Inst inst) const
-> SemIR::ValueRepr {
// TODO: This can emit new SemIR instructions. Consider emitting them into a
// dedicated file-scope instruction block where possible, or somewhere else
// that better reflects the definition of the type, rather than wherever the
@@ -887,50 +879,45 @@ class TypeCompleter {
CARBON_FATAL() << "Type refers to non-type inst " << inst;
case SemIR::CrossRef::Kind:
return BuildCrossRefValueRepresentation(type_id,
inst.As<SemIR::CrossRef>());
return BuildCrossRefValueRepr(type_id, inst.As<SemIR::CrossRef>());
case SemIR::ArrayType::Kind: {
// For arrays, it's convenient to always use a pointer representation,
// even when the array has zero or one element, in order to support
// indexing.
return MakePointerRepresentation(
inst.parse_node(), type_id,
SemIR::ValueRepresentation::ObjectAggregate);
return MakePointerValueRepr(inst.parse_node(), type_id,
SemIR::ValueRepr::ObjectAggregate);
}
case SemIR::StructType::Kind:
return BuildStructTypeValueRepresentation(type_id,
inst.As<SemIR::StructType>());
return BuildStructTypeValueRepr(type_id, inst.As<SemIR::StructType>());
case SemIR::TupleType::Kind:
return BuildTupleTypeValueRepresentation(type_id,
inst.As<SemIR::TupleType>());
return BuildTupleTypeValueRepr(type_id, inst.As<SemIR::TupleType>());
case SemIR::ClassType::Kind:
// The value representation for a class is a pointer to the object
// representation.
// TODO: Support customized value representations for classes.
// TODO: Pick a better value representation when possible.
return MakePointerRepresentation(
return MakePointerValueRepr(
inst.parse_node(),
context_.classes()
.Get(inst.As<SemIR::ClassType>().class_id)
.object_representation_id,
SemIR::ValueRepresentation::ObjectAggregate);
.object_repr_id,
SemIR::ValueRepr::ObjectAggregate);
case SemIR::Builtin::Kind:
CARBON_FATAL() << "Builtins should be named as cross-references";
case SemIR::PointerType::Kind:
case SemIR::UnboundElementType::Kind:
return MakeCopyRepresentation(type_id);
return MakeCopyValueRepr(type_id);
case SemIR::ConstType::Kind:
// The value representation of `const T` is the same as that of `T`.
// Objects are not modifiable through their value representations.
return GetNestedValueRepresentation(
inst.As<SemIR::ConstType>().inner_id);
return GetNestedValueRepr(inst.As<SemIR::ConstType>().inner_id);
}
}
@@ -938,7 +925,7 @@ class TypeCompleter {
// The next step is to add nested types to the list of types to complete.
AddNestedIncompleteTypes,
// The next step is to build the value representation for the type.
BuildValueRepresentation,
BuildValueRepr,
};
struct WorkItem {
+15 -18
View File
@@ -48,8 +48,7 @@ static auto FindReturnSlotForInitializer(SemIR::File& sem_ir,
case SemIR::Call::Kind: {
auto call = init.As<SemIR::Call>();
if (!SemIR::GetInitializingRepresentation(sem_ir, call.type_id)
.has_return_slot()) {
if (!SemIR::GetInitRepr(sem_ir, call.type_id).has_return_slot()) {
return SemIR::InstId::Invalid;
}
return sem_ir.inst_blocks().Get(call.args_id).back();
@@ -353,8 +352,8 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
bool is_init = target.is_initializer();
ConversionTarget::Kind inner_kind =
!is_init ? ConversionTarget::Value
: SemIR::GetInitializingRepresentation(sem_ir, target.type_id).kind ==
SemIR::InitializingRepresentation::InPlace
: SemIR::GetInitRepr(sem_ir, target.type_id).kind ==
SemIR::InitRepr::InPlace
? ConversionTarget::FullInitializer
: ConversionTarget::Initializer;
@@ -444,8 +443,8 @@ static auto ConvertStructToStructOrClass(Context& context,
bool is_init = target.is_initializer();
ConversionTarget::Kind inner_kind =
!is_init ? ConversionTarget::Value
: SemIR::GetInitializingRepresentation(sem_ir, target.type_id).kind ==
SemIR::InitializingRepresentation::InPlace
: SemIR::GetInitRepr(sem_ir, target.type_id).kind ==
SemIR::InitRepr::InPlace
? ConversionTarget::FullInitializer
: ConversionTarget::Initializer;
@@ -548,8 +547,7 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type,
return SemIR::InstId::BuiltinError;
}
auto dest_struct_type = context.insts().GetAs<SemIR::StructType>(
context.sem_ir().GetTypeAllowBuiltinTypes(
class_info.object_representation_id));
context.sem_ir().GetTypeAllowBuiltinTypes(class_info.object_repr_id));
// If we're trying to create a class value, form a temporary for the value to
// point to.
@@ -645,10 +643,10 @@ static auto PerformBuiltinConversion(Context& context, Parse::NodeId parse_node,
if (value_cat == SemIR::ExprCategory::Initializing &&
IsValidExprCategoryForConversionTarget(SemIR::ExprCategory::Value,
target.kind) &&
SemIR::GetInitializingRepresentation(sem_ir, value_type_id).kind ==
SemIR::InitializingRepresentation::ByCopy) {
auto value_rep = SemIR::GetValueRepresentation(sem_ir, value_type_id);
if (value_rep.kind == SemIR::ValueRepresentation::Copy &&
SemIR::GetInitRepr(sem_ir, value_type_id).kind ==
SemIR::InitRepr::ByCopy) {
auto value_rep = SemIR::GetValueRepr(sem_ir, value_type_id);
if (value_rep.kind == SemIR::ValueRepr::Copy &&
value_rep.type_id == value_type_id) {
// The initializer produces an object representation by copy, and the
// value representation is a copy of the object representation, so we
@@ -747,9 +745,9 @@ static auto PerformCopy(Context& context, SemIR::InstId expr_id)
// TODO: Directly track on the value representation whether it's a copy of
// the object representation.
auto value_rep = SemIR::GetValueRepresentation(context.sem_ir(), type_id);
if (value_rep.kind == SemIR::ValueRepresentation::Copy &&
value_rep.aggregate_kind == SemIR::ValueRepresentation::NotAggregate &&
auto value_rep = SemIR::GetValueRepr(context.sem_ir(), type_id);
if (value_rep.kind == SemIR::ValueRepr::Copy &&
value_rep.aggregate_kind == SemIR::ValueRepr::NotAggregate &&
value_rep.type_id == type_id) {
// For by-value scalar types, no explicit action is required. Initializing
// from a value expression is treated as copying the value.
@@ -905,9 +903,8 @@ auto Convert(Context& context, Parse::NodeId parse_node, SemIR::InstId expr_id,
// Perform a final destination store, if necessary.
if (target.kind == ConversionTarget::FullInitializer) {
if (auto init_rep =
SemIR::GetInitializingRepresentation(sem_ir, target.type_id);
init_rep.kind == SemIR::InitializingRepresentation::ByCopy) {
if (auto init_rep = SemIR::GetInitRepr(sem_ir, target.type_id);
init_rep.kind == SemIR::InitRepr::ByCopy) {
target.init_block->InsertHere();
expr_id = context.AddInst(SemIR::InitializeFrom{
parse_node, target.type_id, expr_id, target.init_id});
+1 -1
View File
@@ -280,7 +280,7 @@ auto HandleClassDefinition(Context& context, Parse::NodeId parse_node) -> bool {
// The class type is now fully defined.
auto& class_info = context.classes().Get(class_id);
class_info.object_representation_id =
class_info.object_repr_id =
context.CanonicalizeStructType(parse_node, fields_id);
return true;
}
+1 -2
View File
@@ -71,8 +71,7 @@ static auto BuildFunctionDecl(Context& context, bool is_definition)
context.sem_ir().StringifyType(return_type_id));
})) {
return_type_id = SemIR::TypeId::Error;
} else if (!SemIR::GetInitializingRepresentation(context.sem_ir(),
return_type_id)
} else if (!SemIR::GetInitRepr(context.sem_ir(), return_type_id)
.has_return_slot()) {
// The function only has a return slot if it uses in-place initialization.
} else {
+18 -23
View File
@@ -81,12 +81,10 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id)
sem_ir().inst_blocks().Get(function.implicit_param_refs_id);
auto param_refs = sem_ir().inst_blocks().Get(function.param_refs_id);
SemIR::InitializingRepresentation return_rep =
SemIR::InitRepr return_rep =
function.return_type_id.is_valid()
? SemIR::GetInitializingRepresentation(sem_ir(),
function.return_type_id)
: SemIR::InitializingRepresentation{
.kind = SemIR::InitializingRepresentation::None};
? SemIR::GetInitRepr(sem_ir(), function.return_type_id)
: SemIR::InitRepr{.kind = SemIR::InitRepr::None};
CARBON_CHECK(return_rep.has_return_slot() == has_return_slot);
llvm::SmallVector<llvm::Type*> param_types;
@@ -106,17 +104,16 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id)
for (auto param_ref_id :
llvm::concat<const SemIR::InstId>(implicit_param_refs, param_refs)) {
auto param_type_id = sem_ir().insts().Get(param_ref_id).type_id();
switch (auto value_rep =
SemIR::GetValueRepresentation(sem_ir(), param_type_id);
switch (auto value_rep = SemIR::GetValueRepr(sem_ir(), param_type_id);
value_rep.kind) {
case SemIR::ValueRepresentation::Unknown:
case SemIR::ValueRepr::Unknown:
CARBON_FATAL()
<< "Incomplete parameter type lowering function declaration";
case SemIR::ValueRepresentation::None:
case SemIR::ValueRepr::None:
break;
case SemIR::ValueRepresentation::Copy:
case SemIR::ValueRepresentation::Custom:
case SemIR::ValueRepresentation::Pointer:
case SemIR::ValueRepr::Copy:
case SemIR::ValueRepr::Custom:
case SemIR::ValueRepr::Pointer:
param_types.push_back(GetType(value_rep.type_id));
param_inst_ids.push_back(param_ref_id);
break;
@@ -125,10 +122,9 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id)
// If the initializing representation doesn't produce a value, set the return
// type to void.
llvm::Type* return_type =
return_rep.kind == SemIR::InitializingRepresentation::ByCopy
? GetType(function.return_type_id)
: llvm::Type::getVoidTy(llvm_context());
llvm::Type* return_type = return_rep.kind == SemIR::InitRepr::ByCopy
? GetType(function.return_type_id)
: llvm::Type::getVoidTy(llvm_context());
std::string mangled_name;
if (SemIR::IsEntryPoint(sem_ir(), function_id)) {
@@ -199,8 +195,8 @@ auto FileContext::BuildFunctionDefinition(SemIR::FunctionId function_id)
for (auto param_ref_id :
llvm::concat<const SemIR::InstId>(implicit_param_refs, param_refs)) {
auto param_type_id = sem_ir().insts().Get(param_ref_id).type_id();
if (SemIR::GetValueRepresentation(sem_ir(), param_type_id).kind ==
SemIR::ValueRepresentation::None) {
if (SemIR::GetValueRepr(sem_ir(), param_type_id).kind ==
SemIR::ValueRepr::None) {
function_lowering.SetLocal(
param_ref_id, llvm::PoisonValue::get(GetType(param_type_id)));
} else {
@@ -260,11 +256,10 @@ auto FileContext::BuildType(SemIR::InstId inst_id) -> llvm::Type* {
sem_ir_->GetArrayBoundValue(array_type.bound_id));
}
case SemIR::ClassType::Kind: {
auto object_representation_id =
sem_ir_->classes()
.Get(inst.As<SemIR::ClassType>().class_id)
.object_representation_id;
return GetType(object_representation_id);
auto object_repr_id = sem_ir_->classes()
.Get(inst.As<SemIR::ClassType>().class_id)
.object_repr_id;
return GetType(object_repr_id);
}
case SemIR::ConstType::Kind:
return GetType(inst.As<SemIR::ConstType>().inner_id);
+10 -11
View File
@@ -80,11 +80,11 @@ auto FunctionContext::CreateSyntheticBlock() -> llvm::BasicBlock* {
auto FunctionContext::FinishInit(SemIR::TypeId type_id, SemIR::InstId dest_id,
SemIR::InstId source_id) -> void {
switch (SemIR::GetInitializingRepresentation(sem_ir(), type_id).kind) {
case SemIR::InitializingRepresentation::None:
case SemIR::InitializingRepresentation::InPlace:
switch (SemIR::GetInitRepr(sem_ir(), type_id).kind) {
case SemIR::InitRepr::None:
case SemIR::InitRepr::InPlace:
break;
case SemIR::InitializingRepresentation::ByCopy:
case SemIR::InitRepr::ByCopy:
CopyValue(type_id, source_id, dest_id);
break;
}
@@ -92,16 +92,15 @@ auto FunctionContext::FinishInit(SemIR::TypeId type_id, SemIR::InstId dest_id,
auto FunctionContext::CopyValue(SemIR::TypeId type_id, SemIR::InstId source_id,
SemIR::InstId dest_id) -> void {
switch (auto rep = SemIR::GetValueRepresentation(sem_ir(), type_id);
rep.kind) {
case SemIR::ValueRepresentation::Unknown:
switch (auto rep = SemIR::GetValueRepr(sem_ir(), type_id); rep.kind) {
case SemIR::ValueRepr::Unknown:
CARBON_FATAL() << "Attempt to copy incomplete type";
case SemIR::ValueRepresentation::None:
case SemIR::ValueRepr::None:
break;
case SemIR::ValueRepresentation::Copy:
case SemIR::ValueRepr::Copy:
builder().CreateStore(GetValue(source_id), GetValue(dest_id));
break;
case SemIR::ValueRepresentation::Pointer: {
case SemIR::ValueRepr::Pointer: {
const auto& layout = llvm_module().getDataLayout();
auto* type = GetType(type_id);
// TODO: Compute known alignment of the source and destination, which may
@@ -114,7 +113,7 @@ auto FunctionContext::CopyValue(SemIR::TypeId type_id, SemIR::InstId source_id,
align, layout.getTypeAllocSize(type));
break;
}
case SemIR::ValueRepresentation::Custom:
case SemIR::ValueRepr::Custom:
CARBON_FATAL() << "TODO: Add support for CopyValue with custom value rep";
}
}
+10 -11
View File
@@ -144,16 +144,15 @@ auto HandleCall(FunctionContext& context, SemIR::InstId inst_id,
llvm::ArrayRef<SemIR::InstId> arg_ids =
context.sem_ir().inst_blocks().Get(inst.args_id);
if (SemIR::GetInitializingRepresentation(context.sem_ir(), inst.type_id)
.has_return_slot()) {
if (SemIR::GetInitRepr(context.sem_ir(), inst.type_id).has_return_slot()) {
args.push_back(context.GetValue(arg_ids.back()));
arg_ids = arg_ids.drop_back();
}
for (auto arg_id : arg_ids) {
auto arg_type_id = context.sem_ir().insts().Get(arg_id).type_id();
if (SemIR::GetValueRepresentation(context.sem_ir(), arg_type_id).kind !=
SemIR::ValueRepresentation::None) {
if (SemIR::GetValueRepr(context.sem_ir(), arg_type_id).kind !=
SemIR::ValueRepr::None) {
args.push_back(context.GetValue(arg_id));
}
}
@@ -256,16 +255,16 @@ auto HandleReturn(FunctionContext& context, SemIR::InstId /*inst_id*/,
auto HandleReturnExpr(FunctionContext& context, SemIR::InstId /*inst_id*/,
SemIR::ReturnExpr inst) -> void {
switch (SemIR::GetInitializingRepresentation(
context.sem_ir(),
context.sem_ir().insts().Get(inst.expr_id).type_id())
.kind) {
case SemIR::InitializingRepresentation::None:
case SemIR::InitializingRepresentation::InPlace:
switch (
SemIR::GetInitRepr(context.sem_ir(),
context.sem_ir().insts().Get(inst.expr_id).type_id())
.kind) {
case SemIR::InitRepr::None:
case SemIR::InitRepr::InPlace:
// Nothing to return.
context.builder().CreateRetVoid();
return;
case SemIR::InitializingRepresentation::ByCopy:
case SemIR::InitRepr::ByCopy:
// The expression produces the value representation for the type.
context.builder().CreateRet(context.GetValue(inst.expr_id));
return;
+26 -33
View File
@@ -37,20 +37,19 @@ static auto GetAggregateElement(FunctionContext& context,
case SemIR::ExprCategory::Value: {
auto value_rep =
SemIR::GetValueRepresentation(context.sem_ir(), aggr_inst.type_id());
CARBON_CHECK(value_rep.aggregate_kind !=
SemIR::ValueRepresentation::NotAggregate)
SemIR::GetValueRepr(context.sem_ir(), aggr_inst.type_id());
CARBON_CHECK(value_rep.aggregate_kind != SemIR::ValueRepr::NotAggregate)
<< "aggregate type should have aggregate value representation";
switch (value_rep.kind) {
case SemIR::ValueRepresentation::Unknown:
case SemIR::ValueRepr::Unknown:
CARBON_FATAL() << "Lowering access to incomplete aggregate type";
case SemIR::ValueRepresentation::None:
case SemIR::ValueRepr::None:
return aggr_value;
case SemIR::ValueRepresentation::Copy:
case SemIR::ValueRepr::Copy:
// We are holding the values of the aggregate directly, elementwise.
return context.builder().CreateExtractValue(aggr_value, idx.index,
name);
case SemIR::ValueRepresentation::Pointer: {
case SemIR::ValueRepr::Pointer: {
// The value representation is a pointer to an aggregate that we want
// to index into.
auto pointee_type_id =
@@ -67,12 +66,11 @@ static auto GetAggregateElement(FunctionContext& context,
// `elem_ptr` points to a value representation. Load it.
auto result_value_type_id =
SemIR::GetValueRepresentation(context.sem_ir(), result_type_id)
.type_id;
SemIR::GetValueRepr(context.sem_ir(), result_type_id).type_id;
return context.builder().CreateLoad(
context.GetType(result_value_type_id), elem_ptr, name + ".load");
}
case SemIR::ValueRepresentation::Custom:
case SemIR::ValueRepr::Custom:
CARBON_FATAL()
<< "Aggregate should never have custom value representation";
}
@@ -120,8 +118,7 @@ auto HandleClassElementAccess(FunctionContext& context, SemIR::InstId inst_id,
inst_id,
GetAggregateElement(
context, inst.base_id, inst.index, inst.type_id,
GetStructFieldName(context, class_info.object_representation_id,
inst.index)));
GetStructFieldName(context, class_info.object_repr_id, inst.index)));
}
static auto EmitAggregateInitializer(FunctionContext& context,
@@ -130,14 +127,13 @@ static auto EmitAggregateInitializer(FunctionContext& context,
llvm::Twine name) -> llvm::Value* {
auto* llvm_type = context.GetType(type_id);
switch (
SemIR::GetInitializingRepresentation(context.sem_ir(), type_id).kind) {
case SemIR::InitializingRepresentation::None:
case SemIR::InitializingRepresentation::InPlace:
switch (SemIR::GetInitRepr(context.sem_ir(), type_id).kind) {
case SemIR::InitRepr::None:
case SemIR::InitRepr::InPlace:
// TODO: Add a helper to poison a value slot.
return llvm::PoisonValue::get(llvm_type);
case SemIR::InitializingRepresentation::ByCopy: {
case SemIR::InitRepr::ByCopy: {
auto refs = context.sem_ir().inst_blocks().Get(refs_id);
CARBON_CHECK(refs.size() == 1)
<< "Unexpected size for aggregate with by-copy value representation";
@@ -185,20 +181,19 @@ auto HandleStructLiteral(FunctionContext& /*context*/,
// Emits the value representation for a struct or tuple whose elements are the
// contents of `refs_id`.
auto EmitAggregateValueRepresentation(FunctionContext& context,
SemIR::TypeId type_id,
SemIR::InstBlockId refs_id,
llvm::Twine name) -> llvm::Value* {
auto value_rep = SemIR::GetValueRepresentation(context.sem_ir(), type_id);
auto EmitAggregateValueRepr(FunctionContext& context, SemIR::TypeId type_id,
SemIR::InstBlockId refs_id, llvm::Twine name)
-> llvm::Value* {
auto value_rep = SemIR::GetValueRepr(context.sem_ir(), type_id);
switch (value_rep.kind) {
case SemIR::ValueRepresentation::Unknown:
case SemIR::ValueRepr::Unknown:
CARBON_FATAL() << "Incomplete aggregate type in lowering";
case SemIR::ValueRepresentation::None:
case SemIR::ValueRepr::None:
// TODO: Add a helper to get a "no value representation" value.
return llvm::PoisonValue::get(context.GetType(value_rep.type_id));
case SemIR::ValueRepresentation::Copy: {
case SemIR::ValueRepr::Copy: {
auto refs = context.sem_ir().inst_blocks().Get(refs_id);
CARBON_CHECK(refs.size() == 1)
<< "Unexpected size for aggregate with by-copy value representation";
@@ -209,7 +204,7 @@ auto EmitAggregateValueRepresentation(FunctionContext& context,
context.GetValue(refs[0]), {0});
}
case SemIR::ValueRepresentation::Pointer: {
case SemIR::ValueRepr::Pointer: {
auto pointee_type_id = context.sem_ir().GetPointeeType(value_rep.type_id);
auto* llvm_value_rep_type = context.GetType(pointee_type_id);
@@ -227,7 +222,7 @@ auto EmitAggregateValueRepresentation(FunctionContext& context,
return alloca;
}
case SemIR::ValueRepresentation::Custom:
case SemIR::ValueRepr::Custom:
CARBON_FATAL()
<< "Aggregate should never have custom value representation";
}
@@ -242,9 +237,8 @@ auto HandleStructInit(FunctionContext& context, SemIR::InstId inst_id,
auto HandleStructValue(FunctionContext& context, SemIR::InstId inst_id,
SemIR::StructValue inst) -> void {
context.SetLocal(
inst_id, EmitAggregateValueRepresentation(context, inst.type_id,
inst.elements_id, "struct"));
context.SetLocal(inst_id, EmitAggregateValueRepr(context, inst.type_id,
inst.elements_id, "struct"));
}
auto HandleStructTypeField(FunctionContext& /*context*/,
@@ -285,9 +279,8 @@ auto HandleTupleInit(FunctionContext& context, SemIR::InstId inst_id,
auto HandleTupleValue(FunctionContext& context, SemIR::InstId inst_id,
SemIR::TupleValue inst) -> void {
context.SetLocal(inst_id,
EmitAggregateValueRepresentation(context, inst.type_id,
inst.elements_id, "tuple"));
context.SetLocal(inst_id, EmitAggregateValueRepr(context, inst.type_id,
inst.elements_id, "tuple"));
}
} // namespace Carbon::Lower
+12 -16
View File
@@ -9,28 +9,27 @@ namespace Carbon::Lower {
auto HandleBindValue(FunctionContext& context, SemIR::InstId inst_id,
SemIR::BindValue inst) -> void {
switch (auto rep =
SemIR::GetValueRepresentation(context.sem_ir(), inst.type_id);
switch (auto rep = SemIR::GetValueRepr(context.sem_ir(), inst.type_id);
rep.kind) {
case SemIR::ValueRepresentation::Unknown:
case SemIR::ValueRepr::Unknown:
CARBON_FATAL()
<< "Value binding for type with incomplete value representation";
case SemIR::ValueRepresentation::None:
case SemIR::ValueRepr::None:
// Nothing should use this value, but StubRef needs a value to
// propagate.
// TODO: Remove this now the StubRefs are gone.
context.SetLocal(inst_id,
llvm::PoisonValue::get(context.GetType(inst.type_id)));
break;
case SemIR::ValueRepresentation::Copy:
case SemIR::ValueRepr::Copy:
context.SetLocal(inst_id, context.builder().CreateLoad(
context.GetType(inst.type_id),
context.GetValue(inst.value_id)));
break;
case SemIR::ValueRepresentation::Pointer:
case SemIR::ValueRepr::Pointer:
context.SetLocal(inst_id, context.GetValue(inst.value_id));
break;
case SemIR::ValueRepresentation::Custom:
case SemIR::ValueRepr::Custom:
CARBON_FATAL() << "TODO: Add support for BindValue with custom value rep";
}
}
@@ -52,9 +51,8 @@ auto HandleValueAsRef(FunctionContext& context, SemIR::InstId inst_id,
SemIR::ValueAsRef inst) -> void {
CARBON_CHECK(SemIR::GetExprCategory(context.sem_ir(), inst.value_id) ==
SemIR::ExprCategory::Value);
CARBON_CHECK(
SemIR::GetValueRepresentation(context.sem_ir(), inst.type_id).kind ==
SemIR::ValueRepresentation::Pointer);
CARBON_CHECK(SemIR::GetValueRepr(context.sem_ir(), inst.type_id).kind ==
SemIR::ValueRepr::Pointer);
context.SetLocal(inst_id, context.GetValue(inst.value_id));
}
@@ -62,12 +60,10 @@ auto HandleValueOfInitializer(FunctionContext& context, SemIR::InstId inst_id,
SemIR::ValueOfInitializer inst) -> void {
CARBON_CHECK(SemIR::GetExprCategory(context.sem_ir(), inst.init_id) ==
SemIR::ExprCategory::Initializing);
CARBON_CHECK(
SemIR::GetValueRepresentation(context.sem_ir(), inst.type_id).kind ==
SemIR::ValueRepresentation::Copy);
CARBON_CHECK(
SemIR::GetInitializingRepresentation(context.sem_ir(), inst.type_id)
.kind == SemIR::InitializingRepresentation::ByCopy);
CARBON_CHECK(SemIR::GetValueRepr(context.sem_ir(), inst.type_id).kind ==
SemIR::ValueRepr::Copy);
CARBON_CHECK(SemIR::GetInitRepr(context.sem_ir(), inst.type_id).kind ==
SemIR::InitRepr::ByCopy);
context.SetLocal(inst_id, context.GetValue(inst.init_id));
}
+12 -13
View File
@@ -16,7 +16,7 @@
namespace Carbon::SemIR {
auto ValueRepresentation::Print(llvm::raw_ostream& out) const -> void {
auto ValueRepr::Print(llvm::raw_ostream& out) const -> void {
out << "{kind: ";
switch (kind) {
case Unknown:
@@ -39,7 +39,7 @@ auto ValueRepresentation::Print(llvm::raw_ostream& out) const -> void {
}
auto TypeInfo::Print(llvm::raw_ostream& out) const -> void {
out << "{inst: " << inst_id << ", value_rep: " << value_representation << "}";
out << "{inst: " << inst_id << ", value_rep: " << value_repr << "}";
}
File::File(SharedValueStores& value_stores)
@@ -585,23 +585,22 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
}
}
auto GetInitializingRepresentation(const File& file, TypeId type_id)
-> InitializingRepresentation {
auto value_rep = GetValueRepresentation(file, type_id);
auto GetInitRepr(const File& file, TypeId type_id) -> InitRepr {
auto value_rep = GetValueRepr(file, type_id);
switch (value_rep.kind) {
case ValueRepresentation::None:
return {.kind = InitializingRepresentation::None};
case ValueRepr::None:
return {.kind = InitRepr::None};
case ValueRepresentation::Copy:
case ValueRepr::Copy:
// TODO: Use in-place initialization for types that have non-trivial
// destructive move.
return {.kind = InitializingRepresentation::ByCopy};
return {.kind = InitRepr::ByCopy};
case ValueRepresentation::Pointer:
case ValueRepresentation::Custom:
return {.kind = InitializingRepresentation::InPlace};
case ValueRepr::Pointer:
case ValueRepr::Custom:
return {.kind = InitRepr::InPlace};
case ValueRepresentation::Unknown:
case ValueRepr::Unknown:
CARBON_FATAL()
<< "Attempting to perform initialization of incomplete type";
}
+16 -21
View File
@@ -78,9 +78,7 @@ struct Class : public Printable<Class> {
// Determines whether this class has been fully defined. This is false until
// we reach the `}` of the class definition.
auto is_defined() const -> bool {
return object_representation_id.is_valid();
}
auto is_defined() const -> bool { return object_repr_id.is_valid(); }
// The following members always have values, and do not change throughout the
// lifetime of the class.
@@ -115,11 +113,11 @@ struct Class : public Printable<Class> {
// The object representation type to use for this class. This is valid once
// the class is defined.
TypeId object_representation_id = TypeId::Invalid;
TypeId object_repr_id = TypeId::Invalid;
};
// The value representation to use when passing by value.
struct ValueRepresentation : public Printable<ValueRepresentation> {
struct ValueRepr : public Printable<ValueRepr> {
auto Print(llvm::raw_ostream& out) const -> void;
enum Kind : int8_t {
@@ -178,7 +176,7 @@ struct TypeInfo : public Printable<TypeInfo> {
InstId inst_id;
// The value representation for this type. Will be `Unknown` if the type is
// not complete.
ValueRepresentation value_representation = ValueRepresentation();
ValueRepr value_repr = ValueRepr();
};
// Provides semantic analysis on a Parse::Tree.
@@ -213,16 +211,15 @@ class File : public Printable<File> {
}
// Marks a type as complete, and sets its value representation.
auto CompleteType(TypeId object_type_id,
ValueRepresentation value_representation) -> void {
auto CompleteType(TypeId object_type_id, ValueRepr value_repr) -> void {
if (object_type_id.index < 0) {
// We already know our builtin types are complete.
return;
}
CARBON_CHECK(types().Get(object_type_id).value_representation.kind ==
ValueRepresentation::Unknown)
CARBON_CHECK(types().Get(object_type_id).value_repr.kind ==
ValueRepr::Unknown)
<< "Type " << object_type_id << " completed more than once";
types().Get(object_type_id).value_representation = value_representation;
types().Get(object_type_id).value_repr = value_repr;
complete_types_.push_back(object_type_id);
}
@@ -240,18 +237,18 @@ class File : public Printable<File> {
// Gets the value representation to use for a type. This returns an
// invalid type if the given type is not complete.
auto GetValueRepresentation(TypeId type_id) const -> ValueRepresentation {
auto GetValueRepr(TypeId type_id) const -> ValueRepr {
if (type_id.index < 0) {
// TypeType and InvalidType are their own value representation.
return {.kind = ValueRepresentation::Copy, .type_id = type_id};
return {.kind = ValueRepr::Copy, .type_id = type_id};
}
return types().Get(type_id).value_representation;
return types().Get(type_id).value_repr;
}
// Determines whether the given type is known to be complete. This does not
// determine whether the type could be completed, only whether it has been.
auto IsTypeComplete(TypeId type_id) const -> bool {
return GetValueRepresentation(type_id).kind != ValueRepresentation::Unknown;
return GetValueRepr(type_id).kind != ValueRepr::Unknown;
}
// Gets the pointee type of the given type, which must be a pointer type.
@@ -420,13 +417,12 @@ enum class ExprCategory : int8_t {
auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory;
// Returns information about the value representation to use for a type.
inline auto GetValueRepresentation(const File& file, TypeId type_id)
-> ValueRepresentation {
return file.GetValueRepresentation(type_id);
inline auto GetValueRepr(const File& file, TypeId type_id) -> ValueRepr {
return file.GetValueRepr(type_id);
}
// The initializing representation to use when returning by value.
struct InitializingRepresentation {
struct InitRepr {
enum Kind : int8_t {
// The type has no initializing representation. This is used for empty
// types, where no initialization is necessary.
@@ -449,8 +445,7 @@ struct InitializingRepresentation {
};
// Returns information about the initializing representation to use for a type.
auto GetInitializingRepresentation(const File& file, TypeId type_id)
-> InitializingRepresentation;
auto GetInitRepr(const File& file, TypeId type_id) -> InitRepr;
} // namespace Carbon::SemIR
+1 -2
View File
@@ -789,8 +789,7 @@ class Formatter {
llvm::ArrayRef<InstId> args = sem_ir_.inst_blocks().Get(inst.args_id);
bool has_return_slot =
GetInitializingRepresentation(sem_ir_, inst.type_id).has_return_slot();
bool has_return_slot = GetInitRepr(sem_ir_, inst.type_id).has_return_slot();
InstId return_slot_id = InstId::Invalid;
if (has_return_slot) {
return_slot_id = args.back();