"unsupported register width" compiling stdlib

This function from stdlib won't compile, fails SIL generation for my target:

@inline(__always)
@inlinable
public func _bridgeObject(toTagged x: Builtin.BridgeObject) -> UInt {
  // _sanityCheck(_isTaggedObject(x))
  let bits = _bitPattern(x)
  // _sanityCheck(bits & _objCTaggedPointerBits != 0)
  return bits
}

...here's the backtrace...

unsupported register width
UNREACHABLE executed at /Users/carlpeto/avr/swift/swift/lib/IRGen/IRGenSIL.cpp:673!
Process 5864 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff7301eb66 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff7301eb66 <+10>: jae    0x7fff7301eb70            ; <+20>
    0x7fff7301eb68 <+12>: movq   %rax, %rdi
    0x7fff7301eb6b <+15>: jmp    0x7fff73015ae9            ; cerror_nocancel
    0x7fff7301eb70 <+20>: retq   
Target 0: (swift) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff7301eb66 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff731e9080 libsystem_pthread.dylib`pthread_kill + 333
    frame #2: 0x00007fff72f7a1ae libsystem_c.dylib`abort + 127
    frame #3: 0x0000000108c792b0 swift`llvm::llvm_unreachable_internal(msg="unsupported register width", file="/Users/carlpeto/avr/swift/swift/lib/IRGen/IRGenSIL.cpp", line=673) at ErrorHandling.cpp:222
    frame #4: 0x0000000100502102 swift`(anonymous namespace)::IRGenSILFunction::emitLifetimeExtendingUse(this=0x00007ffeefbf5d20, Var=0x0000000116003a10) at IRGenSIL.cpp:673
    frame #5: 0x000000010051c108 swift`(anonymous namespace)::IRGenSILFunction::emitShadowCopyIfNeeded(this=0x00007ffeefbf5d20, Storage=0x0000000116003a10, Scope=0x0000000115040998, Name=(Data = "bits", Length = 4), ArgNo=0, IsAnonymous=false, Align=(Value = 0)) at IRGenSIL.cpp:806
    frame #6: 0x0000000100527f94 swift`(anonymous namespace)::IRGenSILFunction::emitShadowCopyIfNeeded(this=0x00007ffeefbf5d20, SILVal=0x00007ffeefbf4ee8, Scope=0x0000000115040998, Name=(Data = "bits", Length = 4), ArgNo=0, IsAnonymous=false, copy=0x00007ffeefbf4fe8) at IRGenSIL.cpp:845
    frame #7: 0x0000000100515592 swift`(anonymous namespace)::IRGenSILFunction::visitDebugValueInst(this=0x00007ffeefbf5d20, i=0x0000000114c06720) at IRGenSIL.cpp:3678
    frame #8: 0x00000001005014a4 swift`swift::SILInstructionVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(this=0x00007ffeefbf5d20, inst=0x0000000114c06720) at SILNodes.def:611
    frame #9: 0x00000001004f671e swift`(anonymous namespace)::IRGenSILFunction::visitSILBasicBlock(this=0x00007ffeefbf5d20, BB=0x00000001150408b8) at IRGenSIL.cpp:1830
    frame #10: 0x00000001004f0189 swift`(anonymous namespace)::IRGenSILFunction::emitSILFunction(this=0x00007ffeefbf5d20) at IRGenSIL.cpp:1696
    frame #11: 0x00000001004ef8e3 swift`swift::irgen::IRGenModule::emitSILFunction(this=0x00007ffeefbf6e90, f=0x0000000115040788) at IRGenSIL.cpp:1612
    frame #12: 0x00000001002fc04a swift`swift::irgen::IRGenerator::emitGlobalTopLevel(this=0x00007ffeefbf8598, emitForParallelEmission=false) at GenDecl.cpp:1071
    frame #13: 0x00000001004841bd swift`performIRGeneration(Opts=0x00007ffeefbfc190, M=0x00000001168084a0, SILMod=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbf89c0, ModuleName=(Data = "uSwift.ll", Length = 9), PSPs=0x00007ffeefbfa590, LLVMContext=0x0000000114f2bb90, SF=0x0000000116808558, outModuleHash=0x00007ffeefbf9388, StartElem=0) at IRGen.cpp:795
    frame #14: 0x0000000100484f8b swift`swift::performIRGeneration(Opts=0x00007ffeefbfc190, SF=0x0000000116808558, SILMod=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbf8c88, ModuleName=(Data = "uSwift.ll", Length = 9), PSPs=0x00007ffeefbfa590, LLVMContext=0x0000000114f2bb90, StartElem=0, outModuleHash=0x00007ffeefbf9388) at IRGen.cpp:1121
    frame #15: 0x000000010011f48c swift`generateIR(IRGenOpts=0x00007ffeefbfc190, SM=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbf9380, PSPs=0x00007ffeefbfa590, OutputFilename=(Data = "uSwift.ll", Length = 9), MSF=swift::ModuleOrSourceFile @ 0x00007ffeefbf8cb0, IRModule=0x00007ffeefbf9390, HashGlobal=0x00007ffeefbf9388, parallelOutputFilenames=(Data = "uSwift.ll", Length = 1)) at FrontendTool.cpp:1131
    frame #16: 0x00000001000f8b6d swift`performCompileStepsPostSILGen(Instance=0x0000000116806e00, Invocation=0x00007ffeefbfbb08, SM=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbfa570, astGuaranteedToCorrespondToSIL=true, MSF=swift::ModuleOrSourceFile @ 0x00007ffeefbf9508, PSPs=0x00007ffeefbfa590, moduleIsPublic=true, ReturnValue=0x00007ffeefbfaf84, observer=0x0000000000000000, Stats=0x0000000000000000) at FrontendTool.cpp:1384
    frame #17: 0x00000001000ea433 swift`performCompile(Instance=0x0000000116806e00, Invocation=0x00007ffeefbfbb08, Args=ArrayRef<const char *> @ 0x00007ffeefbfa790, ReturnValue=0x00007ffeefbfaf84, observer=0x0000000000000000, Stats=0x0000000000000000) at FrontendTool.cpp:1002
    frame #18: 0x00000001000e7512 swift`swift::performFrontend(Args=ArrayRef<const char *> @ 0x00007ffeefbfb198, Argv0="/Users/carlpeto/avr/swift/build/Ninja-DebugAssert+stdlib-ReleaseAssert/swift-macosx-x86_64/bin/swift", MainAddr=0x000000010000b140, observer=0x0000000000000000) at FrontendTool.cpp:1842
    frame #19: 0x000000010000d865 swift`run_driver(ExecName=(Data = "swift", Length = 5), argv=const llvm::ArrayRef<const char *> @ 0x00007ffeefbfc8f8) at driver.cpp:122
    frame #20: 0x000000010000c11d swift`main(argc_=19, argv_=0x00007ffeefbff798) at driver.cpp:246
    frame #21: 0x00007fff72ece015 libdyld.dylib`start + 1
    frame #22: 0x00007fff72ece015 libdyld.dylib`start + 1
(lldb) 

This is the code that breaks...

  /// Try to emit an inline assembly gadget which extends the lifetime of
  /// \p Var. Returns whether or not this was successful.
  bool emitLifetimeExtendingUse(llvm::Value *Var) {
    llvm::Type *ArgTys;
    auto *Ty = Var->getType();
    // Vectors, Pointers and Floats are expected to fit into a register.
    if (Ty->isPointerTy() || Ty->isFloatingPointTy() || Ty->isVectorTy())
      ArgTys = {Ty};
    else {
      // If this is not a scalar or vector type, we can't handle it.
      if (isa<llvm::CompositeType>(Ty))
        return false;
      // The storage is guaranteed to be no larger than the register width.
      // Extend the storage so it would fit into a register.
      llvm::Type *IntTy;
      switch (IGM.getClangASTContext().getTargetInfo().getRegisterWidth()) {
      case 64:
        IntTy = IGM.Int64Ty;
        break;
      case 32:
        IntTy = IGM.Int32Ty;
        break;
      default:
        llvm_unreachable("unsupported register width");
      }
      ArgTys = {IntTy};
      Var = Builder.CreateZExtOrBitCast(Var, IntTy);
    }
    // Emit an empty inline assembler expression depending on the register.
    auto *AsmFnTy = llvm::FunctionType::get(IGM.VoidTy, ArgTys, false);
    auto *InlineAsm = llvm::InlineAsm::get(AsmFnTy, "", "r", true);
    Builder.CreateAsmCall(InlineAsm, Var);
    return true;
  }

Does this code need patching for more unusual architectures? Or am I missing something?

Just by observation of the shown code I would imagine that you need to add:

      case 16:
        IntTy = IGM.Int16Ty;
        break;

to the switch, as it seems to be finding the LLVM type corresponding to …getRegisterWidth(), and no system has previously had a register width of 16.

Just a guess, I don't know c++.

1 Like