[MCAssembler] changing layout in assembler backend

Our target has a perhaps unique problem relating to code alignment. Like other targets, it wants to insert NOPs for an FT_Align fragment. The unique part is that it has a way to “fold” these NOPs into the previous instruction packet, so that when falling through to the aligned label there is no execution penalty. Doing so requires re-encoding the previous packet, which “enlarges” it such that no actual NOPs are needed.

So I’d like to do this in the target-specific MCAsmBackend, in the finishLayout hook which is called after the MCAssembler finishes the layout pass. The idea is to look for FT_Align fragments, see how much padding they generate, find the previous packet, and re-encode it. The problem is that doing so changes the layout – sort of. Actually, it just changes the offset of the FT_Align fragment because the previous packet is larger. I could just do that directly… but the Offset member is private to the Fragment and only settable by its friend the MCAsmLayout class.

I looked at doing this via relaxation but there is not enough context. In particular the backend’s relaxation API does not have access to the fragment list.

Also I noticed there is an interesting looking mechanism called MCCodePadder, but it’s super obtuse and no in-tree targets seem to use it.

For now I just made MCFragment’s Offset public and modified it directly from finishLayout. But that seems like it significantly undermines the design. Ideally I think the MCAsmBackend should have authority to do whatever it needs to do, including adjusting the layout (especially in an API called “finishLayout”) but currently that is not the case. I’m looking for advice on how to make this work with minimal changes to the existing APIs.

-Alan