This is an archive of the discontinued LLVM Phabricator instance.

[X86] Fix the implementation of __readcr3/__writecr3 to work in 64-bit mode
ClosedPublic

Authored by craig.topper on Nov 11 2019, 3:08 PM.

Details

Summary

We need to use a 64-bit type in 64-bit mode so a 64-bit register will get used in the generated assembly. I've also changed the constraints to just use "r" intead of "q". "q" forces to a only an a/b/c/d register in 32-bit mode, but I see no reason that would matter here. Still not sure why in 32-bit mode one uses long and the other uses int, but I'm just going to leave that alone.

Fixes Nico's note in PR19301 over 4 years ago.

Diff Detail

Event Timeline

craig.topper created this revision.Nov 11 2019, 3:08 PM
craig.topper edited subscribers, added: cfe-commits; removed: llvm-commits.Nov 11 2019, 3:22 PM
rnk added a comment.Nov 11 2019, 3:27 PM

What do you think of using __INTPTR_TYPE__ for this instead? If that doesn't work, we could define and undefine our own macro to use as a typedef. The resulting code should be clean enough that we can generalize it to __readcr0 etc.

It looks like long is the correct return type for 32-bit:
https://gcc.godbolt.org/z/6NzZWz
I'm not sure what the best device to figure out __writecr3 would be.

In D70101#1741452, @rnk wrote:

What do you think of using __INTPTR_TYPE__ for this instead? If that doesn't work, we could define and undefine our own macro to use as a typedef. The resulting code should be clean enough that we can generalize it to __readcr0 etc.

It looks like long is the correct return type for 32-bit:
https://gcc.godbolt.org/z/6NzZWz
I'm not sure what the best device to figure out __writecr3 would be.

I cobbled together some code from stackoverflow. I think the input type for __writecr3 really is int https://gcc.godbolt.org/z/dc8hQq

So in order to match the long and int behavior, I need two different macros to replace the argument? I think INTPTR_TYPE will return int on 32-bit targets so I can't use that for the long case. But maybe for the __int64?

rnk added a comment.Nov 14 2019, 10:27 AM

So in order to match the long and int behavior, I need two different macros to replace the argument? I think INTPTR_TYPE will return int on 32-bit targets so I can't use that for the long case. But maybe for the __int64?

Right, we can use __INTPTR_TYPE__ for all __writecr* functions (they use int or long long), and our own macro (__LPTRINT_TYPE__?) for __readcr*. Make sure to undef it so it doesn't leak out of the header, similar to __DEFAULT_FN_ATTRS.

Add LPTRINT_TYPE and use that to qualify the readcr3. Use INTPTR_TYPE for writecr3

rnk accepted this revision.Nov 14 2019, 12:34 PM

Lgtm

This revision is now accepted and ready to land.Nov 14 2019, 12:34 PM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptNov 14 2019, 1:29 PM