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

Fix handling of empty type #776

Merged
merged 4 commits into from
Nov 11, 2024
Merged

Conversation

ThomasHaas
Copy link
Collaborator

@ThomasHaas ThomasHaas commented Nov 9, 2024

This fixes a bug introduced in #770.

EDIT: I renamed the PR and added more fixes, mostly related to handling the empty type (+ one fix for alignments computation of arrays).

@hernanponcedeleon
Copy link
Owner

I noticed this regression when running the svcomp benchmarks. The fix restores the previous behavior.

@natgavrilenko can you please review?

@ThomasHaas
Copy link
Collaborator Author

There is nothing to review really. The empty struct is 1-aligned but #776 changed the behaviour to throw an error instead.

@natgavrilenko
Copy link
Collaborator

I don't see why it would change the behavior. The getAlignment method is called either from computeDefaultOffsets or from getMemorySizeInBytes. Both caller methods check if the AggregateType is empty.

How can reproduce the problem?

@hernanponcedeleon
Copy link
Owner

Try this file. It should be reproducible with all memory models.

@ThomasHaas
Copy link
Collaborator Author

I just noticed that the commit message of this PR is wrong (it seems I accidentally took the one from #775). Not sure how that happened.

@ThomasHaas
Copy link
Collaborator Author

Btw. I think this part of the alignment computation is wrong (*) as well:

        if (type instanceof ArrayType arrayType) {
            return getMemorySizeInBytes(arrayType.getElementType());
        }

The array should be aligned according to the alignment of its elements, not their size.

(*) This might technically not wrong because we simply overalign. But it does not match the usually expected alignment.

@ThomasHaas
Copy link
Collaborator Author

ThomasHaas commented Nov 10, 2024

Actually, there are more issues.

(1) The behaviour of TypeFactory.getAggregateType(List<Type>) and TypeFactory.getAggregateType(List<Type>, List<Integer>) differ in that the former allows for empty members but the latter does not.

(2) In C, empty structs are undefined behavior, at least in theory!!! The SVCOMP benchmark is thus problematic. GCC allows empty structs as a custom extension and gives them size 0, and since Clang tries to be compatible with GCC, it shows the same behaviour.
Interestingly, in C++ empty structs are allowed but their size is 1 as to disallow different objects occupying the same memory location.
This begs the question: what should we do? Since we do only C for now, the choice of size 0 for the empty struct is probably the best (maybe we need to support a flag in the future like input.language=c++). However, we then inherit the awkward situation of having different objects at the same memory location, i.e., unions.
So the preconditions on TypeFactory.getAggregateType need to get relaxed.

EDIT: I fixed the above mentioned issues.

Fixed alignment computation of arrays.
Added TypeFactory.hasKnownSize helper function.
@ThomasHaas ThomasHaas changed the title Empty type is 1-aligned Fix handling of empty type Nov 10, 2024
@hernanponcedeleon
Copy link
Owner

the choice of size 0 for the empty struct is probably the best

If empty structures are undefined behavior, we should report this and throw an exception when verifying C code.

@natgavrilenko what does the spirv standard say about empty structures? Can we have "This is UB" as a general solution?

@natgavrilenko
Copy link
Collaborator

Try this file. It should be reproducible with all memory models.

Thanks, now I see what is the problem.

@natgavrilenko
Copy link
Collaborator

the choice of size 0 for the empty struct is probably the best

If empty structures are undefined behavior, we should report this and throw an exception when verifying C code.

@natgavrilenko what does the spirv standard say about empty structures? Can we have "This is UB" as a general solution?

Yes, it works fine for spirv with empty structures. @ThomasHaas could you add this case to AggregateTypeTest?

@ThomasHaas
Copy link
Collaborator Author

If empty structures are undefined behavior, we should report this and throw an exception when verifying C code.

I think this solution is not practically viable because its a feature that is expected to work since GCC/Clang support it. One might say it is more implementation-defined in practice rather than undefined. On top of that you have the issue that we are technically parsing LLVM and not C directly, and so it makes sense to take LLVM semantics into account. For LLVM, empty structs are not an issue it seems.

@ThomasHaas
Copy link
Collaborator Author

[...] @ThomasHaas could you add this case to AggregateTypeTest?

will do.

@hernanponcedeleon hernanponcedeleon merged commit 025e4a7 into development Nov 11, 2024
1 check passed
@hernanponcedeleon hernanponcedeleon deleted the fixAlignmentOfEmptyType branch November 11, 2024 11:59
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.

3 participants