Skip to content
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

[CIR][CodeGen][Bugfix] bitfields: use the storage type ifor the getMeberOp #261

Closed
wants to merge 1 commit into from

Conversation

gitoleg
Copy link
Collaborator

@gitoleg gitoleg commented Sep 15, 2023

Here is a fast-fix for the bit-fields PR, because now the tests don't pass. Basically, the bugs disclosed by the last changes in GetMemberOp::verify Bypass get_member verifier

There is one bug that remain unfixed though - and it's kind of weird since everything was ok recently.

Speaking about the fix itself. Previously the result type for the GetMemberOp was inferred from FieldDecl, now - from the storage size. Also, there are changes in tests: since storages for bitfields are unsigned, we don't need to add a cast after the getMemverOp

Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

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

I just reverted your patch, the trunk should never be broken. After you answer the inline questions, please incorporate the changes here with the original change and submit a new PR. Thanks

Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base,
const FieldDecl *field,
unsigned index,
unsigned size) {
Copy link
Member

Choose a reason for hiding this comment

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

Why are you changing the function signature? Why wasn't it getAddrOfBitFieldStorage in the first place?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The function was introduced by me and in previous version it was not intended to work with bitfields only. After the last changes it will serve only them though. That's why I renamed it and added one more argument

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good.

if (index == 0)
return base.getAddress();

auto loc = getLoc(field->getLocation());
auto fieldType = convertType(field->getType());
auto fieldType = builder.getUIntNTy(size);
Copy link
Member

Choose a reason for hiding this comment

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

Please explain why it shouldn't use convertType here.

Copy link
Collaborator Author

@gitoleg gitoleg Sep 17, 2023

Choose a reason for hiding this comment

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

convertType for the integer field is always 32, type mismatch guaranteed, see a longer comment below

Copy link
Member

Choose a reason for hiding this comment

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

So please add assert(convertType(field->getType()) == ...)

const unsigned SS = useVolatile ? info.VolatileStorageSize : info.StorageSize;
Address Addr = getAddrOfBitFieldStorage(base, field, Idx, SS);
Copy link
Member

Choose a reason for hiding this comment

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

What's LLVM codegen doing here? Does it call getAddrOfBitFieldStorage or getAddrOfField?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

there is no LLVM codegen here.

Copy link
Member

Choose a reason for hiding this comment

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

I mean, we follow the principle of using the same skeleton as clang/lib/CodeGen, at least to the extend of what's possible.

I don't see anything similar to getAddrOfBitFieldStorage or getAddrOfField in clang/lib/CodeGen/*, and I want to understand what's the rationale there. Are those names introduced for specific functionality you refactor into helpers or are they complete new names for something that already existed in clang/lib/CodeGen? If so, I'm trying to understand why can't you just s/Emit/build and call it a day?

clang/test/CIR/CodeGen/bitfields.c Show resolved Hide resolved
@bcardosolopes
Copy link
Member

Speaking about the fix itself. Previously the result type for the GetMemberOp was inferred from FieldDecl, now - from the storage size.

Please elaborate on a rationale

@gitoleg
Copy link
Collaborator Author

gitoleg commented Sep 17, 2023

@bcardosolopes
So. Speaking about what is all about.
As I said, the last changes in the GetMemverOp::verify make some bugs visible. That's good actually!!

So now, all the problems were investigated and everything works.

The two problems appeared in the verification stage:

  1. type mismatch
  2. index out of bounds (my fault, didn't test the PR for a long time, concentrated on the minor fixes)

Answering one more time to your question about the convertType usage. The type for the bit field is created in the CIRRecordLayoutBuilder and is an integer type of the bitwidth that is closest value to the power of two. The type, created by convertType call you pointed at is a result type that is always of 32 bit length for integers. Hence the problem: the result type must be even with the type of a field being accessed. Otherwise type mismatch error will be emitted during the verification. Thus, we create an integer type of the storage bitwidth for the given field. This fixes the type mismatch problem.

Concerning indexes problems.
There is a bug in creation of get_member in the case of C++ inheritance - and I need to create a PR for that at first place. You can take a look at CIR/CodeGen/derived-to-base.cpp . The point is the get_member is created with index 0, what is not true if there is a base class. That kind of made me think that it was my bug somewhere, so l went the wrong way. Anyways, I'm going to fix this as well.

Btw, for some reasons I thought that you have a sort of CI here - I saw some green check mark as if a PR was tested somehow. But after the second glance, there was nothing that was tested. Is it true?

Once it sounds ok, I can push and updated PR here or create a new one, up to you.

@bcardosolopes
Copy link
Member

  1. index out of bounds (my fault, didn't test the PR for a long time, concentrated on the minor fixes)

It happens.

Answering one more time to your question about the convertType usage. The type for the bit field is created in the CIRRecordLayoutBuilder and is an integer type of the bitwidth that is closest value to the power of two. The type, created by convertType call you pointed at is a result type that is always of 32 bit length for integers. Hence the problem: the result type must be even with the type of a field being accessed. Otherwise type mismatch error will be emitted during the verification. Thus, we create an integer type of the storage bitwidth for the given field. This fixes the type mismatch problem.

Thanks for the detailed explanation, please add an assert with your assumption there then, in case for some ABI reasons something different show up, I'd prefer if it crashes at that point and we can easily fix.

Concerning indexes problems. There is a bug in creation of get_member in the case of C++ inheritance - and I need to create a PR for that at first place. You can take a look at CIR/CodeGen/derived-to-base.cpp . The point is the get_member is created with index 0, what is not true if there is a base class. That kind of made me think that it was my bug somewhere, so l went the wrong way. Anyways, I'm going to fix this as well.

Nice, I can see that. Thanks for catching this (and investigating a fix). Could be its own PR though, right? Sounds to me this isn't blocking a fix to land you bitfield work, but correct me if I'm wrong.

Btw, for some reasons I thought that you have a sort of CI here - I saw some green check mark as if a PR was tested somehow. But after the second glance, there was nothing that was tested. Is it true?

I wish we had, and I understand that green mark is misleading. I need to sort that out at some point! I currently do some internal testing on our codebase, but that's it.

Once it sounds ok, I can push and updated PR here or create a new one, up to you.

If you can change the name of this PR than this one is fine, otherwise might be better to create a new one.

@bcardosolopes
Copy link
Member

Nice, I can see that. Thanks for catching this (and investigating a fix). Could be its own PR though, right? Sounds to me this isn't blocking a fix to land you bitfield work, but correct me if I'm wrong.

Oh, this is #263, never mind :)

bcardosolopes pushed a commit that referenced this pull request Sep 26, 2023
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;  
  unsigned f;
} S; 
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.
 
Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8 

The cases covered with tests.
@bcardosolopes
Copy link
Member

Work here has been done in #268

lanza pushed a commit that referenced this pull request Oct 27, 2023
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;  
  unsigned f;
} S; 
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.
 
Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8 

The cases covered with tests.
lanza pushed a commit that referenced this pull request Dec 20, 2023
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;  
  unsigned f;
} S; 
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.
 
Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8 

