How to emit full LLVM IR from Mojo source

Hi, I’m looking for a way to emit the entire Mojo source file as LLVM IR.

Currently, compile_info() only exposes the LLVM IR for individual Mojo functions, but this is not sufficient for performing full optimization when linking with LLVM IR generated from other languages (e.g., C/C++, Rust, etc.).

For complete, whole-program optimization, having access to the full IR is essential.

As far as I understand, under the current implementation, even the main function cannot be compiled into LLVM IR as a whole. Because of this, it’s currently not possible to call external functions (already compiled into LLVM IR) from Mojo code in a unified LLVM-level optimization context.

Is there any method or workaround at this stage to generate a full .ll or .bc output from a Mojo module and enable integration with external LLVM-compiled code?

I’d appreciate any guidance or suggestions.
Thank you!

I don’t think anything like that is available, at least not publicly.

Hey everyone, I’m Rob Parolin, an Engineering Manager at Modular working on the Tools team. I wanted to share that we’ve added a new argument to the mojo build command: --emit-llvm. This argument does two things—it dumps the LLVM IR of the specified mojo file to stdout, and it writes the LLVM IR to an .ll file in the same directory with the same filename as the mojo file.

This feature is expected to be included in the next nightly release. Please reach out if you have any questions or comments. Enjoy!

> mojo build --help

        mojo-build — Builds an executable from a Mojo file.

SYNOPSIS
        mojo build [options] <path>

<snipped>

        --emit-llvm
            Whether to emit LLVM IR. Defaults to false.
10 Likes

Thank you so much, Rob!
This is exactly the feature I was hoping for—and it’s a fantastic improvement for LLVM-based workflows.
I really appreciate the amazing work your team is doing on this project. Looking forward to trying it out in the next nightly! :raising_hands:

1 Like

You are most welcome. Enjoy!

This feature is now live in the current nightly release.

1 Like

First of all, thank you for adding this great “emit raw LLVM IR” feature—being able to dive into the IR is extremely useful!

While testing it I ran into a small incompatibility:

$ llvm-as hello.ll -o hello.bc
llvm-as: hello.ll:322:52: error: expected ')' at end of argument list
declare void @llvm.lifetime.end.p0(i64 immarg, ptr captures(none)) #2

If I manually replace captures(none) with the upstream‑accepted attribute nocapture, assembly succeeds:

declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2

Could the backend emit nocapture (or otherwise output IR that vanilla LLVM tools accept) so the file round‑trips with the standard tool‑chain?

Hey @Yo-hey! Thanks for raising this. I’ll forward this issue to our backend compiler engineers so they can review it and post an update to this thread.

1 Like

Hi @Yo-hey. This is likely the result of a version discrepancy. Mojo relies on bleeding-edge features in LLVM, so we always build close to the head of the LLVM development tree, which can be months ahead of any released version of LLVM. captures(none) vs nocapture in particular appears to be caused by upstream LLVM PR #123181. If you use a newer LLVM version from Git (you may need to build it yourself to get one new enough), tools like llvm-as should be able to work out-of-the-box with the IR from Mojo. Hope this helps.

2 Likes

Is there a way to emit MLIR instead? If not, could you add a flag for this?

I’d also want that, but I’ve been told it’s not as simple as adding a flag.

Thanks! I’ll give it a try.

Is there any chance that Modular could provide their builds of LLVM in Modular’s conda repos?

This has been requested in the past. See [Feature Request] Emit MLIR in my own dialect · Issue #1008 · modular/max · GitHub.

As @clattner mentions in the ticket, this is supported internally, but it is not supported for external developers at this time. IMHO, I expect we will enable the requested workflow as we open source more, but unfortunately, I don’t have any timelines to share for emitting MLIR specifically.

I’m not aware of any plans but I’ll ping our internal responsible for this area and make them aware of your request. I’d also create a Github issue if you haven’t already. Thanks for suggestion!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.