Error lowering addrspacecast instruction... (I will need to patch my current backend)

Hi all,

Not sure what sub-category to put this into, although it’s probably AVR target related, it relates to a feature I’ll probably need to add as one of the (few) contributors to that target, so I think I’ll need wider help!

This IR fails to lower on the AVR platform…

i8* addrspacecast (i8 addrspace(1)* bitcast (void () addrspace(1)* @swift_deletedMethodError to i8 addrspace(1)*) to i8*)

With this error:
LLVM ERROR: Unsupported expression in static initializer: addrspacecast (i8 addrspace(1)* bitcast (void () addrspace(1)* @swift_deletedMethodError to i8 addrspace(1)*) to i8*)

Looking in the code in AsmPrinter.cpp in lowerConstant, it looks like the function isNoopAddrSpaceCast needs to return true…

  case Instruction::AddrSpaceCast: {
    const Constant *Op = CE->getOperand(0);
    unsigned DstAS = CE->getType()->getPointerAddressSpace();
    unsigned SrcAS = Op->getType()->getPointerAddressSpace();
    if (TM.isNoopAddrSpaceCast(SrcAS, DstAS))
      return lowerConstant(Op);

    // Fallthrough to error.
    LLVM_FALLTHROUGH;
  }

I’m trying to understand what this function is/does, to decide how to write the implementation for AVR (there currently isn’t an implementation… AVR only recently left experimental and is still fairly niche).

It seems like the base implementation in TargetMachine.h returns false, but on many platforms (AArch64, ARM, PPC, RISCV) its hard coded to return true. In some platforms (X86, MIPS) there’s a basic test that the address spaces are not “special types”.

It doesn’t help that I don’t really have much of a concept of what the addrspacecast instruction is used for in general and what the edge cases are. In my particular case, I’m adding it to a specialised fork of my swift compiler’s IRGen system, what I’m doing is storing an array of various types of i8* from various sources. Some are from pointers in address space 0, some are from pointers in (program) address space 1. So for me, addspacecast seems the perfect instruction. I suppose that given that addres spaces for pointers are largely theoretical, really the only thing addspacecast can ever do is a noop that effectively removes an error (you’re asserting that it’s OK to interpret a pointer value in one address space as a pointer value in another address space)? So the name of the function makes sense.

If I’m right, then it seems to me OK that I add an implementation on our backend to return true from isNoopAddrSpaceCast, because all you are really saying is “if a compiler developer/user of llvm libraries targeting the AVR platform wants to use the addrspacecast instruction and they’re sure it’s a good idea, then they are allowed to”. Is that right?

Thanks for any help and advice people!

If your pointers have the same representation and size, you have a no-op addrspacecast and can simply return true. The interpretation of address spaces is left to the backend.

OK, sounds good. I’ll bounce it off the other AVR guys to see if anyone objects but it seems like this is a safe change.

Cheers!