Fact-checked by Grok 2 weeks ago

C--

C-- (pronounced C minus minus) is a C-like programming language designed as a portable to serve as an efficient primarily generated by compilers for high-level languages, with particular emphasis on supporting garbage collection and optimizing for speed across major computer architectures. Developed in the late 1990s by researchers including from the , Thomas Nordin, and Dino Oliva, C-- aims to balance minimal hardware dependencies with high performance and usability, prioritizing these over strict orthogonality or minimality to make it suitable as a backend for both mainstream and research s. The language was introduced through key publications such as the 1997 paper "C--: A Portable " and the 1998 C-- Language Reference Manual, which detail its syntax and semantics tailored for compiler backends. Later revisions involved contributions from Norman Ramsey, enhancing its infrastructure for practical use. Key features of C-- include explicit support for low-level operations like and while providing abstractions for high-level constructs such as closures and garbage collection interfaces, enabling portable without sacrificing efficiency. It has been employed in compiler pipelines, including early versions of the (GHC), where it facilitated the translation of functional language code to . The design allows programmers familiar with imperative languages to write or understand C-- code, though its primary role remains as a target for rather than direct human authoring.

Introduction

Overview

C-- (pronounced "C minus minus") is a simplified, C-like (IR) language designed for in compilers targeting high-level languages, especially functional or garbage-collected ones. Developed as a portable , it enables efficient translation from abstract source semantics to across multiple architectures. Distinct from standard C—a full —C-- functions primarily as a backend target in compiler pipelines rather than for direct human-written programs. It emphasizes minimalism and portability, avoiding high-level constructs like I/O while providing low-level suitable for optimization and code emission. The core purpose of C-- is to bridge high-level program semantics and low-level machine instructions through an assembly-like syntax, incorporating features such as explicit stack management and interfaces for runtime services like garbage collection. This design supports writers in generating efficient, architecture-independent code for complex language features. The original C--, introduced in the 1990s by Simon Peyton Jones and Norman Ramsey, underwent refinements in the 2000s, culminating in Version 2 with improved specifications for broader compiler integration.

History

C-- originated in the mid-1990s at the University of Glasgow and Digital Equipment Corporation's Systems Research Center, where it was initiated by Simon Peyton Jones, Norman Ramsey, and collaborators including Fermín Reig to overcome limitations in existing compiler backends for functional languages like Haskell and ML. The project sought to create a portable assembly language that facilitated efficient code generation while supporting high-level runtime features such as garbage collection. The first edition, C-- v1, emerged around 1997, with its formal definition outlined in "The C-- Language Reference Manual" published in 1998 by and contributors Thomas Nordin, Dino Oliva, and Pablo Nogueira Iglesias. By the early , development advanced to C-- v2, which enhanced support for segmented memory architectures and provided a more rigorous formal specification, as detailed in subsequent academic works. A pivotal publication, "The C-- Compiler Infrastructure" by Norman Ramsey and in 2004, described the evolution toward a robust infrastructure for construction. Adoption of C-- reached its height in the 2000s through integration into major compilers, particularly the (GHC), where a simplified fork called Cmm was introduced around 2005 to serve as the low-level for . This enabled efficient backend processing for while leveraging C--'s design for portability and runtime support. Post-2010, the core language saw no major version releases due to its maturity, though minor updates persisted in associated tools and forks like Cmm within GHC. As of 2025, Cmm remains a foundational component of GHC's compilation pipeline, supporting native across multiple architectures without significant changes to the original C-- v2 framework.

Design

Goals and Principles

C-- was designed primarily to serve as a portable assembly language that simplifies the generation of efficient machine code across diverse platforms for compiler writers, addressing the challenges of developing retargetable backends for high-level languages. By providing a common intermediate representation, it enables the reuse of code generators while preserving the essential features of source languages, particularly those requiring advanced runtime support like garbage collection. The core principles of C-- emphasize minimalism and simplicity, eschewing a standard library and restricting features to essentials in order to avoid unnecessary complexity and bloat. Portability is a foundational tenet, achieved through architecture-agnostic constructs that abstract machine-specific details, allowing explicit control over low-level elements such as registers, memory layout, and calling conventions without inheriting the full intricacies and undefined behaviors of C. To accommodate modern programming paradigms, especially in functional and garbage-collected languages, C-- incorporates built-in mechanisms for garbage collection interfaces and support for closures via runtime primitives, facilitating efficient implementation of these features in the generated code. Design choices prioritize formal, verifiable semantics to eliminate ambiguities common in lower-level languages, with a focus on automated code generation by front-end compilers rather than manual authoring by programmers.

