When i'm compiling swift code to LLVM IR using my slightly patched version of swift 4.2 with the unusual target triple avr-atmel-linux-gnueabihf
, I'm getting a trap within the constructor for swift::irgen::IRGenModule.
Specifically, the last line, IsSwiftErrorInRegister = clang::CodeGen::swiftcall::isSwiftErrorLoweredInRegister( ClangCodeGen->CGM());
Clang source code shows this method is simply...
// Is swifterror lowered to a register by the target ABI.
bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) {
return getSwiftABIInfo(CGM).isSwiftErrorInRegister();
}
getSwiftABIInfo traps with...
Assertion failed: (isa<X>(Val) && "cast<Ty>() argument of incompatible type!"), function cast, file /Users/carlpeto/avr/swift/llvm/include/llvm/Support/Casting.h, line 248.
The code in question looks simple...
static const SwiftABIInfo &getSwiftABIInfo(CodeGenModule &CGM) {
return cast<SwiftABIInfo>(CGM.getTargetCodeGenInfo().getABIInfo());
}
So my best guess is that CGM.getTargetCodeGenInfo().getABIInfo()
returns ABI info that's not Swift ABI info, whatever that means.
Looking through clang source code I can see something that looks like an issue.
Tracing all of the above back to source, the ABI information that comes out depends on the target triple as you would expect.
The thing that looks suspicious is in CodeGenModule::getTargetCodeGenInfo()
where the TargetCodeGenInfo is being created with ABI information in it, most major targets (e.g. ARM, x86_64, SystemZ) are creating TargetCodeGenInfo using a specialised ABIInfo, for example for ARM it's ARMABIInfo. In all these cases where I know Swift works, the ABI Info class derives from a special subclass called SwiftABIInfo. For AVR, Mips and some other architectures, it does not. AVR uses DefaultABIInfo for example.
This then would cause the crash when compiling because swift tries to load clang context for emitting IR and correctly asserts because DefaultABIInfo cannot be cast to SwiftABIInfo.
Firstly, can anyone recommend a simple workaround (e.g. disabling parts of clang that aren't doing anything useful here). I am not interested in clang emission i don't think.
Secondly, if there's no way to limit this, can I just change AVRTargetCodeGenInfo to use ABI info for swift, e.g.
namespace {
class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
public:
AVRTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) { }
becomes...
namespace {
class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
public:
AVRTargetCodeGenInfo(CodeGenTypes &CGT)
: TargetCodeGenInfo(new SwiftABIInfo(CGT)) { }
Would this work? Do I need to add extra features to make it all work?
(I know the question looks like clang rather than swift but I think this infrastructure isn't really core clang and looks like it's just been added to clang to support swift.)