Skip to content

[CIR][CodeGen] fixes access to globals with bitfields #1244

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

Merged

Conversation

gitoleg
Copy link
Collaborator

@gitoleg gitoleg commented Dec 19, 2024

This PR adds a bitcast when we rewrite globals type. Previously we just set a new type and it worked.
But recently I started to test ClangIR with CSmith in order to find some run time bugs and faced with the next problem.

typedef struct {
    int x : 15;   
    uint8_t y;
} S;

S g = { -12, 254};

int main() {    
    printf("%d\n", g.y);
    return 0;
}

The output for this program is ... 127 but not 254!
The reason is that first global var is created with the type of struct S, then get_member operation is generated with index 1
and then after, the type of the global is rewritten - I assume because of the anon struct created on the right side in the initialization.
But the get_member operation still wants to access to the field at index 1 and get a wrong byte.
If we change the y type to int we will fail on the verification stage. But in the example above it's a run time error!

This is why I suggest to add a bitcast once we have to rewrite the global type.

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.

Nice catch!

@bcardosolopes bcardosolopes merged commit 5f3b2c3 into llvm:main Dec 19, 2024
7 checks passed
lanza pushed a commit that referenced this pull request Mar 18, 2025
This PR adds a bitcast when we rewrite globals type. Previously we just
set a new type and it worked.
But recently I started to test ClangIR with CSmith in order to find some
run time bugs and faced with the next problem.

```
typedef struct {
    int x : 15;   
    uint8_t y;
} S;

S g = { -12, 254};

int main() {    
    printf("%d\n", g.y);
    return 0;
}

```
The output for this program is  ... 127 but not 254!
The reason is that first global var is created with the type of struct
`S`, then `get_member` operation is generated with index `1`
and then after, the type of the global is rewritten - I assume because
of the anon struct created on the right side in the initialization.
But the `get_member` operation still wants to access to the field at
index `1` and get a wrong byte.
If we change the `y` type to `int` we will fail on the verification
stage. But in the example above it's a run time error!

This is why I suggest to add a bitcast once we have to rewrite the
global type.
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