Key Features

C-- uses a procedure-based execution model with an unlimited number of local variables, which the backend maps to registers or locations, providing explicit control over evaluation order and facilitating straightforward and optimization by compilers targeting the language. This model requires explicit management of variables, enhancing portability across different architectures. The language supports a minimal set of primitive types, such as word1, word2, word4, word8 (for integers and pointers) and float4, float8 (for floating-point numbers), or in later versions bits8, bits16, bits32, bits64 and float32, float64, float80. These sized types guide for without the complexity of higher-level structures. Garbage collection safety is supported through directives to identify pointers, ensuring portability across memory models. Control flow in C-- is structured around basic blocks connected by jumps and conditional branches, providing a linear, assembly-like flow suitable for optimization passes. It includes explicit support for tail calls, allowing efficient of recursive or iterative patterns without in compatible . and higher-order functions are not directly supported in the core language syntax; instead, closures are handled through that manage capture and , delegating complexity to the underlying . Built-in operations encompass arithmetic on words or bits and floats, bit manipulation for low-level efficiency, and calls to external functions, all crafted to expose opportunities for compiler optimizations such as constant folding and dead code elimination. Unlike standard C, C-- omits the preprocessor to avoid macro expansion issues in generated code, flattens structs and unions into explicit memory layouts without aggregate types, and eschews automatic variable allocation in favor of manual stack or heap management, making it a more suitable target for high-level language compilers.

Language Elements

Syntax

C-- programs consist of a sequence of top-level declarations, including data layout directives and definitions, with support for and export declarations but no modules or include directives, assuming a flat structure suitable for backends. definitions use the form [conv] proc name(type arg1, ..., type argn) { body }, where "conv" specifies a , types are explicit for parameters, and the body contains a sequence of statements. The supports multiple values via return(expr1, ..., exprn); and tail calls with jump name(args); for optimization. includes blocks delimited by curly braces for grouping statements. Variable declarations appear as type name1, ..., namen; within bodies or blocks, without inline initialization; scoping is block-based but simplified without nested functions. Statements include (name = expr;), conditionals (if expr rel expr block [else block]; where rel is ==, !=, etc.), jumps ([goto](/page/Goto) name;), and returns (return [exprs];), following a low-level, assembly-oriented notation. Labels are defined as name:. is achieved using statements and labels, as there is no built-in while or . Expressions include constants, variable names, memory accesses (e.g., type [expr] for dereference), operators (infix binary like +, *, ==; prefix unary like -), and calls (prim(op, args)). Operator precedence follows standard rules, with parentheses for grouping. Arithmetic uses +, -, *, /; comparisons use ==, !=, <, etc.; no logical && or || as high-level booleans, but conditions via comparisons. Function (procedure) calls are name(args). For example, (a + b) * c follows standard precedence. Comments use block style only: /* ... */ for multi-line annotations, non-nested. Whitespace is insignificant except to separate tokens; the language is not indentation-sensitive, and statements end with semicolons. Keywords are reserved (e.g., proc, if, return), and identifiers start with letters or underscore, followed by letters, digits, or underscores, case-sensitive. The formal grammar is context-free, with nonterminals in italics and terminals in bold. Key BNF from the specification includes:
  • program ::= pal_element | program pal_element
  • pal_element ::= data_decl | proc_decl
  • proc_decl ::= [conv] Name ( typed_arg_list ) [ data_decl ] block
  • block ::= { stm_list }
  • stm ::= skip ; | type Name_list ; | Name = expr ; | if expr rel_op expr block [ else block ] ; | goto Name ; | return ( expr_list ) ; | Name : stm
  • expr ::= const | Name | type [ expr ] | ( expr ) | expr binop expr | prim ( op , expr_list )
  • binop ::= + | - | * | / | == | != | < | > | <= | >=
This grammar ensures parsing for low-level code generation. Types are attached explicitly to declarations and operations to aid code generation and debugging, without automatic conversions.

Type System

C-- uses a simple static type system for low-level code generation, focusing on explicit sizes to support verification and optimization in backends, with types mapping directly to hardware. It lacks higher-level features like subtyping, prioritizing portability for functional language compilers. The description here is for the original version 1 specification (1998); later versions and implementations like GHC's Cmm introduce variations. Basic types include word n for fixed-width values of n bytes (n=1,2,4,8, typically unsigned or machine-word), float m for floating-point (m=4 for single-precision, m=8 for double-precision). Pointers are represented as word n (n matching pointer size) for raw addresses. For garbage collection support, gcptr denotes heap pointers, enabling accurate via stack maps and tagged values without runtime checks. These types inform and operations. No implicit type conversions; all must be explicit via casts (e.g., word4 n), with checks for size compatibility and . accesses specify type and optional (e.g., word4{align2}[ptr] for 4-byte access at 2-byte ). The ensures type consistency for , avoiding dynamic checks. The is monomorphic, without polymorphism, generics, or , keeping it lightweight for backend tasks. No ad-hoc polymorphism or . Type inference is absent; all types must be explicitly annotated in declarations, parameters, and operations to maintain clarity for generated code and enable optimizations like inlining. Functions (procedures) require explicit typed signatures, e.g., word4 proc_name(word4 arg1, word8 arg2), supporting multiple returns like return(word4, word8);, ensuring consistency for code emission and analysis.

Runtime Support

Memory Management

C-- employs a segmented memory model to promote portability across diverse architectures, dividing memory into four distinct segments: code, , , and . The code segment contains the program's executable instructions as initialized data in sections. The segment accommodates static data, with its size and initial contents fixed at for predictable layout. The segment handles local variables and activation records via stackdata labels, dynamically expanding and contracting as procedures are invoked and returned. The segment supports runtime allocation for variable-sized objects, managed by the front-end and abstracting away platform-specific details to facilitate backend implementation. This segmentation allows C-- programs to reason about independently of the underlying machine's addressing conventions. Allocation and deallocation in C-- are handled by the front-end runtime system rather than language primitives, enabling compilers to generate portable code without embedded machine-specific assembly. Heap objects under garbage collection do not require manual deallocation, while non-collected memory management is delegated to the runtime. Stack space is reserved implicitly through procedure activations and stackdata declarations. Access to memory in C-- uses load and store operations of the form type[expr], where type is typically bits k for the native pointer size, applied across segments without explicit qualifiers. For example, bits32[ptr] = value stores a 32-bit value at the address given by ptr, with analogous loads like value = bits32[ptr]. Pointers use a single native type (bits k), checked at compile time for compatibility. C-- is an unsafe language, permitting unchecked runtime errors for invalid accesses such as null dereferences or out-of-bounds pointers, without built-in compile-time prevention beyond basic type matching. Alignment can be asserted optionally (e.g., aligned int), but is not enforced by default. Alignment in C-- is governed by type specifications to accommodate constraints portably. For instance, a bits(64) type requires 8-byte on 64-bit systems, with the inserting as necessary to satisfy this during in any . Larger or types inherit alignment from their components, ensuring consistent behavior across targets. This rule-based approach minimizes runtime overhead while avoiding from misaligned accesses. Overall, C--'s memory model balances explicit control with safety guarantees, making it suitable as an for high-level language .

Garbage Collection

