[RFC] Add vibecoded EZH target

Hi all,

I’ve put up a PR to add support for the EZH (aka SmartDMA) core inside of NXP MCUs. In some MCUs this core isn’t even listed in the datasheet as being present. This core is similar to a Cortex M0 in capabilities and is a bit more performant. It uses 32 bit instructions so it’s less efficient on code space.

On a project I’ve been working on we’ve required more and more functionality out of this core and writing assembly without a real assembler has been really hard. Currently all code written for EZH is written using preprocessor macros used to create an array of machine code which is fed to EZH to processor. I went down the path of making a real assembler but then realized it was best to do all of this right in LLVM. So over the last 6 weeks I’ve vibecoded an EZH target in LLVM. The PR to add it to llvm-project as an experimental target is here: Add NXP EZH (SmartDMA) architecture by rpasek · Pull Request #201498 · llvm/llvm-project · GitHub. This adds full support for EZH so assembling, compiling, linking and debugging.

I think this brings up 2 important topics.

  1. Do we want to add the EZH target to llvm-project as an experimental target or would it be better living on in it’s own fork?
  2. Do we want to have vibe coded targets in llvm-project?

Thanks!

Richard

1 Like

I do not think we want vibe coded targets in tree.

While the maintenance burden on the rest of the community isn’t gigantic for an experimental target given changes are allowed to break them and maintainers are responsible for fixes, it generally is not zero. The review burden to get something like this actually upstream will also be quite high on the community, and the amount of review time required to fully land this might actually be higher than the time spent creating this, which probably isn’t a fair tradeoff to the LLVM community, especially without (from what I can see) a strong user community around this target.

If this is needed for something, I think it makes sense to just leave out of tree for now.

12 Likes

To be clear, I didn’t have to be forthcoming with stating this was vibecoded. However, I do want the community to know about this.

I do not enjoy working with AI agents and it’s not my preferred way of development. I found that it got lost a lot and would lie about things forcing me to truly learn about the problem to make progress. It also and it spent a lot of time blaming the hardware when there was no issue, often attempting to make work arounds for things that were not needed. I also didn’t like that it decouples me from the learning process. I want to know exactly how something works and this gets in the way of that.

As much as I don’t like vibecoding, I recognize it is the direction that code is going to be written in the future. I expect that the next target that is introduced will be vibecoded whether the author states it or not. It saves such a dramatic amount of time that I’m not clear why anyone would attempt to write a target by hand anymore.

I had a major role in the development of this code and I’ve committed to maintain it. I think it makes sense for it to live in tree as an experimental target so there isn’t a constant burden of needing to rebase. I was careful throughout this process to make sure that only the changes needed to enable EZH were included. No changes were made that could change the behavior of other targets.

I would expect that experimental targets have substantially less community behind them from fully supported targets. In my opinion, I’m using experimental targets in exactly the intended way.

According to LLVM’s AI policy, you did: LLVM AI Tool Use Policy — LLVM 23.0.0git documentation

Contributors are expected to be transparent and label contributions that contain substantial amounts of tool-generated content

7 Likes

Oh! Thank you for the clarification!

I suspect part of the problem here is that “vibecoded” means different things to different people, and it may carry a more negative connotation for many people than you intended here. For example, to me vibecoded means that you just let the agent do its thing fully, you never even looked at the generated code, you only care about the outcomes and not the code itself, etc. It sounds like you had a lot more involvement than that (and the six-week timeframe also suggests that), so you may want to phrase it as “AI-assisted” (and maybe detail exactly how involved you were and how much oversight you exercised) to avoid potential knee-jerk reactions (like the one I had myself when I read “vibecoded”).

4 Likes

Thanks for putting this up and for being upfront. I’d like to argue, respectfully, for the fork rather than in-tree.

On the community requirement. This looks like a single-maintainer target for a core that, by your own description, isn’t even listed in some datasheets. It does look like it has “too few users”.

On the precedent (your question 2). If we accept this, we should expect more single-author, low-community, AI-generated targets, and the policy’s community/maintenance bar is exactly what protects the tree from that. I’d rather we hold that bar than relax it case-by-case.

On reviewability of generated code. This is a 117-file change spanning clang, lld, lldb, libc, compiler-rt and the backend itself. For AI-generated code at this scale, the open question is whether anyone understands it well enough to maintain and debug it independently.
In-tree code becomes everyone’s maintenance surface. A fork keeps the cost with the people who benefit until that understanding and a real user base exists.

A fork is the better fit for your actual goal. You built this to serve a specific project; an out-of-tree fork lets you iterate fast without gating every change on upstream review, and don’t impose a cost on 99.999% users that don’t build code with LLVM EZH.

The usual objection to forks is rebase pain. But that’s largely gone now: resolving the mechanical churn (renamed APIs, signature changes) against upstream is exactly what an agent does well — pull, resolve, build, run the target’s tests, iterate. The same workflow that produced EZH can maintain it.

11 Likes

Just my 2 pence: the fact that the target is vibe-coded/AI generated in some manner should irrelevant to whether the target should be present in tree, as long as it doesn’t fall foul of the LLVM AI Policy. We have a policy and that should form the basis for any related discussions. Clearly the “extractive” element of the policy is applicable here, as is the “human-in-the-loop” element, so we should be evaluating against those.

For the “extractive” element, to me that means in this case “does it meet the agreed criteria for in-tree targets”, in addition to the overall quality of the code. If it meets that criteria, why does it matter that this code is written with AI assistance? Equally, if it doesn’t meet that criteria, it should be rejected based on that criteria and not because it was AI-generated. Similarly, if the code meets our usual quality standards, it shouldn’t matter that this quality bar was met via AI assistance (and on the flip side, it should be rejected as extractive if it doesn’t). Given the boiler-plate nature of much of the target setup, I wouldn’t be at all surprised if the code generated by the AI ends up being very similar to what a human would produce.

That all being said, I completely agree with @MaskRay’s comments about AI also being good at the mostly-mechanical actions of maintaining a new target in a fork.

3 Likes

Smeenai,
I agree vibecoded has a negative connotation but to be clear, I did not write this code so I find the term is accurate. In general I instructed it to copy large portions of code from other targets. I initially instructed it to copy the Lanai target because it’s the simplest target. I immediately ran into problems because of issues with limited registers in EZH and issues with having insufficient PC relative load range for constants.

Most of my time as a developer has been on ARM cores and I recognized that EZH is very similar to Thumb 1. They both have a similar PC relative load range, no hardware divide, no float, and the same number of readily accessible registers (R0-R7 (most thumb 1 instructions cannot access the higher registers)). Because of this, I asked it to copy the ARM constant island, soft float, frame pointer handing, base pointer handling and for the most part the ABI.

A lot of this just worked (verified by homegrown and GCC torture tests) however major issues were encountered around a few key areas:

  • 16 bit support. EZH can only perform 8 and 32 bit loads and stores. I instructed it to insert 2, 8 bit loads/stores to emulate 16 bit support.
  • Signed comparison support. EZH doesn’t have an overflow flag but does have a carry flag. I had it inject a bit toggle instruction to toggle the 31st bit (simulating an XOR) on both inputs before comparison to allow for an unsigned comparison using the carry flag.
  • Signed 64 bit support. Figuring out how to get lowering to work correctly with the signed comparison issue was tricky.
  • Interrupt support. EZH doesn’t support interrupts so I had it make another pass to inject conditional gotos using bitslice condition flag to jump to an “interrupt” handler in front of every goto instruction.
  • The constant island. The ARM constant island worked fine however it continued to mess it up with the changes above and I had to carefully guide it through. It would often believe it hit some silicon pipeline bug when loads were near gotos. It couldn’t be self guided here because EZH has the concept of a “scheduled branch” in the EZH application note which really means if desired, EZH can execute 2 instructions after a goto instruction and then actually jump to the new location. AI latched onto this concept and was confident that EZH would always do this. Since AI can develop in a build and test loop, if left alone it would just generate insane code.

This is where I spent most of my time working directly on the code with AI. I also spent a lot of time telling to clean up, de spaghetti code or remove changes it made to non EZH code.

While I have read every line that it has output, I admit, do not understand how every line works. I have contemplated on whether this is an issue or not and I keep coming back to this is not very different from code I wrote a long time ago and forgot how it works. I am capable of learning or relearning code to fix it especially since I generally understand how it works. I’m also left with the thought, should I know how it works if it works fine? I’m honestly not sure and I think it depends on the situation. If it has security, human safety implications or may cause the system to crash, it is not fine, otherwise it probably is.

jh7370, you are right, there are many trivial and pretty much boiler plate changes. It’s worth pointing out that 40 of the files being touched are nothing but adding EZH to a list of targets.

Anyway, the part that I’m still most confused about is what is the point of experimental targets? I see experimental as meaning it’s not ready for main for whatever reason. It seems that LLVM views it as exclusively a staging area ( LLVM Developer Policy — LLVM 23.0.0git documentation “new targets are always added as experimental until they can be proven stable, and later moved to non-experimental”) before entry into main and I don’t think this makes a lot of sense. In my opinion the real gate from transitioning from experimental to main should be how many users there are and nothing else.

For example if the x86 target was incredibly low quality, AI generated and poorly tested, it doesn’t matter, it still must be in main because everyone expects it to be there because everyone uses it. This helps lean into your point MaskRay “don’t impose a cost on 99.999% users that don’t build code with LLVM” [insert seldom used target name here]. I suspect this is a good rule: if there are more than 100 users, it likely should be in main. If less, it should fall back out to experimental.

With that reasoning Lanai should not be a main line target. Looking at git history, it doesn’t appear that Lanai has had any real changes in a very long time. Maybe others should not be as well.

I think experimental should mean experimental. Experimental targets should not go through as rigorous of a review process (it’s an experiment) nor should they be guaranteed to build or work ( LLVM Developer Policy — LLVM 23.0.0git documentation “Test failures, bugs, and build breakages that only appear when the experimental target is enabled, caused by changes unrelated to the target, are the responsibility of the community behind the target to fix”). In the event that a target should be upgraded to a main target, it should then go through the main review process.

I think experimental targets get too much effort/attention with the current LLVM ideology. In my opinion the LLVM team would benefit by having a real experimental target section. This allows people to soft bring their target into LLVM, have the exposure of being in LLVM, not suffer from having to rebase their forks constantly and spreads the burden of these experimental targets to people who actually use it (I’m suggesting people are often scared off by someone’s non official fork, leading to these forks getting limited to no attention). LLVM benefits because it becomes the place where support for all CPU architectures (new, old, heavily used, disused) is found, driving more interest in the project. If someone needs an experimental target and it’s broken, it’s their problem to fix it. This is likely substantially easier than bringing up a whole target from scratch. Maybe this should be a special folder in llvm-project so it doesn’t pollute the non experimental targets? I hear your point MaskRay about having AI rebase and you are totally right it but this doesn’t help with exposure.

Wrapping all of this up, I think EZH is roughly equivalent to Lanai. It’s an architecture which is both obscure and posses a very limited community and there are millions of them already deployed. I’m still a bit confused that Lanai is main and EZH is out of tree but I’m ok with it.

I agree with the general consensus here. With the way LLVM is today it seems like it would be best for EZH to live as an out of tree fork. I think this is primarily based around an unclear need for the EZH target at this point and also very limited community. I’m not sure if we found consensus about whether being AI assisted is an issue or not.

Thanks for all of your thoughts here,

Richard

1 Like

Removal of Lanai has been discussed previously ( Delete llvm/lib/Target/Lanai ). If someone proposed adding it today, I’m not sure it would end up being accepted. But it’s already in-tree, and has not been a concrete maintenance concern.

Note that experimental backends are not built by default and maintainers are not expected to keep them working. A maintainer of an experimental target will still end up doing a lot of this rebase work themselves until they are ready to turn it on by default. You get some maintenance benefits (due to the community now sharing that cost) around components that are enabled by default/code that does get built, but that’s not the majority of what a new target is.

I think the biggest concern here is review bandwidth. Upstreaming this target means that people from the community will need to review all the changes. That is a very high amount of effort. If you can find someone with CodeGen expertise in the upstream community who is willing to review all the backend changes, then I’m probably fine letting this go in-tree as an experimental target, but given the lack of user community and the extremely high review load upstream reviewers already face, I’m not sure you’re going to be able to find anyone ( LLVM: The bad parts ). I don’t think the community is going to accept a less rigorous review process. That would require re-review if someone ever wants to enable the target by default which would probably be a significantly bigger time investment rather than just “doing it right” in the first place.

You’re welcome to propose changes to the policy (in a separate RFC), but I would imagine that eliminating user community as a consideration for whether or not we should accept new experimental targets is going to get a lot of push back.

1 Like

No.

Yes, you did. It’s in out policy, as stated above. The tone in your response does not make things better.

You are not: LLVM Developer Policy — LLVM 23.0.0git documentation

It doesn’t seem you’re spending the time to actually read the LLVM code and policies, and you’re making a lot of wrong assumptions.

You are only thinking on your own burden, not the rest of the community.

Please be considerate to the thousands of people that work on LLVM every day, the thousands of projects that depend on LLVM to be stable and fast, the thousands of groups in industry, academia and hobbyists that want to make LLVM a reliable compiler infrastructure.

No one does. This is a non-starter.

Vibe coding is not AI assistance, is full AI generation. No one has the ability to review a change across so many projects in LLVM and expect not to be bugs introduced, bad code, wrong assumptions, etc.

That’s the key. You must be able to explain your code. You must not imbue the onus of proof onto reviewers. You must not waste reviewer time on things you do not understand and did not verify (torture tests aren’t enough).

Please, keep your work in a fork until the day when you can explain all of your changes, can form a plan on how to slowly upstream it to LLVM, convince a large-enough community to support you, and make sure that you pass every requirement for new targets in our policy before you try again.

Thank you.

8 Likes

boomanaiden154-1,

Thanks for the additional information. I appreciate the details on the difficulties the community is facing.

I suppose I was misled by the presence of Lanai in main that the LLVM community is open to low community targets. I now understand this is not the case and Lanai has been considered for removal in the past and it remains because it isn’t causing problems.

The documentation is vague on what a community actually is “There must be an active community behind the target.”. I’m still not sure I understand what size of community is expected but I do know that EZH doesn’t have enough. While I could push on the path to get it reviewed, spending precious reviewer time on such a low community target just isn’t worth it.

Responding to the point about the community accepting a less rigorous review process, as the culture is defined today, I totally agree. It should go through the full review process. There isn’t a place for lower quality, lower community contributions in LLVM today. There is also no clearly defined system to review experimental targets before they are promoted to a main target. The experimental section doesn’t mean what I initially thought.

I will spend some time thinking about what a lower quality, lower community target section would look like and how it could live in a project like LLVM. With the problems you shared and with the current mindset, I’m not confident there is a solution. I maintain that there is value in something like this, however I’m also not confident that it’s net positive for the community over simply having forks. Forks decrease exposure but it keeps the experimental (lower quality) code out and from what I can tell, LLVM wants exclusively the highest quality code (I have no proof on this this is just based on the sentiment I find when reading the discourse). I spent some time looking through https://blog.llvm.org/ and https://llvm.org/devmtg/2026-04/ to see what the community has on its mind and it doesn’t seem like making it easier to add more targets is a priority. If I come up with something that is worth sharing I will share it in another RFC.

Thanks,

Richard

1 Like

rengolin,

Thank you for your response on this.

Would it be fair to say that we don’t care if it’s vibecoded or not as long as the developer (?)/author (?)/commiter does “not imbue the onus of proof onto reviewers”? In the circumstance with EZH I am fully willing to do that. However, I will not be proceeding forward with landing EZH as an experimental target because it doesn’t have enough community.

You state:

It doesn’t seem you’re spending the time to actually read the LLVM code and policies, and you’re making a lot of wrong assumptions.

This is an unqualified statement. I am reading the documentation and I am quoting and referring to the documentation throughout my posts and in my PR comments. There is a lot of documentation, some of which I do not know is relevant to me yet. If you think there is something that I am missing, please share it with me and I will read it.

You state:

You are only thinking on your own burden, not the rest of the community.

When I spend a significant amount of time on something and it solves the problem that I am having and then my objective becomes to share it with the community to help out people who work on projects like GitHub - wavenumber-eng/bunny_build · GitHub, put my name on the maintainers list to indefinitely maintain this target and participate in these difficult discussions would you think think that I am only thinking of my own burden? We are having this discussion to determine what the implications will be on the community and I want to take all of this into consideration.

You state:

The tone in your response does not make things better.

I suspect you are speaking about respect. Please consider that all of the information that I shared is not to my benefit in any way. In fact, it makes landing EZH harder. There will be others that don’t tell the truth and cover up what they did but I want to help advance the community of “thousands of people that work on LLVM every day” with dealing with the challenged of vibecoded or AI generated code. Out of respect and betterment of the community I have been brutally honest and transparent.

This is a 117 file change. I recognize it is not reviewable in the state that it’s in. As discussed on the PR, we did not begin on the process of breaking the work down into committable pieces because there were questions on whether the community wanted it or not. For most of this project, I wasn’t sure it would ever work. It didn’t even make sense to discuss it with the community before I started work. Now that it does, I wanted to put whatever I had in front of the community to determine what the best path forward is.

Thanks,

Richard

2 Likes

There are ongoing discussions in the community, and in the broader open-source ecosystem, on how to handle the whole LLM-assisted/generated code situation. We are not going to figure out a perfect policy here, but this is a pretty clear data point on what the community wants, or rather does not want. As for the amount of policy, I hear there are these new tools called LLMs that can summarize long policy documents quite efficiently, though extra effort is then needed to fact-check the result.

While it is laudable that you want to share your solution to a problem with a community, the first thing to do is to find out whether that particular community has that particular problem in the first place, otherwise it is just noise and wasted effort on both sides. It doesn’t look like the LLVM community has a “not enough experimental targets” problem or a particular need for the EZH target.

1 Like

IMHO, before even getting into the AI policy the question needs to be answered whether it meets the criteria for upstreaming an experimental target and it doesn’t look like it does.

I also don’t see any benefit for this target living in upstream (plenty much less niche targets aren’t). Some select changes that prove to be a pain point for rebasing can always be submitted as standalone patches if it makes sense.

ftynse,

I mostly agree. While it’s difficult to ascertain what the whole community wants with the small sample size of responses we received here, it’s likely a good enough signal make decisions with. This is a reversible decision so the outcome isn’t that important.

There are people outside of the community that will continue to stay outside of it. We know they exist because we have evidence of them. The current community is likely very small, but this is just a guess. I know through conversations with NXP that they have have a team dedicated to this core. There are open source tools to work with this core as well. This likely puts it in line with Lanai, CSKY and ARK. What size community LLVM cares to service is still unknown to me.

Now llvm-ezh exists, we can see if the community grows to a level that LLVM is interested in servicing.

Thanks,

Richard

danilaml,

You mentioned “plenty much less niche targets aren’t”. Can you share the niche targets that you know about? These are the LLVM target forks that I’ve found so far:

GitHub - llvm-mos/llvm-mos: Port of LLVM to the MOS 6502 and related processors · GitHub

GitHub - graphcore/llvm-project-fork: Fork of LLVM Project containing a Colossus IPU backend implementation · GitHub

GitHub - Xilinx/llvm-aie: Fork of LLVM to support AMD AIEngine processors · GitHub

GitHub - qualcomm/cpullvm-toolchain · GitHub

GitHub - llvm-z80/llvm-z80: An LLVM backend implementation targeting the Zilog Z80 processor · GitHub

I’m trying to understand if there is value in something like an experimental branch or some other mechanism as discussed earlier with boomanaiden154-1. If so I’d like to put together an RFC discussing what this would look like, what benefits it has for the community, the burden it places on the community and the operational model.

Most of the ones above have tangible reasons for not being a part of LLVM (llvm-mos modifies substantial parts including IR, Qualcomm wants to retain control, Z80 is unstable, aie might just be too different to be part of mainline).

Thanks,

Richard

There is no need for such RFC.

The process for introducing new targets is clear and has been followed (and updated) for over a decade without problems. It’s not perfect, but even this thread has demonstrated that the target policy stands on its own, with clear recommendations, some of which your target didn’t meet. The AI policy restrictions that your target didn’t meet are in addition to the existing new target restrictions above.

So, let’s just leave other targets make their own decisions WRT upstreaming their code.

rengolin,
This is no longer about the EZH target. Clearly I’m not alone in my thinking. Here is a conversation that you are a part of:

I am unable to make decisions for other forked targets related to “their own decisions WRT upstreaming their code” nor is the LLVM project.

I do think that I could engineer a solution that could decrease reviewer burden while simultaneously providing an experimental playground for targets that want to be close to LLVM but not in mainline. Once again, I’m not confident that there is an actual need for this.

I find it especially interesting that you don’t even want to hear my thoughts on this. Do you think your responses have followed the LLVM Community Code of Conduct — LLVM 23.0.0git documentation “Be friendly and patient.”?

Thanks,

Richard

Aside: this repo does not have any additional LLVM backends beyond those upstream. It has additional build scripts not found upstream, that is all.