Skip to content

Conversation

danakj
Copy link
Contributor

@danakj danakj commented Oct 7, 2025

We swap the labels for ImportIRId and CheckIRId, so that CheckIRId the short name "ir" as this is now part of other ids (included as a tag), and is dumped as part of the id. Currently this is only for InstId but other Ids are coming.

Then we make the dumping process of the CheckIRId a bit more typesafe by having the IdTag return a CheckIRId, and we print it in the usual way so that any special casing in the implementation of CheckIRId::Print will be used.

TODOs are left behind to improve the typesafety for IdTag.

@danakj
Copy link
Contributor Author

danakj commented Oct 7, 2025

Based on #6168, first commit is rename-irs

}

struct IrAndIndex {
int32_t check_ir_id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't this use CheckIRId? TBH I'm even a little confused why int32_t for index, it seems like this could either be InstId, or a template like:

  template <typename IdT>
  static auto DecomposeWithBestEffort(IdT id) -> std::pair<SemIR::CheckIRId, IdT> {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because this is in base/ not in sem_ir/. I wanted to make it use CheckIRId also but layering. We would have to move ValueStore to sem_ir/.

I also see on the PR introducing this that @zygoloid was thinking about future ValueStore usage where the tag would not even be a CheckIRId.

So maybe I should actually not call this check_ir_id at all here either, I will generalize it.

I think we could consider adding a type InstId::TagType = CheckIRId and then we could template the IdTag class and make things more typesafe - with a fallback to int32_t (or maybe a sentinel type?) for id types that don't specify a tag type. Maybe we could have a specialization of IdTag that more obviously does nothing in those cases.

int32_t index;
};

static auto DecomposeWithBestEffort(int32_t tagged_index) -> IrAndIndex {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's worth adding comments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe @dwblaikie is going to follow up with some comments here

return (llvm::reverseBits(2) & tagged_index) != 0;
}

struct IrAndIndex {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we usually write "IR" instead of "Ir"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// zero-based, to make it a bit less likely this doesn't collide with
// anything else (though with the second-highest-bit-tagging this might not
// be needed).
id_tag_ = llvm::reverseBits((((id_index + 1) << 1) | 1) << 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're editing constructors, perhaps this should be done via initializer list instead of assignment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

IdBase::Print(out);
} else {
out << "ir" << ir_id << ".inst" << simple_index;
out << CheckIRId::Label << check_ir_id << "." << Label << inst_id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe construct a CheckIRId here and use it for formatting? That way too, if we add special formatting (e.g. for Cpp) it would automatically get it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, thanks

Comment on lines +120 to +133
int32_t id_tag_ = 0;
int32_t initial_reserved_ids_ = std::numeric_limits<int32_t>::max();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you switch away from the prior setup? It seemed safer, since there are only two constructors and both must set different values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setting things on the fields is generally safer and preferred. It's easy to miss a field in the other form. If you do, this way they all get initialized to some default value at least.

Copy link
Contributor Author

@danakj danakj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PTAL

}

struct IrAndIndex {
int32_t check_ir_id;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because this is in base/ not in sem_ir/. I wanted to make it use CheckIRId also but layering. We would have to move ValueStore to sem_ir/.

I also see on the PR introducing this that @zygoloid was thinking about future ValueStore usage where the tag would not even be a CheckIRId.

So maybe I should actually not call this check_ir_id at all here either, I will generalize it.

I think we could consider adding a type InstId::TagType = CheckIRId and then we could template the IdTag class and make things more typesafe - with a fallback to int32_t (or maybe a sentinel type?) for id types that don't specify a tag type. Maybe we could have a specialization of IdTag that more obviously does nothing in those cases.

int32_t index;
};

static auto DecomposeWithBestEffort(int32_t tagged_index) -> IrAndIndex {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe @dwblaikie is going to follow up with some comments here

Comment on lines +120 to +133
int32_t id_tag_ = 0;
int32_t initial_reserved_ids_ = std::numeric_limits<int32_t>::max();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setting things on the fields is generally safer and preferred. It's easy to miss a field in the other form. If you do, this way they all get initialized to some default value at least.

return (llvm::reverseBits(2) & tagged_index) != 0;
}

struct IrAndIndex {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// zero-based, to make it a bit less likely this doesn't collide with
// anything else (though with the second-highest-bit-tagging this might not
// be needed).
id_tag_ = llvm::reverseBits((((id_index + 1) << 1) | 1) << 1);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

IdBase::Print(out);
} else {
out << "ir" << ir_id << ".inst" << simple_index;
out << CheckIRId::Label << check_ir_id << "." << Label << inst_id;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, thanks

@danakj danakj requested a review from jonmeow October 7, 2025 19:27
@danakj danakj changed the title Swap the labels for ImportIRId and CheckIRId Dump CheckIRId more explicitly for InstId tags Oct 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants