Possible bug in SIL

I'm seeing an error in SIL:

include/swift/SIL/SILConstants.h:356:1: error: static_assert failed "SymbolicValue  should stay small"
static_assert(sizeof(SymbolicValue) == 2 * sizeof(void *),
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

This is from a clean git clone done yesterday.

Nothing seems to have changed there recently, so

  • are you compiling for a 32-bit system? (i.e. do you want to run the compiler itself on a 32-bit host)
  • are you using MSVC to compile? (probably not; that looks like a Clang error)

Yes, I'm compiling on a 32-bit host for the same host.
No, it's clang.

Okay. I don't think we regularly test the compiler for 32-bit hosts, so you may find places you need to tweak the code to get that to work. In this case I think it'd be fine to change the static assert to say sizeof(SymbolicValue) <= 2 * sizeof(uint32_t) + sizeof(void *), …) (and we would accept a PR to that effect).

Actually that causes an error as well.

swift-source/swift/include/swift/SIL/SILConstants.h:356:1: error: static_assert failed "SymbolicValue should stay small"
static_assert(sizeof(SymbolicValue) == 2 * sizeof(uint32_t) + sizeof(void *),
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

That <= was deliberate, although I'm a little surprised that that's not the final size of the type. It seems to me like alignment would force it into that.

Oops I didn't see the <=. I've commented this line out and the build is continuing.

But this is an object, so on top of the ivars, which are at least 10 bytes, there is also an is_a pointer.

Another compilation error:

swift: ...swift-source/llvm/include/llvm/ADT/PointerIntPair.h:165: static intptr_t llvm::PointerIntPairInfo<swift::AvailableAttr *, 2, llvm::PointerLikeTypeTraits<swift::AvailableAttr *> >::updatePointer(intptr_t, PointerT) [PointerT = swift::AvailableAttr *, IntBits = 2, PtrTraits = llvm::PointerLikeTypeTraits<swift::AvailableAttr *>]: Assertion `(PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"' failed.

swiftc compiles with -fno-rtti, so only classes with virtual methods will have the extra pointer. (Unless you're somehow not getting an -fno-rtti build?)

In general I suspect you'll get a bunch of these static assertions, and maybe some runtime ones as well. For the alignment cases, feel free to use alignas where necessary to provide the alignment that's expected. For the static assertions, figure out what the equivalent rule would be in a 32-bit world. (For example, I think it's worth figuring out what the size of SymbolicValue actually is and why.)

Why does the pointer pair type have to be 16-byte aligned in the first place? That seems like a minuscule optimization, if that's what it's for.

Also, if Swift isn't really intended for 32-bit systems, can it really be said to be a cross platform language? 32-bit systems will be around for years.

The compiler implementation overaligns certain types (even in 64-bit mode) in order to store flags in the same word as a pointer. Is it an important optimization? Sometimes yes, sometimes we're probably being overzealous. It is a balance against wasting alignment padding, and we haven't measured that specifically, and particularly not for a 32-bit host.