Skip to content

Conversation

Sterling-Augustine
Copy link
Contributor

This PR parses CFI instructions to generate FREs.

Unfortunately, actually emitting the FREs into the object file is somewhat involved and would make this PR quite a bit harder to review. And the dumper itself properly errors if the FRE count is included in the header or FDEs, but they are not actually emitted. So actually testing that the proper FREs are generated will have to wait for a subsequent PR.

For now, just check for common issues with CFI that sframe doesn't support, and that proper error handling is done.

@llvmbot llvmbot added the llvm:mc Machine (object) code label Aug 26, 2025
Copy link

github-actions bot commented Aug 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

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

Looks pretty good overall. I have a bunch of comments, but I don't feel particularly strongly about most of them, so feel free to push back if you disagree (in particular, fields like Invalid are a pet peeve of mine).

The hardcoding of register constants is somewhat unfortunate, not so much because it can change (it's an ABI constant), but because it looks bad. It should be possible to get the RA register number generically (MCRegisterInfo::getRARegister), but it looks like there's no way to get the FP value without depending on a particular backend, so I guess we can live with that.

// asm parser doesn't give a location with .cfi_def_cfa_offset
// CHECK: :0:{{.*}} Adjusting CFA offset without a base register.{{.*}}
// .cfi_adjust_cfa_offset
// CHECK: :13:{{.*}} Adjusting CFA offset without a base register. {{.*}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will make it hard to update the file. Please move the checks next to the code which generates those diagnostics. That makes it easier to see what's being checked, and you can use [[@LINE-1]] to match the line numbers.

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

.cfi_def_cfa 0, 4
nop

.cfi_endproc
Copy link
Collaborator

Choose a reason for hiding this comment

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

something wrong with the indentation here. Tabs?

Copy link
Collaborator

Choose a reason for hiding this comment

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

There's still something wrong with the indentation on this line (.cfi_endproc), at least when I view it in github UI. (I would expect it to start at the same column as the other .cfi directives.

Comment on lines 264 to 269
// Instructions from InitialFrameState may not have a label, but if
// these instructions don't, then they are in dead code or otherwise
// unused.
auto *L = CFI.getLabel();
if (L && !L->isDefined())
continue;
Copy link
Collaborator

Choose a reason for hiding this comment

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

When does this happen? Can we have a test case for these undead CFI insns?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is copied from the corresponding eh_frame code, which was added in 2010 (commit 85d9198), and does not include a test for that case.

Nothing in the testsuite triggers it today, and I haven't been able to reproduce it myself in either location. So it's possible that it isn't necessary today.

On the other hand, there are only seven (non-error checking) tests for .cfi_startproc simple in the codebase. So we are in solidly under-tested waters. The alternative here would be to warn and skip with some sort of "missing label" failure. But I'm wary of erroring on invalid input where eh_frame doesn't.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd be tempted to add an assert and see what/if anything breaks there, but I guess following eh_frame makes sense as well. It would be nice to make a note of why you're doing that, to help someone looking at this in the future.

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'll add a TODO here and when this is in a state to run against some much bigger and a wider variety test cases, will see if it can be removed.

Comment on lines 148 to 149
setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset());
return true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be:

Suggested change
setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset());
return true;
return setCFAOffset(FRE, CFI.getLoc(), CFI.getOffset());

I guess the difference is that if this was the only error, the code would still go on to produce a (broken) FDE entry.

.cfi_def_cfa 0, 4
nop

.cfi_endproc
Copy link
Collaborator

Choose a reason for hiding this comment

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

There's still something wrong with the indentation on this line (.cfi_endproc), at least when I view it in github UI. (I would expect it to start at the same column as the other .cfi directives.

Comment on lines 264 to 269
// Instructions from InitialFrameState may not have a label, but if
// these instructions don't, then they are in dead code or otherwise
// unused.
auto *L = CFI.getLabel();
if (L && !L->isDefined())
continue;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd be tempted to add an assert and see what/if anything breaks there, but I guess following eh_frame makes sense as well. It would be nice to make a note of why you're doing that, to help someone looking at this in the future.

Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

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

This is definitely stretching my knowledge, so I'm going to leave it to others to review. One minor style comment from me only.

// hand-written assembly.
if (DF.RAReg != RAReg) {
Streamer.getContext().reportWarning(
SMLoc(), "Non-default RA register in .cfi_return_column " +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: non-default to conform with LLVM warning style guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants