Add or wire a calling convention in an LLVM 22 in-tree target or document IR-level ABI choices for out-of-tree frontends. Covers CallingConv IDs, TableGen CallingConv.td, CCState/CCValAssign hooks, ISel lowering, and tests.
64
76%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./tiles/tessl-llvm/skills/add-calling-convention/SKILL.mdUse this skill when the user needs a new or customized ABI for a target inside the LLVM tree, or when an out-of-tree frontend must choose among existing conventions and attributes.
Scope boundary: Truly new register/stack rules require target TableGen + lowering changes inside LLVM. Out-of-tree projects that only consume an installed LLVM should not expect to add a global CallingConv::ID without rebuilding LLVM.
| Goal | Where to work |
|---|---|
| Use standard C/fast call on existing target | IR only: setCallingConv, parameter attributes |
| Language needs special struct return / copies | sret, byval, inalloca, alignment attrs |
| New register/stack layout for a target | In-tree: CallingConv.h, *CallingConv.td, *ISelLowering.cpp |
| Document/embedder custom protocol | Often metadata + existing CC, or a dedicated in-tree target fork |
Read calling-conventions.md for terminology (CCState, CCValAssign, related IR features).
llvm::CallingConv::ID that matches the platform (usually C or Fast).llvm::Function and on CallInst/InvokeInst, call setCallingConv.sret, byval, nest, swiftself, etc.) per LangRef.verifyModule and compile with llc (or your driver) for the intended triple.F->setCallingConv(CallingConv::C);
F->addParamAttrs(0, ParamAttrBuilder...); // e.g. ByVal, StructRetIf this satisfies the ABI, stop—no TableGen work needed.
llvm/include/llvm/IR/CallingConv.h.LangRef.rst) with the spelling and number.switch (CC) exhaustiveness warnings in tree.*CallingConv.td)llvm/lib/Target/X86/X86CallingConv.td (pattern: Target/*/*CallingConv.td).def / multiclass instance for your convention that hooks CCAssignFn-style logic the same way sibling conventions do.cmake --build --target <Target>CommonTableGen or full target build)—never hand-edit *Gen*.inc.If you are unsure which multiclass to extend, clone the closest existing convention (e.g. a variant of Fast) and adjust register/stack rules incrementally.
In the target’s *ISelLowering.cpp (and related files):
LowerFormalArguments — handle the new CallingConv when assigning incoming values to SDValues / registers.LowerCall / LowerCallTo — match outgoing call setup (caller-side).CanLowerReturn / LowerReturn — return-value rules (registers, sret, multiple values).Use CCState / CCValAssign consistently with the TableGen side. Mismatches here cause silent ABI bugs.
Search the target for getCallingConv() / callconv dispatch to find existing patterns.
If Clang (or another frontend) must expose the convention:
setCallingConv on the IR function and calls..ll showing call/define with the new cc number or name (as printed by LLVM).Run llvm-lit on the new files.
[ ] CallingConv enum value unique and documented
[ ] TableGen + generated inc files regenerated
[ ] LowerFormalArguments / LowerCall / LowerReturn updated
[ ] Varargs path considered (if applicable)
[ ] Clang/frontend mapping (if user-facing)
[ ] lit tests for IR + machine level
[ ] Compared against platform ABI doc or psABIYou cannot complete Steps 2–4 from a standalone plugin; they live in the LLVM target sources. Out-of-tree frontends should:
CallingConv values and attributes, and/orcc without matching backend assignment logic.a251bde
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.