Skip to content

[GlobalOpt] Update debug info when changing CC to Fast #144303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,14 @@ static void RemovePreallocated(Function *F) {
}
}

static unsigned char GetDebugInfoFastCC(const Triple &Triple) {
if (Triple.isOSWindows() && Triple.isArch32Bit()) {
return llvm::dwarf::DW_CC_BORLAND_msfastcall;
}

return llvm::dwarf::DW_CC_normal;
}

Comment on lines +1923 to +1930
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems a bit brittle, if other targets had other calling convention choices - perhaps this logic should go wherever the CC is determined?

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 agree. However, I think the mapping for fastcc is determined by a table definition for each architecture. I feel like integrating this there is not easily feasible.

Do you have a recommendation on how this could be done better?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you point to the table definition, we/someone could take a look to see how practical it is.

Copy link
Contributor Author

@momo5502 momo5502 Jul 3, 2025

Choose a reason for hiding this comment

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

The decision how FastCC is being lowered happens here:

CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_X86_32_FastCC>>,

Here is where the dwarf CC is translated to the CodeView format:

case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;

I feel like the reason this issue arises in the first place is the redundancy for calling convention specifications: the information is stored in the function, as well as the debug info.

What would also work would be a pseudo dwarf calling convention for fastCC that can then be mapped onto the real CC for each respective platform. However, I assume that for most platforms this is just the normal calling convention, which is why this approach seemed to cause the least overhead.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps @zmodem has some thoughts on the PDB side of things, and @nikic has some thoughts on the broader LLVM architectural issue.

Yeah, I'd be open to the right direction being each architecture having a mapping from their real CCs to the DWARF CC they want to use for them, and removing the CC from the LLVM IR debug info metadata.

Copy link
Collaborator

Choose a reason for hiding this comment

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

No PDB specific thoughts really, but it does sound redundant to store the calling convention in the debug info metadata as well (and error prone as it needs to stay in sync).

When we lower the debug metadata (or translate it to codeview), do we have an easy way to get to the llvm::Function? If so it sounds like we should just get the calling convention from there?

Copy link
Collaborator

Choose a reason for hiding this comment

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

We do - the subprogram data is attached to the llvm::Function (so, technically, you could be looking at a subprogram without knowing what function it came from, but that's fixable)

I guess in the case where a DWARF function declaration is emitted with no associated LLVM IR, it might be a problem - in theory we could/may need to still carry a calling convention down through the debug info metadata to handle cases like that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If we don't go the route of dropping it from the metadata, maybe the verifier could check for Function/metadata calling convention consistency?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah - I'm not 100% sure we carry CC on declarations, so someone'd have to check that/see if we need it anyway. And if we do, yeah, checking for consistency would be good - and maybe the metadata would/could carry the same type of CC as the IR, rather than the debug info one - and then only convert from real CC to DWARF CC at the backend.

static bool
OptimizeFunctions(Module &M,
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
Expand All @@ -1938,6 +1946,9 @@ OptimizeFunctions(Module &M,
if (hasOnlyColdCalls(F, GetBFI, ChangeableCCCache))
AllCallsCold.push_back(&F);

unsigned char DebugInfoFastCC =
GetDebugInfoFastCC(Triple(M.getTargetTriple()));

// Optimize functions.
for (Function &F : llvm::make_early_inc_range(M)) {
// Don't perform global opt pass on naked functions; we don't want fast
Expand Down Expand Up @@ -2021,6 +2032,13 @@ OptimizeFunctions(Module &M,
// Fast calling convention.
F.setCallingConv(CallingConv::Fast);
ChangeCalleesToFastCall(&F);

if (F.getSubprogram()) {
DISubprogram *SP = F.getSubprogram();
auto Temp = SP->getType()->cloneWithCC(DebugInfoFastCC);
SP->replaceType(MDNode::replaceWithPermanent(std::move(Temp)));
}

++NumFastCallFns;
Changed = true;
}
Expand Down
Loading