C-- incorporates a dedicated runtime interface for garbage collection, enabling compilers for high-level languages to integrate efficient reclamation without relying on platform-specific details. This support, introduced in the initial design and refined in later versions like v2.0, is achieved through mechanisms that expose operations for tracing and , while abstracting low-level machine dependencies. The design emphasizes portability across architectures and compatibility with diverse strategies, making it suitable for languages requiring automatic . Central to C--'s GC mechanism is the management of roots, where live pointers in registers or on the stack are identified using front-end descriptors and marked with the gc_root directive to inform the collector of potential references. This approach allows precise tracing during collection phases, reducing overhead by avoiding conservative approximations. For incremental and concurrent collection, C-- supports write barriers through the invariant keyword, which identifies variables unchanged across procedure calls to aid analysis without halting the mutator. This enables techniques like remembered sets in generational collectors to track modifications efficiently. Such mechanisms are essential for maintaining collector invariants in low-latency applications. Object representation in C-- facilitates through tagged values, where allocated blocks include headers with type tags and slots for forwarding addresses during copying phases. Allocation is performed manually by the front-end (e.g., updating a pointer), ensuring objects are initialized for tracing. Execution interruptions are managed via yield(GC) calls at safe points, allowing the collector to suspend the program for reclamation after non-allocating operations. These features collectively enable precise, type-aware collection while supporting forwarding for compacting algorithms. The GC interface is engineered for flexibility, accommodating stop-the-world collectors for simplicity, generational schemes for performance in long-running programs, and custom implementations via extensible hooks. A foundational element is the segmented model, which confines objects to designated segments; the collector scans only these segments for roots and pointers, bypassing irrelevant regions like or , thereby optimizing scan times and minimizing false positives in pointer identification. This segmented approach underpins C--'s efficiency in resource-constrained or large-address-space environments. These features position C-- as an effective backend for functional language compilers, where frequent allocations and complex pointer structures necessitate robust GC support without compromising portability.

Examples

Basic Program

A basic program in C-- demonstrates the language's core syntax for defining procedures, using type annotations, performing arithmetic, and returning results. The following example defines a simple procedure to add two 32-bit integers and invokes it to compute the sum of 1 and 2, returning the result.
c
proc add (word4 x, word4 y) {
  return (x + y);
}

proc main () {
  let result = add (1, 2);
  return (result);
}
This program defines the add, which takes two parameters typed as word4—32-bit words representing —and returns their using the + arithmetic operator. The type word4 specifies a 4-byte (32-bit) , ensuring portable representation across architectures. The main calls add(1, 2) with literal constants and returns the result. Literals are promoted to word4 as needed. Execution proceeds by entering the main , evaluating the call to add, performing the (3 in decimal), and returning the value. C--'s evaluation model uses registers where possible, spilling to the if necessary, with arithmetic operators handling operations. This highlights C--'s low-level control while maintaining portability. When compiled, this program generates that loads constants, adds them, and exits, typically producing an that returns 3 as its exit status. Its purpose is to illustrate a simple in C-- as a portable intermediate language.

Compiler-Generated Snippet

C-- provides interfaces for , allowing compiler-generated code to interact with systems. The following illustrative snippet demonstrates low-level for a closure-like structure, using data segments and foreign calls for allocation, as supported in the language design for high-level runtimes like those in functional compilers. Note that implementations such as the (GHC) extend C-- with variants like Cmm for specific features like explicit GC primitives.
c
data {
  word tag;
  word code_ptr;
  word env_ptr;
} closure;

proc create_closure (word env) {
  foreign "gc_alloc" (3 * sizeof(word)) -> r1;  // Call to runtime allocator
  r1 ! 0 = 1;  // Tag
  r1 ! 1 = &closure_body;  // Code pointer
  r1 ! 2 = env;  // Environment
  return (r1);
}

proc closure_body (word self, word arg) {
  let env = self ! 2;
  let x = env ! 0;
  let result = x + arg;
  return (result);
}
This snippet shows allocation via a foreign call to a GC runtime (gc_alloc), initialization of a closure structure in a data segment, and access in the body procedure. Write barriers are handled by the runtime during pointer stores. In standard C--, GC support is via foreign interfaces rather than built-in primitives; GHC's Cmm adds explicit support for such operations to facilitate code generation from Haskell. These features enable optimization while preserving semantics for garbage-collected environments.

Implementations

Glasgow Haskell Compiler

The (GHC) employs C-- as the core (IR) in its backend pipeline, a role it has held since the mid-1990s to facilitate efficient and portable compilation of programs. In this pipeline, Haskell source code undergoes front-end processing—including parsing, type checking, and desugaring—followed by optimization in the Core language, a simplified functional IR. Core is then transformed into the STG (Spineless Tagless G-machine) machine, which models Haskell's semantics, before being converted to C-- via the code generation phase. This C-- IR captures low-level imperative constructs while preserving essential high-level abstractions needed for Haskell's runtime behaviors, such as laziness and garbage collection interfaces. GHC's implementation of C--, referred to internally as Cmm, features a dialect with targeted extensions to accommodate Haskell-specific constructs that standard C-- does not natively support. These include representations for unboxed types, such as primitive integers () and floats (), which avoid the overhead of heap allocation and inherent in Haskell's boxed values, enabling direct manipulation of machine-level data. Additionally, the dialect incorporates support for parallelism, including primitives for creation, generation for parallel evaluation, and mechanisms aligned with Haskell's concurrent model. These adaptations ensure that C-- can express the nuances of Haskell's non-strict semantics and without excessive low-level boilerplate. From the C-- stage, the pipeline branches to one of several backends for final code emission: the Native Code Generator (NCG), which produces for over 20 architectures; the backend, which leverages LLVM's optimization passes for improved performance on supported targets; or the C backend, used primarily in unregisterised mode for maximum portability across exotic platforms. This modular design allows GHC to maintain broad architectural coverage while isolating backend-specific optimizations. As of GHC 9.14.1 released in November 2025, C-- continues to serve as the foundational backend , with active maintenance focused on enhancements like better integration with modern versions and optimizations for emerging hardware. This enduring role underscores C--'s contribution to GHC's portability, enabling Haskell programs to compile efficiently across diverse systems without platform-specific rewrites in earlier pipeline stages.

Other Compilers and Tools

An experimental version of MLton, a whole-program for , was developed to generate C-- as a backend, but it is not used in current configurations. The of C-- includes a dedicated toolkit for validation and processing, comprising assemblers, linkers, and simulators that enable testing of C-- code on various architectures. These tools support the language's portability goals by providing a standardized way to assemble and simulate intermediate representations, aiding developers in debugging and verifying compiler backends. Beyond these, C-- has seen minor use in experimental backends for functional languages such as , primarily within academic prototypes focused on retargetable . As of 2025, such applications remain confined to tools, with no significant new adoptions or integrations reported in major systems like proof assistants.

Current Status

Ongoing Use

Cmm, the implementation of the C-- intermediate language within the (GHC), remains integral to Haskell code compilation in 2025, primarily serving as the low-level representation for the native code generator backend that produces optimized across supported architectures. This backend is the default for most GHC builds, handling the final stages of optimization and code generation after higher-level intermediates like and STG. GHC versions 9.6.7 and 9.12.2, released in March 2025, incorporate refinements to the Cmm pipeline, including enhancements to register allocation and instruction selection that improve runtime performance for functional codebases involving millions of lines, such as those in enterprise Haskell deployments. These updates ensure Cmm's efficiency in processing complex Haskell programs without introducing breaking changes to its core semantics. Later releases, including the LTS version 9.14 in August 2025 and 9.12.3 release candidate in November 2025, continue to integrate Cmm as the default backend. Maintenance of Cmm occurs through the GHC repository on , where the Haskell community contributes sporadically to extend support for emerging architectures, including optimizations for ARM64 in cross-compilation scenarios. A 2025 Google Summer of Code project dedicated to documenting and improving Cmm, accepted in May and ongoing as of November 2025, underscores active community involvement, focusing on better tooling and clarity for backend contributors. In production environments as of 2025, Cmm enables the compilation of widely used tools like , which processes documents in diverse formats, and , a , demonstrating its reliability for real-world applications with no plans indicated in GHC roadmaps. Although GHC's LLVM backend offers an alternative for broader optimization opportunities, Cmm's straightforward design preserves its value in research-oriented and lightweight compilation niches, where direct control over low-level details is preferred. Developments in the , such as the integration of Cmm with GHC's backend for browser-based Haskell execution, highlight ongoing explorations of its intermediates for modern targets.

Limitations and Alternatives

Despite its foundational role in GHC's code generation pipeline, C-- (implemented as Cmm in GHC) exhibits several limitations that constrain its broader applicability. Development of the core C-- specification has been inactive since the early 2000s, with the last major revision (Version 2.0) published in 2005, leading to a stagnant ecosystem lacking modern tools, IDE integrations, or third-party libraries. In GHC, Cmm remains under-documented and fragmented, complicating maintenance and extension efforts, as highlighted in ongoing documentation initiatives. Architecture support also lags; while GHC provides experimental native code generation for RISC-V via Cmm as of version 9.12.1, full production readiness is pending further stabilization, with discussions at the 2025 Haskell Implementors' Workshop focusing on advancing RISC-V backend support. Scalability challenges further limit C--'s effectiveness in contemporary environments. The language's support for mutable variables and redefinitions hinders precise lifetime tracking, impeding advanced optimizations like or . Manual stack management in Cmm can obstruct compiler auto-optimizations, and remains rudimentary, with no built-in for SIMD instructions beyond extensions proposed over a decade ago, restricting performance on modern CPUs. GPU offloading is unsupported, as C-- lacks constructs for , forcing reliance on external frameworks for such workloads. Modern alternatives to C-- offer more robust features for needs. LLVM stands out as a feature-rich, widely adopted option, enabling aggressive optimizations, broad architecture coverage (including mature and GPU targets), and integration with diverse frontends; GHC itself supports an LLVM backend that partially bypasses Cmm for improved performance in select scenarios. Cranelift provides a faster, WebAssembly-oriented suitable for and lightweight environments, emphasizing simplicity over C--'s procedural depth. For ultimate control in performance-critical paths, native remains viable, though it sacrifices portability. Transition trends in GHC include experiments with direct LLVM integration to sidestep Cmm bottlenecks, though complete replacement is unlikely in the near term due to entrenched dependencies; meanwhile, many languages have shifted to intermediates like JVM or CLR for managed execution. Looking ahead, C-- holds niche potential for revival as a secure intermediate representation in formally verified compilers, having influenced designs like CompCert's for provable correctness, but realization depends on renewed funding and community investment, which appears improbable without targeted initiatives.

References

  1. [1]
    [PDF] C--: A Portable Assembly Language - Microsoft
    C--: A Portable Assembly Language. Simon Peyton Jones1, Thomas Nordin2, and Dino Oliva2. 1 Department of Computing Science, University of Glasgow. 2 Paci c ...
  2. [2]
    [PDF] The C-- Language Reference Manual - Microsoft
    C-- is a portable assembly language designed to be a good backend for high level languages (par- ticularly for those that make use of garbage-collection) ...
  3. [3]
    The C– Language Reference Manual - Microsoft Research
    C– is a portable assembly language designed to be a good backend for high level languages (particularly for those that make use of garbage-collection) and ...
  4. [4]
    The C-- Compiler Infrastructure
    C-- also provides a compile-time interface. For ease of use with multiple ... Norman Ramsey graduated from Princeton University in 1983 with a degree ...
  5. [5]
    The Architecture of Open Source Applications (Volume 2)The ...
    The Glasgow Haskell Compiler (GHC) started as part of an academic research ... C-- (was Abstract C), 1,416, 7,591, 5.4. Identifier representations, 1,831 ...
  6. [6]
    C–: a portable assembly language that supports garbage collection
    Jan 1, 1999 · C– is a new language designed expressly for this purpose. The use of a portable assembly language introduces new problems in the support of such high-level run ...
  7. [7]
    The C-- Language Reference Manual
    The C-- Language Reference Manual. Simon Peyton Jones Thomas Nordin Dino Oliva Pablo Nogueira Iglesias May 23,1999. 1 Introduction. C-- is a ...
  8. [8]
    C-- News for May, 2001
    Feb 5, 2007 · We still don't have a working compiler that implements the full Version 2 specification. ... Sergei has built an implementation of C-- by ...
  9. [9]
    [PDF] An LLVM Backend for GHC
    Sep 30, 2010 · The Glasgow Haskell Compiler (GHC) began with a backend trans- lating code for the Spineless Tagless G-machine (STG-machine) to. C [23]. The ...
  10. [10]
    5.10. GHC Backends — Glasgow Haskell Compiler 9.15.20251105 ...
    GHC supports Native, LLVM, C (deprecated), and JavaScript (technical preview) backends. The default is Native, which compiles to assembly code.
  11. [11]
    [PDF] C--: a portable assembly language that supports garbage ... - Microsoft
    We address these prob- lems by combining the C-- language with a C-- run-time interface. ... C: A Reference Manual. fourth edition. Englewood ... The C-- manual.
  12. [12]
    A single intermediate language that supports multiple ...
    We present mechanisms that enable our compiler-target language, C--, to express four of the best known techniques for implementing exceptions, all within a ...
  13. [13]
    Untitled
    module GHC.Cmm.Type ( CmmType -- Abstract , b8, b16, b32, b64, b128, b256, b512, f32, f64, bWord, bHalfWord, gcWord , cInt , cmmBits, cmmFloat , typeWidth, ...
  14. [14]
    [PDF] The C-- Language Specification Version 2.0 ( CVS Revision 1.128 )
    Feb 23, 2005 · The C-- Language Specification. Version 2.0. ( CVS Revision 1.128 ) ... C-- supports the standard C comment conventions. A one-line comment ...
  15. [15]
    A Haskell Compiler - Stanford Secure Computer Systems Group
    We will start though with a quick look at Core, the main intermediate language used by GHC: variables, literals, let, case, lambda abstraction, application.
  16. [16]
    GHC 9.14.1-alpha1 released - Announcements - Haskell Discourse
    Aug 20, 2025 · The GHC developers are very pleased to announce the availability of the first alpha prerelease of GHC 9.14.1. Binary distributions, source ...
  17. [17]
    [PDF] The Yale Haskell Users Manual - Version Y2.0-beta
    Sep 25, 1992 · When you are ready to create fully compiled code and save it in output files, use the C-c c command. This command recur- sively compiles all ...
  18. [18]
    CMinusMinus - MLton
    Oct 21, 2021 · C-- is a portable assembly language intended to make it easy for compilers for different high-level languages to share the same backend.
  19. [19]
  20. [20]
    C--: A portable assembly language | SpringerLink
    May 28, 2006 · C--: A portable assembly language. Conference paper; First ... C-- has to strike a balance between being high-level enough to allow ...
  21. [21]
    [PDF] C-: A Portable Assembly Language | Semantic Scholar
    C--: A Portable Assembly Language that Supports Garbage Collection · S. JonesN. RamseyF. Reig · 1999 ; The Portable Assembly Language C-- : A Critical Review and ...Missing: intended | Show results with:intended
  22. [22]
    GHC activities report: March–May 2025 - Well-Typed
    Jun 20, 2025 · GHC saw explicit level imports, GHCi primop support, debugger improvements, and new GHC releases (9.12.2, 9.6.7, 9.10.2) during March-May 2025.
  23. [23]
    Glasgow Haskell Compiler (GHC) - endoflife.date
    Sep 15, 2025 · Starting with GHC 9.14 (expected in August 2025), there will be preannounced major versions designated as LTS. The first LTS release will be ...
  24. [24]
    Glasgow Haskell Compiler / GHC · GitLab
    ### Summary of C-- Intermediate Language in GHC Codebase (2024-2025)
  25. [25]
    Haskell.org - Program Organization | Google Summer of Code
    Cmm is the intermediate representation and code generation layer used by the Glasgow Haskell Compiler (GHC). It is written in Haskell and sits... View project ...
  26. [26]
    Frontend live-coding via ghci - Tweag
    Apr 17, 2025 · Demonstrate the GHC wasm backend ghci browser mode and how it can be used to live-code a Haskell wasm frontend app.How To Use It · Hot Reloading · Using Ghci To Debug Other...Missing: intermediate | Show results with:intermediate<|control11|><|separator|>
  27. [27]
    The C-- Language Specification Version 2.0 - Publications
    The C-- Language Specification Version 2.0 by Norman Ramsey, Simon Peyton ... Abstract. Specification of the portable assembly language C--. BibTeX Entry.
  28. [28]
    GSoC 2025: Documenting and Improving Cmm - Haskell Discourse
    Apr 16, 2025 · Apple at that time was also hyping it as an intermediate target for iOS deployment… ... Sorry for the delay, getting this here : The ghc-devs July ...
  29. [29]
    2.1. Version 9.12.1 — Glasgow Haskell Compiler 9.12.2 User's Guide
    GHC now has experimental support for native RISC-V code generation (#16783). Constructor PluginProv of type UnivCoProvenance , relevant for typing plugins ...
  30. [30]
    CPU Vector instructions in GHC.Prim (#3557) · Issue - Haskell Gitlab
    Oct 27, 2010 · At the Cmm level, I want to combine 4 floats into one 128-bit packed register. (C and LLVM have operations for this, as does SSE). I'm not clear ...
  31. [31]
    [PDF] A formally verified compiler back-end - Xavier Leroy
    It is a simple, low-level imperative language, comparable to a stripped-down, typeless variant of C. Another source of inspiration was the C-- intermediate ...