界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
开发与工程 · SKILL.md

compiler-toolchain

compiler-toolchain

【开发与工程】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.

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: compiler-toolchain description: > 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. version: 1.0.0 author: chuanseng-ng license: MIT allowed-tools: Read, Write, Bash

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:

  1. 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.
  2. 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 (dialect greenhills) — safety-critical compiler and debugger IDE
  • IAR Embedded Workbench (dialect iar) — certified compiler for ARM/RISC-V
  • Arm Compiler 6 (armcc, dialect arm) — LLVM-based compiler for Arm targets

Stage: isa_analysis

ISA Feature → Toolchain Component Mapping

ISA FeatureToolchain Component
Instruction encodingAssembler, disassembler
Register fileRegister allocator, ABI
Calling conventionABI, function call lowering
Branch/jumpControl flow, delay slot handling
Load/store addressingMemory access patterns
SIMD/vectorAuto-vectorisation, intrinsics
AtomicsMemory model, concurrency
Multiply/divideInteger arithmetic lowering
FPU presenceFP ABI (hard-float vs soft-float)
Custom instructionsIntrinsics, builtin functions

ABI Requirements (define before any backend code)

  1. Argument passing: which registers, stack spill rules
  2. Return value registers
  3. Callee-saved vs caller-saved register classification
  4. Stack alignment (8 or 16 byte)
  5. Data type sizes and alignments
  6. Struct layout (padding, packing rules)
  7. 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

  1. RegisterInfo.td: register classes, aliases, reserved registers
  2. InstrInfo.td: all instruction definitions with encoding
  3. CallingConv.td: argument and return value register rules
  4. SchedModel.td: latency and throughput per instruction class
  5. TargetMachine.cpp: entry point, subtarget selection
  6. ISelDAGToDAG.cpp: selection DAG → machine instruction lowering
  7. FrameLowering.cpp: stack frame, prologue/epilogue
  8. 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

IssueFix
TableGen pattern not matchingAdd explicit Pat<> with matching operand types
Stack corruptVerify prologue saves all callee-saved regs
Calling convention mismatchCross-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

  1. LLVM MC layer provides assembler via .td instruction definitions
  2. For every instruction: encode-decode round-trip test
  3. Define all ELF relocation types: R_<ARCH>_*
  4. Directives: .section, .global, .type, .size, .align all working
  5. DWARF: verify .debug_info emitted for a C function (needed for GDB)
  6. Branch offsets: verify PC-relative encoding for forward and backward branches
  7. 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

  1. Memory regions must match chip memory map exactly
  2. Startup code (crt0.S): copy .data LMA→VMA; zero .bss; call main()
  3. Stack defined via linker symbol __stack_top; size configurable at link time
  4. All relocation types from assembler stage must be handled
  5. 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

LibraryContentsSource
compiler-rtInteger multiply/divide, soft-floatLLVM
newlib/picolibcC standard library (bare-metal)Port
libstdc++/libc++C++ standard libraryLLVM/GCC
libmMath librarynewlib

Porting newlib

  1. Implement syscall stubs: _write, _read, _sbrk, _exit, _close
  2. _sbrk: heap using __heap_start/__heap_end linker symbols
  3. _write: route to UART or semihosting for debug output
  4. 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

TierPass 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
PerformanceWithin 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

  • Compiler: generates correct code for custom ISA
  • Assembler: encodes all instructions correctly
  • Linker: correct scripts for all memory configurations
  • Runtime: libgcc/compiler-rt, newlib, libm all pass tests
  • Binutils: objdump, readelf, nm, objcopy work for target
  • Debugger: GDB or LLDB with target support functional
  • ISS: instruction-set simulator available
  • All regression tiers: PASS
  • Documentation: ABI spec, getting started guide, known issues

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.

我的收藏