The cases covered with tests.
lanza pushed a commit that referenced this pull request Jan 29, 2024
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
lanza pushed a commit to lanza/llvm-project that referenced this pull request Feb 8, 2024
…lvm#268)

This is an updated PR for [PR
llvm#233](llvm/clangir#233) with some fixes
explained in [PR llvm#261](llvm/clangir#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
lanza pushed a commit that referenced this pull request Mar 23, 2024
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
eZWALT pushed a commit to eZWALT/clangir that referenced this pull request Mar 24, 2024
…lvm#268)

This is an updated PR for [PR
llvm#233](llvm#233) with some fixes
explained in [PR llvm#261](llvm#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
lanza pushed a commit that referenced this pull request Apr 29, 2024
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
lanza pushed a commit that referenced this pull request Apr 29, 2024
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
eZWALT pushed a commit to eZWALT/clangir that referenced this pull request Apr 29, 2024
…lvm#268)

This is an updated PR for [PR
llvm#233](llvm#233) with some fixes
explained in [PR llvm#261](llvm#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
lanza pushed a commit that referenced this pull request Apr 29, 2024
This is an updated PR for [PR
#233](#233) with some fixes
explained in [PR #261](#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
pysuxing pushed a commit to pysuxing/llvm-project that referenced this pull request Jul 17, 2024
…lvm#268)

This is an updated PR for [PR
llvm#233](llvm/clangir#233) with some fixes
explained in [PR llvm#261](llvm/clangir#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
Hugobros3 pushed a commit to shady-gang/clangir that referenced this pull request Oct 2, 2024
…lvm#268)

This is an updated PR for [PR
llvm#233](llvm#233) with some fixes
explained in [PR llvm#261](llvm#261) which
now can be safely closed.

First of all, let me introduce how do the bitfields looks like in CIR.
For the struct `S` defined as following:
```
typedef struct {
  int a : 4;
  int b : 27;
  int c : 17;
  int d : 2;
  int e : 15;
  unsigned f;
} S;
```
the CIR type is `!ty_22S22 = !cir.struct<struct "S" {!u32i, !u32i,
!u16i, !u32i} #cir.record.decl.ast>` where all the bitfields are packed
in the first three storages.

Also, the next bugs was fixed:
- type mismatch
- index out of bounds
- single bitfield of size < 8

The cases covered with tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants