Skill: Compiler Toolchain Development
Invocation
When this skill is loaded and a user presents a compiler or ISA task, do not
execute stages directly. Immediately spawn the
digital-chip-design-agents:compiler-orchestrator agent and pass the full user
request and any available context to it. The orchestrator enforces the stage
sequence, loop-back rules, and sign-off criteria defined below.
Use the domain rules in this file only when the orchestrator reads this skill
mid-flow for stage-specific guidance, or when the user asks a targeted reference
question rather than requesting a full flow execution.
Pre-run Context
Before executing or advising on any stage, read the following files if they exist:
memory/compiler/knowledge.md — known failure patterns, successful tool flags, PDK/tool quirks.
Incorporate its guidance into every stage decision. If absent, proceed without it.
memory/compiler/run_state.md — current run identity (run_id, design_name, tool,
last_stage). Use this to resume correctly after interruption. If absent, a new run
is starting; the orchestrator will create this file before the first stage.
This pre-run read applies whether this skill is loaded by a user or called by the
orchestrator mid-flow. It ensures the fix database is consulted before any diagnosis step.
Purpose
Build and validate a complete compiler toolchain (LLVM or GCC based) for a
custom processor ISA. Bridges hardware and software — without a working
toolchain no software can run on the designed chip.
Supported EDA Tools
Open-Source
- LLVM/Clang (
clang, llc, llvm-mc, llvm-objdump) — primary toolchain for new ISA backends
- GCC and GNU Binutils (
gcc, as, ld, objdump) — alternative backend; well-tested for RISC-V extensions
- QEMU (
qemu-system-*) — instruction-accurate ISA emulation for toolchain validation without hardware
Proprietary
- Green Hills MULTI — safety-critical compiler and debugger IDE
- IAR Embedded Workbench — certified compiler for ARM/RISC-V
- Arm Compiler 6 (
armcc) — LLVM-based compiler for Arm targets
Stage: isa_analysis
ISA Feature → Toolchain Component Mapping
| ISA Feature |
Toolchain Component |
| Instruction encoding |
Assembler, disassembler |
| Register file |
Register allocator, ABI |
| Calling convention |
ABI, function call lowering |
| Branch/jump |
Control flow, delay slot handling |
| Load/store addressing |
Memory access patterns |
| SIMD/vector |
Auto-vectorisation, intrinsics |
| Atomics |
Memory model, concurrency |
| Multiply/divide |
Integer arithmetic lowering |
| FPU presence |
FP ABI (hard-float vs soft-float) |
| Custom instructions |
Intrinsics, builtin functions |
ABI Requirements (define before any backend code)
- Argument passing: which registers, stack spill rules
- Return value registers
- Callee-saved vs caller-saved register classification
- Stack alignment (8 or 16 byte)
- Data type sizes and alignments
- Struct layout (padding, packing rules)
- Thread-local storage model (if RTOS target)
Output Required
- ISA-to-toolchain mapping table
- ABI specification document
- List of LLVM/GCC backend files to create/modify
- Target triple:
<arch>-<vendor>-<os>
Stage: backend_dev
LLVM Backend — Implement in This Order
RegisterInfo.td: register classes, aliases, reserved registers
InstrInfo.td: all instruction definitions with encoding
CallingConv.td: argument and return value register rules
SchedModel.td: latency and throughput per instruction class
TargetMachine.cpp: entry point, subtarget selection
ISelDAGToDAG.cpp: selection DAG → machine instruction lowering
FrameLowering.cpp: stack frame, prologue/epilogue
AsmPrinter.cpp: assembly text emission
Testing per Component
- TableGen:
llvm-tblgen compiles .td without errors
- Codegen:
llc compiles C snippets; verify .s output manually
- MC layer:
llvm-mc --show-encoding verifies instruction encoding
QoR Metrics to Evaluate
- All ISA instruction classes: lowerable from LLVM IR
- Calling convention: function call round-trip test passes
- No illegal instructions in generated assembly
- Basic integer test program: compiles, links, executes on ISS
Common Issues & Fixes
| Issue |
Fix |
| TableGen pattern not matching |
Add explicit Pat<> with matching operand types |
| Stack corrupt |
Verify prologue saves all callee-saved regs |
| Calling convention mismatch |
Cross-check CCAssignToReg vs ABI spec |
Output Required
- Complete LLVM backend source tree
- Regression test files (llc lit tests)
- Build instructions (CMake)
Stage: assembler_dev
Domain Rules
- LLVM MC layer provides assembler via .td instruction definitions
- For every instruction: encode-decode round-trip test
- Define all ELF relocation types:
R_<ARCH>_*
- Directives:
.section, .global, .type, .size, .align all working
- DWARF: verify
.debug_info emitted for a C function (needed for GDB)
- Branch offsets: verify PC-relative encoding for forward and backward branches
- Immediate ranges: verify truncation and sign-extension at instruction boundaries
QoR Metrics to Evaluate
- All instructions: encode-decode round-trip passes
- All relocation types: defined and tested
- ELF output: readable by
readelf -a
- DWARF: basic debug info emitted
Output Required
- Assembler integrated in LLVM MC layer
- Encoding test suite (one test per instruction format)
- Relocation definition table
Stage: linker_config
Linker Script Template
MEMORY {
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}
ENTRY(_start)
SECTIONS {
.text : { *(.text.reset) *(.text*) *(.rodata*) } > FLASH
.data : { *(.data*) } > RAM AT > FLASH
.bss : { *(.bss*) *(COMMON); PROVIDE(__bss_end = .); } > RAM
.stack : { . = ALIGN(16); PROVIDE(__stack_top = .); . += STACK_SIZE; } > RAM
}
Domain Rules
- Memory regions must match chip memory map exactly
- Startup code (
crt0.S): copy .data LMA→VMA; zero .bss; call main()
- Stack defined via linker symbol
__stack_top; size configurable at link time
- All relocation types from assembler stage must be handled
- Verify: bare-metal binary links, loads, executes from reset vector
QoR Metrics to Evaluate
- Binary links without undefined symbols
.data initialised correctly at runtime
.bss zeroed at startup
- Stack pointer: correct value at entry
Output Required
- Linker scripts per memory configuration
- Startup code (crt0.S)
- Linker configuration documentation
Stage: runtime_libs
Required Libraries
| Library |
Contents |
Source |
| compiler-rt |
Integer multiply/divide, soft-float |
LLVM |
| newlib/picolibc |
C standard library (bare-metal) |
Port |
| libstdc++/libc++ |
C++ standard library |
LLVM/GCC |
| libm |
Math library |
newlib |
Porting newlib
- Implement syscall stubs:
_write, _read, _sbrk, _exit, _close
_sbrk: heap using __heap_start/__heap_end linker symbols
_write: route to UART or semihosting for debug output
- C++ global constructors: add
.init_array section to linker script
QoR Metrics to Evaluate
printf, malloc, memcpy, strlen: all functional
- Soft-float: bit-exact results vs IEEE 754 (if no HW FPU)
- Heap: no corruption under stress allocation/free test
- C++ constructors: called before
main()
Output Required
- Ported and compiled runtime libraries
- Syscall stub implementations
- Library test results
Stage: toolchain_validation
Validation Tiers
| Tier |
Pass Criteria |
| Smoke (hello world) |
100% |
| Unit (per-instruction asm tests) |
100% |
| Compiler (C feature tests) |
≥ 99% |
| Runtime (C library tests) |
≥ 99% |
| Application (representative workloads) |
Correct output |
| Performance |
Within 10% of target |
QoR Metrics to Evaluate
- Compiler regression: ≥ 99% pass
- Runtime tests: ≥ 99% pass
- Application workloads: correct output vs golden
- No miscompilation (wrong output = P0 blocker)
Output Required
- Regression report (per tier, pass/fail counts)
- Miscompilation root cause (if any)
- Performance comparison vs target
Stage: toolchain_signoff
Sign-off Checklist
Output Required
- Toolchain release package
- Validation report
- ABI specification (final)
- Known issues list
Memory
Write on stage completion
After each stage completes (regardless of whether an orchestrator session is active),
write or overwrite one JSON record in memory/compiler/experiences.jsonl keyed by
run_id. This ensures data is persisted even if the flow is interrupted or called
without full orchestrator context.
Use run_id = compiler_<YYYYMMDD>_<HHMMSS> (set once at flow start; reuse on each
stage update). Every JSON record written must include a top-level "run_id" field
whose value matches this key — this is what makes overwrites unambiguous. Set
signoff_achieved: false until the final sign-off stage completes.
Run state (write before first stage, update after each stage)
Write memory/compiler/run_state.md as the first action before launching any tool:
run_id: compiler_<YYYYMMDD>_<HHMMSS>
design_name: <design>
tool: <primary tool>
start_time: <ISO-8601>
last_stage: <first stage name>
Update last_stage after each stage completes. This file lets wakeup-loop prompts
and resumed sessions identify the correct run without relying on in-memory state.
Create the file and parent directories if they do not exist.
Optional: claude-mem index
If mcp__plugin_ecc_memory__add_observations is available in this session, emit each
applied fix as an observation to entity chip-design-compiler-fixes after writing to
experiences.jsonl. Skip silently if the tool is absent — JSONL is the canonical record.
1---2name: compiler-toolchain3description: Compiler toolchain development for custom processor ISAs — LLVM/GCC backend, assembler, linker scripts, runtime libraries, and regression validation. Use when building a compiler for a custom RISC-V extension, proprietary ISA, or any processor where no existing toolchain targets it correctly.4license: MIT5---67# Skill: Compiler Toolchain Development89## Invocation1011When this skill is loaded and a user presents a compiler or ISA task, **do not12execute stages directly**. Immediately spawn the13`digital-chip-design-agents:compiler-orchestrator` agent and pass the full user14request and any available context to it. The orchestrator enforces the stage15sequence, loop-back rules, and sign-off criteria defined below.1617Use the domain rules in this file only when the orchestrator reads this skill18mid-flow for stage-specific guidance, or when the user asks a targeted reference19question rather than requesting a full flow execution.2021## Pre-run Context2223Before executing or advising on **any** stage, read the following files if they exist:24251. `memory/compiler/knowledge.md` — known failure patterns, successful tool flags, PDK/tool quirks.26 Incorporate its guidance into every stage decision. If absent, proceed without it.272. `memory/compiler/run_state.md` — current run identity (`run_id`, `design_name`, `tool`,28 `last_stage`). Use this to resume correctly after interruption. If absent, a new run29 is starting; the orchestrator will create this file before the first stage.3031This pre-run read applies whether this skill is loaded by a user or called by the32orchestrator mid-flow. It ensures the fix database is consulted before any diagnosis step.3334## Purpose35Build and validate a complete compiler toolchain (LLVM or GCC based) for a36custom processor ISA. Bridges hardware and software — without a working37toolchain no software can run on the designed chip.3839---4041## Supported EDA Tools4243### Open-Source44- **LLVM/Clang** (`clang`, `llc`, `llvm-mc`, `llvm-objdump`) — primary toolchain for new ISA backends45- **GCC and GNU Binutils** (`gcc`, `as`, `ld`, `objdump`) — alternative backend; well-tested for RISC-V extensions46- **QEMU** (`qemu-system-*`) — instruction-accurate ISA emulation for toolchain validation without hardware4748### Proprietary49- **Green Hills MULTI** — safety-critical compiler and debugger IDE50- **IAR Embedded Workbench** — certified compiler for ARM/RISC-V51- **Arm Compiler 6** (`armcc`) — LLVM-based compiler for Arm targets5253---5455## Stage: isa_analysis5657### ISA Feature → Toolchain Component Mapping58| ISA Feature | Toolchain Component |59|-------------|-------------------|60| Instruction encoding | Assembler, disassembler |61| Register file | Register allocator, ABI |62| Calling convention | ABI, function call lowering |63| Branch/jump | Control flow, delay slot handling |64| Load/store addressing | Memory access patterns |65| SIMD/vector | Auto-vectorisation, intrinsics |66| Atomics | Memory model, concurrency |67| Multiply/divide | Integer arithmetic lowering |68| FPU presence | FP ABI (hard-float vs soft-float) |69| Custom instructions | Intrinsics, builtin functions |7071### ABI Requirements (define before any backend code)721. Argument passing: which registers, stack spill rules732. Return value registers743. Callee-saved vs caller-saved register classification754. Stack alignment (8 or 16 byte)765. Data type sizes and alignments776. Struct layout (padding, packing rules)787. Thread-local storage model (if RTOS target)7980### Output Required81- ISA-to-toolchain mapping table82- ABI specification document83- List of LLVM/GCC backend files to create/modify84- Target triple: `<arch>-<vendor>-<os>`8586---8788## Stage: backend_dev8990### LLVM Backend — Implement in This Order911. `RegisterInfo.td`: register classes, aliases, reserved registers922. `InstrInfo.td`: all instruction definitions with encoding933. `CallingConv.td`: argument and return value register rules944. `SchedModel.td`: latency and throughput per instruction class955. `TargetMachine.cpp`: entry point, subtarget selection966. `ISelDAGToDAG.cpp`: selection DAG → machine instruction lowering977. `FrameLowering.cpp`: stack frame, prologue/epilogue988. `AsmPrinter.cpp`: assembly text emission99100### Testing per Component101- TableGen: `llvm-tblgen` compiles .td without errors102- Codegen: `llc` compiles C snippets; verify .s output manually103- MC layer: `llvm-mc --show-encoding` verifies instruction encoding104105### QoR Metrics to Evaluate106- All ISA instruction classes: lowerable from LLVM IR107- Calling convention: function call round-trip test passes108- No illegal instructions in generated assembly109- Basic integer test program: compiles, links, executes on ISS110111### Common Issues & Fixes112| Issue | Fix |113|-------|-----|114| TableGen pattern not matching | Add explicit `Pat<>` with matching operand types |115| Stack corrupt | Verify prologue saves all callee-saved regs |116| Calling convention mismatch | Cross-check CCAssignToReg vs ABI spec |117118### Output Required119- Complete LLVM backend source tree120- Regression test files (llc lit tests)121- Build instructions (CMake)122123---124125## Stage: assembler_dev126127### Domain Rules1281. LLVM MC layer provides assembler via .td instruction definitions1292. For every instruction: encode-decode round-trip test1303. Define all ELF relocation types: `R_<ARCH>_*`1314. Directives: `.section`, `.global`, `.type`, `.size`, `.align` all working1325. DWARF: verify `.debug_info` emitted for a C function (needed for GDB)1336. Branch offsets: verify PC-relative encoding for forward and backward branches1347. Immediate ranges: verify truncation and sign-extension at instruction boundaries135136### QoR Metrics to Evaluate137- All instructions: encode-decode round-trip passes138- All relocation types: defined and tested139- ELF output: readable by `readelf -a`140- DWARF: basic debug info emitted141142### Output Required143- Assembler integrated in LLVM MC layer144- Encoding test suite (one test per instruction format)145- Relocation definition table146147---148149## Stage: linker_config150151### Linker Script Template152```ld153MEMORY {154 FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K155 RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K156}157ENTRY(_start)158SECTIONS {159 .text : { *(.text.reset) *(.text*) *(.rodata*) } > FLASH160 .data : { *(.data*) } > RAM AT > FLASH161 .bss : { *(.bss*) *(COMMON); PROVIDE(__bss_end = .); } > RAM162 .stack : { . = ALIGN(16); PROVIDE(__stack_top = .); . += STACK_SIZE; } > RAM163}164```165166### Domain Rules1671. Memory regions must match chip memory map exactly1682. Startup code (`crt0.S`): copy `.data` LMA→VMA; zero `.bss`; call `main()`1693. Stack defined via linker symbol `__stack_top`; size configurable at link time1704. All relocation types from assembler stage must be handled1715. Verify: bare-metal binary links, loads, executes from reset vector172173### QoR Metrics to Evaluate174- Binary links without undefined symbols175- `.data` initialised correctly at runtime176- `.bss` zeroed at startup177- Stack pointer: correct value at entry178179### Output Required180- Linker scripts per memory configuration181- Startup code (crt0.S)182- Linker configuration documentation183184---185186## Stage: runtime_libs187188### Required Libraries189| Library | Contents | Source |190|---------|----------|--------|191| compiler-rt | Integer multiply/divide, soft-float | LLVM |192| newlib/picolibc | C standard library (bare-metal) | Port |193| libstdc++/libc++ | C++ standard library | LLVM/GCC |194| libm | Math library | newlib |195196### Porting newlib1971. Implement syscall stubs: `_write`, `_read`, `_sbrk`, `_exit`, `_close`1982. `_sbrk`: heap using `__heap_start`/`__heap_end` linker symbols1993. `_write`: route to UART or semihosting for debug output2004. C++ global constructors: add `.init_array` section to linker script201202### QoR Metrics to Evaluate203- `printf`, `malloc`, `memcpy`, `strlen`: all functional204- Soft-float: bit-exact results vs IEEE 754 (if no HW FPU)205- Heap: no corruption under stress allocation/free test206- C++ constructors: called before `main()`207208### Output Required209- Ported and compiled runtime libraries210- Syscall stub implementations211- Library test results212213---214215## Stage: toolchain_validation216217### Validation Tiers218| Tier | Pass Criteria |219|------|--------------|220| Smoke (hello world) | 100% |221| Unit (per-instruction asm tests) | 100% |222| Compiler (C feature tests) | ≥ 99% |223| Runtime (C library tests) | ≥ 99% |224| Application (representative workloads) | Correct output |225| Performance | Within 10% of target |226227### QoR Metrics to Evaluate228- Compiler regression: ≥ 99% pass229- Runtime tests: ≥ 99% pass230- Application workloads: correct output vs golden231- No miscompilation (wrong output = P0 blocker)232233### Output Required234- Regression report (per tier, pass/fail counts)235- Miscompilation root cause (if any)236- Performance comparison vs target237238---239240## Stage: toolchain_signoff241242### Sign-off Checklist243- [ ] Compiler: generates correct code for custom ISA244- [ ] Assembler: encodes all instructions correctly245- [ ] Linker: correct scripts for all memory configurations246- [ ] Runtime: libgcc/compiler-rt, newlib, libm all pass tests247- [ ] Binutils: objdump, readelf, nm, objcopy work for target248- [ ] Debugger: GDB or LLDB with target support functional249- [ ] ISS: instruction-set simulator available250- [ ] All regression tiers: PASS251- [ ] Documentation: ABI spec, getting started guide, known issues252253### Output Required254- Toolchain release package255- Validation report256- ABI specification (final)257- Known issues list258259---260261## Memory262263### Write on stage completion264After each stage completes (regardless of whether an orchestrator session is active),265write or overwrite one JSON record in `memory/compiler/experiences.jsonl` keyed by266`run_id`. This ensures data is persisted even if the flow is interrupted or called267without full orchestrator context.268269Use `run_id` = `compiler_<YYYYMMDD>_<HHMMSS>` (set once at flow start; reuse on each270stage update). Every JSON record written must include a top-level `"run_id"` field271whose value matches this key — this is what makes overwrites unambiguous. Set272`signoff_achieved: false` until the final sign-off stage completes.273### Run state (write before first stage, update after each stage)274Write `memory/compiler/run_state.md` as the **first action** before launching any tool:275```markdown276run_id: compiler_<YYYYMMDD>_<HHMMSS>277design_name: <design>278tool: <primary tool>279start_time: <ISO-8601>280last_stage: <first stage name>281```282Update `last_stage` after each stage completes. This file lets wakeup-loop prompts283and resumed sessions identify the correct run without relying on in-memory state.284Create the file and parent directories if they do not exist.285286### Optional: claude-mem index287If `mcp__plugin_ecc_memory__add_observations` is available in this session, emit each288applied fix as an observation to entity `chip-design-compiler-fixes` after writing to289`experiences.jsonl`. Skip silently if the tool is absent — JSONL is the canonical record.