Skip to content

[embedded] Fix IR verification crash when using arrays of zero-sized structs #69010

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
merged 1 commit into from
Oct 9, 2023

Conversation

kubamracek
Copy link
Contributor

The embedded Swift custom ("no runtime calls") IRGen for array builtins today doesn't handle zero-sized structs, when using an array of zero-sized structs, LLVM IR verifier complains:

GEP into unsized type!
  %8 = getelementptr inbounds %T4main8MyStructV, ptr %1, i64 %6

Let's fix that and handle zero-sized structs in GenBuiltin (we don't really need to emit the loop at all for them).

@kubamracek
Copy link
Contributor Author

@swift-ci please test

@kubamracek kubamracek added the embedded Embedded Swift label Oct 6, 2023
@eeckstein
Copy link
Contributor

Do you know why this isn't a problem in regular swift, too?

@kubamracek
Copy link
Contributor Author

I think that's because in destroy we either do not (for POD) or always emit a runtime call (and the runtime implementation handles zero size correctly):

void TypeInfo::destroyArray(IRGenFunction &IGF, Address array,
                            llvm::Value *count, SILType T) const {
  if (isTriviallyDestroyable(ResilienceExpansion::Maximal))
    return;

 emitDestroyArrayCall(IGF, T, array, count);
}

And same for copy/init/take/assign -- it's either a memcpy/memmove or a runtime call:

void TypeInfo::assignArrayWithTake(IRGenFunction &IGF, Address dest,
                                              Address src, llvm::Value *count,
                                              SILType T) const {
  if (isTriviallyDestroyable(ResilienceExpansion::Maximal)) {
    llvm::Value *stride = getStride(IGF, T);
    llvm::Value *byteCount = IGF.Builder.CreateNUWMul(stride, count);
    IGF.Builder.CreateMemCpy(
        dest.getAddress(), llvm::MaybeAlign(dest.getAlignment().getValue()),
        src.getAddress(), llvm::MaybeAlign(src.getAlignment().getValue()),
        byteCount);
    return;
  }

  emitAssignArrayWithTakeCall(IGF, T, dest, src, count);
}

So we never GEP into the struct in regular Swift.

@kubamracek
Copy link
Contributor Author

@swift-ci please test macOS platform

Copy link
Contributor

@eeckstein eeckstein left a comment

Choose a reason for hiding this comment

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

lgtm!

@kubamracek kubamracek merged commit 356bfd5 into swiftlang:main Oct 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
embedded Embedded Swift
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants