This is an archive of the discontinued LLVM Phabricator instance.

[builtin] Add bitfield support for __builtin_dump_struct
Needs ReviewPublic

Authored by paulsemel on Jun 8 2018, 10:20 AM.

Details

Summary

This is an attempt for adding bitfield support to __builtin_dump_struct.

Diff Detail

Repository
rC Clang

Event Timeline

paulsemel created this revision.Jun 8 2018, 10:20 AM

This version is working for non packed structures. For packed structures, it might sometimes work, sometimes not.
The resulting assembly code seems to be the right one.
If someone went through bitfields manipulation, please do not hesitate to comment !
Requesting for help :)

This seems to be missing tests.

aaron.ballman added inline comments.Jun 19 2018, 8:26 AM
lib/CodeGen/CGBuiltin.cpp
1250

What happens if this overflows due to being < 0?

I will for sure add tests @lebedev.ri . Fact is that, for the moment, this is not working as expected.
This is why I am asking for a bit of help about this bitfield handling :)

lib/CodeGen/CGBuiltin.cpp
1250

How could this be < 0 ?
If it is, it means that there was a problem during bitfield construction isn't it ?
I mean StorageSize is always greater that Offset + Size

I will for sure add tests @lebedev.ri . Fact is that, for the moment, this is not working as expected.
This is why I am asking for a bit of help about this bitfield handling :)

Adding a few more reviewers to see if they have ideas on the bitfield handling. Can you describe a bit more about what's incorrect with it when the structures are packed? Code examples might help.

lib/CodeGen/CGBuiltin.cpp
1250

I don't think it should happen in the normal course of things. I'd probably just put in an assert to ensure that the high bit is never set in HighBits unless it's also set in StorageSize.

Yeah, I know nothing about this dump feature or what's being fixed here - test cases would be great to help motivate/explain.

paulsemel added a comment.EditedJun 22 2018, 7:23 AM

First thanks all for reviewing !

Basically, what's happening is that it works good with non-packed structures.
Here is an example for packed structure (with unsigned signed short):

struct lol {
	unsigned short a:3;
	unsigned short b:2;
	unsigned short c:6;
	unsigned short d:2;
	unsigned short e:6;
} __attribute__((packed));

int main(void)
{
	struct lol lolo = {
		.a = 2,
		.b = 1,
		.c = 13,
		.d = 2,
		.e = 9
	};
	__builtin_dump_struct(&lolo, &printf);
	return 0;
}

Here is the output I get :

unsigned short a : 2
unsigned short b : 1
unsigned short c : 13
unsigned short d : 2
unsigned short e : 1

The last unsigned short is incorrect.

If I switch this to signed integers, I get :

unsigned short a : 0
unsigned short b : 0
unsigned short c : 0
unsigned short d : 0
unsigned short e : 0

All the fields are zeroed. I absolutely do not understand what is happening...
Thanks for trying to help guys !

This doesn't seem to build for me - so hard to debug/probe it:

llvm/src/tools/clang/lib/CodeGen/CGBuiltin.cpp:1264:65: error: no viable conversion from 'clang::QualType' to 'llvm::Type *'

CGF.CGM.getDataLayout().getTypeSizeInBits(CanonicalType),
                                          ^~~~~~~~~~~~~

llvm/src/include/llvm/IR/DataLayout.h:560:53: note: passing argument to parameter 'Ty' here
inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {

^

1 error generated.

paulsemel updated this revision to Diff 153511.Jun 29 2018, 9:46 AM

Fixed version problem. Now building.

This doesn't seem to build for me - so hard to debug/probe it:

llvm/src/tools/clang/lib/CodeGen/CGBuiltin.cpp:1264:65: error: no viable conversion from 'clang::QualType' to 'llvm::Type *'

CGF.CGM.getDataLayout().getTypeSizeInBits(CanonicalType),
                                          ^~~~~~~~~~~~~

llvm/src/include/llvm/IR/DataLayout.h:560:53: note: passing argument to parameter 'Ty' here
inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {

^

1 error generated.

Very sorry about it, I should have paid more attention..

Yeah, doesn't look like this code handles a value crossing the boundary of
the size of the bitfield type (it's reading only the low bit).

I suspect looking at the code that generates bitfield accesses would be
useful - and/or maybe actually calling into that very code, rather than
reimplementing it here? CodeGenFunction::EmitLoadOfBitfieldLValue seems to
be the place to go (I found this by writing a short example that loads one
of these strided bitfield values & then breaking in
llvm::BinaryOperator::BinaryOperator until I found the 'and' operation,
since that seemed like the more interesting one).