Realtime threads with Swift

When I built with optimization, my function was inlined into main, so it was a bit harder to tell.

What do you think of the scanner idea?

You could try marking the function @inline(never) to prevent it from getting inlined into main, so you can still analyze its code in isolation. I think the idea of having an attribute that forces a region of code to have no realtime-unsafe runtime calls is a good one.

3 Likes

Looks good with @inline(never). Rather than adding an attribute to Swift itself (which presumably is a long process, no?), I was thinking of writing a little program that would look at the IR to see if a particular function is rt-safe. Does that seem doable?

That could probably be done, yeah. That would be at least a reasonable first pass for how I would implement an attribute in the compiler too—have it just look at the generated LLVM IR and raise an error if a realtime-unsafe implicit operation appears. (There would clearly need to be some quality-of-implementation work done after that to improve the UX of writing code against that constraint, though.)

1 Like

Cool. Any tips on how to get started? I've used the LLVM API from C++ before. Wondering how I would integrate a RT-verifier into an Xcode project.

One way to get started might be to implement your check as a new LLVM function pass, and add it to Swift IRGen's pass pipeline based on a compiler flag.

1 Like

You can always add a custom build phase that runs a shell script. Alternatively, if you implement this feature as an attribute, you can switch swift toolchain to your custom one.

1 Like

Would it need to be a ModulePass? It would need to ensure called functions also have the rt-safe attribute.

1 Like

I think a function pass would be more appropriate. You can't really in full generality scan every function you call, since some of them may be external, and transitively scanning them is also not scalable. Doing a local analysis of every function should be sufficient, since the primary hazard I think you want to scan for is implicit realtime-unsafe runtime behavior emitted by the compiler, and not so much explicit function calls in the source code—a human can reasonably audit those themself.

1 Like

It would be nice to do explicit function calls too, since in practice people aren't very good at auditing (or don't even know to do so). But point taken, a local analysis should be good enough for the original goal. :slight_smile:

1 Like

Here's my initial change: LLVMPasses: beginnings of SwiftRealtimeVerifier · audulus/swift@4f8f6b9 · GitHub

Does that look ok? (@Joe_Groff )

How should I add the attribute?

6 Likes

Ok I was able to add the attribute to the front-end:

but not sure how to get it all the way down to LLVM.

1 Like

Nice! One way you could plumb the attribute down to LLVM IR would be by adding a similar attribute to SILFunction, and then emitting an LLVM metadata tag during IRGen for SILFunctions marked by the SIL attribute.

2 Likes

Ok, I did that. Here's what I've got:

Also, I broke test/IDE/complete_decl_attribute.swift due to the extra attribute ... not sure how exactly to fix that.

What should I do next?

2 Likes

How can I report nice errors/warnings to the user from my LLVM pass (including source line numbers)? (@Joe_Groff )

1 Like

You should be able to grab a reference to the DiagnosticEngine from the Swift ASTContext and invoke the diagnose method on it.

2 Likes

Ok cool. How can I get the SourceLoc required by diagnose (from within my LLVM pass)?

1 Like

To do that, you'll most likely need to ensure debug info is enabled, the equivalent of -g or -gline-tables-only command line options. With debug info enabled, the instruction should have a !dbg metadata attached to it with source location info.

I’ll put in a contrary opinion: while emitting diagnostics from LLVM using debug info is possible, it’d be much easier from SIL, which has a stronger mapping from instructions back to source ranges. The design of SIL is a little different than LLVM IR, but probably still familiar enough to be accessible.

On the other hand, emitting diagnostics from LLVM IR using debug info is something that could be generally useful for multiple projects and cross-language codebases, so there’s benefit in your current approach as well. :-)

1 Like

Cool. Would doing this from SIL not require -g to have source ranges?