Skip to content

v0.12.0

Latest

Choose a tag to compare

@graemeg graemeg released this 24 Jun 10:56

Blaise v0.12.0 — Changelog

Headline: the native x86-64 backend is now the default, with a complete
internal assembler and internal linker — Blaise compiles and links a binary
with zero external tools. Compilation is incremental (per-unit) by default,
and per-unit OPDF makes incrementally-built multi-unit programs fully
debuggable in pdr. Ships the first real standard library (JSON, crypto,
networking, exact decimals). QBE is now opt-in and deprecated.

Native backend & toolchain (default)

  • Native x86-64 is the default backend; QBE is opt-in via --backend qbe
    (deprecated, slated for removal in a later release).
  • Internal assembler + internal linker are the default: blaise --source X --output Y produces and links an executable with no external as/ld/gcc
    (only the distro CRT objects are read).
  • Internal linker: symbol resolution, static relocations, ET_EXEC,
    then dynamic linking — GOT/PLT, CRT object discovery, PIE (ET_DYN) emission,
    TLS relocations, .init_array/.fini_array, GOTPCRELX relaxation.
  • Internal linker wired into the compiler driver; --assembler and --linker
    accept internal|external (both default to internal on the native backend).
  • Escape hatches: --no-incremental (whole-program build), --assembler external, --linker external, --backend qbe.

Compilation model

  • Incremental, per-unit compilation is the default (like FPC): each unit is
    compiled to its own .o, then linked. Faster rebuilds; sidesteps the
    whole-program assembly memory blow-up. --no-incremental forces the old
    whole-program mode.
  • Fixed a class of cached-interface (.bif) rebuild bugs so a warm-cache
    rebuild is lossless and coherent (dropped unit-init calls, impl-only uses
    dependencies dropped from the link, duplicate globals, and cached-.bif
    method vtable-slot reconstruction).
  • .bif interface format advanced to v2 (carries impl-section uses, unit
    initialisation flag, generic template locals, parameter defaults, exit
    values, and vtable facts); old .bif are rejected and recompiled.
  • New WARMCACHE_FIXPOINT_OK guard plus an extended bif-coverage drift guard
    covering the .bif interface container types.

Debugging (OPDF)

  • Per-unit OPDF: every object (each unit and the program) carries its own
    .opdf section; the linker concatenates them, mirroring FPC's multi-unit
    layout. pdr can now set breakpoints, show cross-unit callstacks, and inspect
    params/locals/fields inside dependency units of an incrementally-built
    program — under both the internal and external toolchains.
  • The internal assembler now carries the .opdf section; the internal linker
    merges it (SHF_ALLOC).

Language

  • Qualified type names: UnitName.TypeName, including dotted qualifiers
    (System.SysUtils.TFormatSettings).
  • Chained l-value assignment: Self.FStack[0].Count := value and similar
    subscript-then-field chains.
  • Writable string subscript with copy-on-write: S[i] := ch.
  • Conditional compilation: symbol-presence {$IFDEF}/{$IFNDEF}/{$DEFINE}
    with a predefined BLAISE symbol plus CPU/OS symbols (-d/--define).
  • Sets over an integer-subrange base (set of 0..255) and Boolean set
    operands; integer literals and ranges in const-decl set literals.
  • Named integer-subrange types; forward routines in a program declaration
    section; nested-proc-first unit implementation bodies.

Examples

// native, one step — no external tools
//   blaise --source hello.pas --output hello
program hello;
begin
  WriteLn('Hello, Blaise 0.12!')
end.
uses Json.Types, Json.Writer;
var o: TJSONObject;
begin
  o := TJSONObject.Create();
  o.Add('name', 'Blaise');
  o.Add('version', 12);
  WriteLn(o.AsJSON());   // {"name":"Blaise","version":12}
  o.Free()
end.
var s: String;
begin
  s := 'hello';
  s[0] := 'H';           // writable subscript, copy-on-write
  WriteLn(s)             // Hello
end.

Standard library (opt-in)

  • JSON — DOM (Json.Types), parser (Json.Parser), reader (Json.Reader),
    writer (Json.Writer).
  • Encoding.Base64Base64Encode / Base64Decode.
  • Security.Crypto — SHA-1 (Sha1, Sha1Hex).
  • Security.Guid — RFC 4122 v4 GUIDs.
  • Net.Sockets — IPv4 TCP.
  • Net.WebSockets — RFC 6455 framing + handshake.
  • Net.Http.Server — minimal HTTP/1.1 server with WebSocket upgrade.
  • Numerics.Decimal (TDecimal, exact decimal) and Numerics.Money
    (TMoney, currency-aware, configurable rounding).
  • StrUtils additions — SplitChar, SplitLines, JoinList,
    CodePointToString.
  • blaise.testing unit-test framework moved into the stdlib; stdlib ships its
    own test suite (pasbuild test -m blaise-stdlib).

Codegen / ARC / runtime fixes

  • Float arguments to methods, constructors, and inherited calls are passed in
    SSE (xmm) registers per the System V ABI, including the >6-slot overflow path
    and on the callee side; float-returning method calls and implicit-Self
    float-field reads are correct on both backends.
  • Implicit-Self virtual method calls dispatch through the vtable (previously
    bound statically — silently wrong for overrides, a link error for abstract
    bases).
  • HasClassAttribute emits the runtime call and the class attribute RTTI table
    on the native backend.
  • Record-copy uses field-width loads/stores; interface arguments to
    record-returning routines; transient record-returning call receivers.
  • 64-bit integer constants keep their full bit pattern (no truncation);
    internal assembler encodes SSE movq/movd between XMM and GP registers.

Tooling / CI

  • Rolling-bootstrap re-anchored at v0.12.0: the replay range is entirely
    native-default with the internal toolchain — no QBE, no gcc.
  • CI runs the bootstrap on master plus branch-scoped validate-only pre-flight
    runs (ci/**, feature/**, bootstrap/**) that never write the master
    carry-forward cache.

Verification

  • Self-hosting fixpoint at 410,477 lines of QBE IR — FIXPOINT_OK,
    NATIVE_FIXPOINT_OK, NATIVE_INTERNAL_OK, and WARMCACHE_FIXPOINT_OK all
    green.
  • 3,745 compiler tests + 57 stdlib tests passing.