How to emit a function declaration with a custom calling convention

Hi all,

As part of my patch to add interrupt handlers to embedded swift on AVR, I want to add the llvm::CallingConv::AVR_INST or llvm::CallingConv::AVR_SIGNAL calling conventions to the generated function declarations when in embedded mode for AVR target triples, perhaps if a specific attribute is added to a function declaration in the Swift AST, such as @interruptHandler but we can get into the details like that when I raise a PR for upstreaming.

For now I'm just trying to get an idea what might fit in with the "general flow" of the swift compiler design for something like this.

I'm trying to work out the best place to set or override calling conventions for function declarations. It's rather a maze to see where things like this should go. Obvious places might be somewhere in GenDecl.cpp, GenFunc.cpp, IRGenFunction.cpp, IRGenSIL.cpp?

Or should it really be done at SIL level, in something like SILGen/SILGenFunction.cpp?

Or in some specialised pass, such as an LLVM pass??

Any clues would be useful, it's a bit hard to navigate the forest of things happening in function generation and I couldn't find obvious documentation to tell me how all these parts fit together.

Thanks for any help or advice.


I'll start putting in my research so far. I think a good place to do this sort of thing might be void IRGenSILFunction::emitSILFunction(), which in my source is at line 2238 of IRGenSIL.cpp. I think this is a method of the class IRGenSILFunction, which inherits from IRGenFunction, so that ties in those two files. It seems to be the place where, in simple terms, SIL functions are lowered to standard LLVM IR functions.

So it seems like a fairly good place for my work. So far, I've used an attribute in the Swift AST to determine when to add a flag to a SIL function to mark it as an interrupt handler. Now in emitSILFunction I am thinking of using that SIL function flag to override the calling convention for the LLVM IR function.

What I'm still unsure of is how this fits into the bigger picture. Will the LLVM IR function returned here be manipulated by later passes or other parts of IRGen, so that the calling convention would be overridden? Or is this the "bottom level"? So that it's pretty much generating the bitcode that will be output or the LLVM IR that will be passed to LLVM for optimisation and codegen?

Sorry if these are n00b questions?