Virgil
1 program
Added 2026-02-05T20:19:59.712785Z
Agent: claude-codeModel: sonnetWebSearch: enabled
Evidence
Report issue
View issues
Aliases: —
Provenance: commit da82e5c293 · authored 2026-02-05T21:21:27+01:00 · agent claude-code · model sonnet
Sources mentioning this language
2 sources · pl_id:
pl/virgilRelated languages
Real programs from Software Heritage
No SWH evidence indexed yet for this language. (Either the SWH mining hasn't reached this language's extensions, or no matching files exist in the archive.)
Programs collected by LLM agents experimental · unverified
Gathered by LLM agents during the experiment that started this catalogue. They are not verified: the agent names an origin, but a program can be altered or invented — an audit found one attributed to a file that does not exist, in a syntax the language does not have. Prefer the programs archived by Software Heritage above. The catalogue's goal is the languages themselves, grounded in sources (PLDB, Wikipedia, Rosetta Code, …), with real archived programs; these examples may be dropped.
Mini Register Allocator
Provenance: commit da82e5c293 · authored 2026-02-05T21:21:27+01:00 · agent claude-code · model sonnet · WebSearch enabled
// implicit type reg: Reg;
// implicit type vreg: int;
// implicit type use: Use;
// implicit type ref: MiRef;
class MiRef(vreg: int) {
var prev: MiRef;
var assignment: Loc;
var constraint: Reg.set;
}
class Def extends MiRef {
var overwrite: bool;
new(vreg: int) super(vreg) { }
def at(r: Reg.set) -> Def { constraint = r; return this; }
def is(loc: Loc) -> Def { assignment = loc; return this; }
}
class Use extends MiRef {
new(vreg: int) super(vreg) { }
def at(r: Reg.set) -> Use { constraint = r; return this; }
def is(loc: Loc) -> Use { assignment = loc; return this; }
}
class Instr(opcode: int, operands: Array<MiRef>) {
}
type Loc {
case None; // No location assigned
case Reg(reg: Reg); // Register
case Stack(slot: i20); // < 0 is caller's stack, > 0 is callee's stack
}
enum Reg { A, B, C, D }
def REG_COUNT = byte.!(Reg.D.tag + 1);
def FREE_LIST: byte = REG_COUNT;
def NOT_FREE: byte = byte.!(REG_COUNT + 1);
def REGS = [Reg.A, Reg.B, Reg.C, Reg.D];
def LOCS: Array<Loc.Reg> = [Loc.Reg(Reg.A), Loc.Reg(Reg.B), Loc.Reg(Reg.C), Loc.Reg(Reg.D)];
def NONE: Reg.set;
// The main register allocator.
class Allocator(vregs: int) {
def vstack = Array<i20>.new(vregs); // The stack slot assignment, if any, for each vreg
def vprev = Array<(MiRef, int)>.new(vregs); // The next backward use for each vreg
def vnext = Array<(MiRef, int)>.new(vregs); // The next forward use for each vreg
def vassign = Array<Loc>.new(vregs); // The current register assignment for each vreg
def rcontents = Array<(MiRef, int)>.new(REG_COUNT); // The current contents of the register file
var curpos: int;
var stack: i20 = 0;
var moves: List<(Instr, int)>;
def rprevfree = Array<byte>.new(REG_COUNT + 1);
def rnextfree = Array<byte>.new(REG_COUNT + 1);
def allocate(instrs: Array<Instr>) -> Array<Instr> {
init();
// Allocate registers by walking instructions in reverse order.
for (pos = instrs.length - 1; pos >= 0; pos--) {
curpos = pos;
var i = instrs[pos];
var defs = 0, operands = i.operands;
for (o in operands) {
if (Def.?(o)) {
defs++;
allocRegForOutput(Def.!(o));
} else if (Use.?(o)) {
if (defs > 0) { defs = 0; freeDefs(operands); }
allocRegForInput(Use.!(o));
}
printState();
}
if (defs > 0) {
freeDefs(operands);
printState();
}
}
if (moves != null) {
var len = 0;
for (l = moves; l != null; l = l.tail) len++;
var ninstrs = Array<Instr>.new(instrs.length + len);
var pos = 0, n = moves;
for (i < instrs.length) {
while (n != null && n.head.1 == i) {
ninstrs[pos++] = n.head.0;
n = n.tail;
}
ninstrs[pos++] = instrs[i];
}
while (n != null) {
ninstrs[pos++] = n.head.0;
n = n.tail;
}
instrs = ninstrs;
}
return instrs;
}
def freeDefs(operands: Array<MiRef>) {
for (o in operands) {
if (!Def.?(o)) break;
var r = vassign[o.vreg];
if (Loc.Reg.?(r)) freeReg(o);
}
}
def allocRegForOutput(d: Def) {
// Allocate a register for the definition, if not already allocated.
var da = vassign[d.vreg];
var dn = vnext[d.vreg];
var next = vnext[d.vreg];
vnext[d.vreg] = (d, curpos);
if (da == Loc.None) {
// The virtual register {d.vreg} was spilled between this instruction
// and the next use. Allocate a new register and insert a save afterward.
var r = allocReg(d, d.constraint);
da = r;
assignReg(r, d);
// Insert a save (somewhere) after this position.
if (next.0 != null) save(d, curpos + 1);
} else if (d.constraint != NONE) {
var reg = Loc.Reg.!(da).reg;
if (!(d.constraint >= reg)) {
freeReg(d);
var r = allocReg(d, d.constraint);
da = r;
assignReg(r, d);
// Insert a move (somewhere) after this position.
if (next.0 != null) mov(d.vreg, next.0.assignment, r, next.1);
}
}
d.assignment = da;
}
def printState() {
puts("STATE @");
puti(curpos);
puts(": ");
for (i < rcontents.length) {
var p = rcontents[i];
if (p.0 == null) continue;
puts(" %");
puts(LOCS[i].reg.name);
puts("=v");
puti(p.0.vreg);
puts("@");
puti(p.1);
}
puts(", free={");
var first = rnextfree[FREE_LIST];
for (i = first; i != FREE_LIST; i = rnextfree[i]) {
if (i != first) putc(',');
puts(REGS[i].name);
}
puts("}");
System.ln();
}
def allocRegForInput(u: Use) {
var ua = vassign[u.vreg];
vnext[u.vreg] = (u, curpos);
if (ua == Loc.None) ua = allocReg(u, u.constraint);
u.assignment = ua;
assignReg(Loc.Reg.!(ua), u);
}
def freeReg(ref: MiRef) {
var reg = Loc.Reg.!(vassign[ref.vreg]).reg;
vassign[ref.vreg] = Loc.None;
rcontents[reg.tag] = (null, 0);
var first = rnextfree[FREE_LIST];
// Insert into register free list.
rprevfree[reg.tag] = FREE_LIST;
rnextfree[reg.tag] = first;
rprevfree[first] = reg.tag;
rnextfree[FREE_LIST] = reg.tag;
}
def assignReg(r: Loc.Reg, ref: MiRef) {
ref.assignment = r;
vassign[ref.vreg] = r;
var index = r.reg.tag;
rcontents[index] = (ref, curpos);
var prev = rprevfree[index];
var next = rnextfree[index];
rnextfree[index] = rprevfree[index] = NOT_FREE;
if (prev != NOT_FREE) {
// Remove from register free list.
rnextfree[prev] = next;
rprevfree[next] = prev;
}
}
def allocReg(ref: MiRef, constraint: Reg.set) -> Loc.Reg {
var vreg = ref.vreg;
if (constraint == NONE) {
var first = rnextfree[FREE_LIST];
if (first != FREE_LIST) {
// Just allocate the first free register.
var reg = LOCS[first];
vassign[vreg] = reg;
return reg;
}
constraint = Reg.set.all;
}
// Constrained or no regs left.
var choice: Reg, prevmax = int.max;
for (r in constraint) {
// Consider each register {r}, and let {nextpos = next(r.vreg)}
var ref = rcontents[r.tag].0;
if (ref == null) return LOCS[r.tag]; // Free; no need to spill.
var nextpos = vnext[ref.vreg].1;
// Don't pick registers used in the same instruction.
if (nextpos == curpos) continue;
// XXX: Pick a register with {nextpos - pos >= reload_latency}
// Pick a register with earliest {prevpos}, which has the
// effect of avoiding conflicts for the longest time.
var prevpos = vprev[ref.vreg].1;
if (prevpos < prevmax) {
prevmax = prevpos;
choice = r;
}
}
vassign[rcontents[choice.tag].0.vreg] = Loc.None;
reload(rcontents[choice.tag]);
return LOCS[choice.tag];
}
def reload(ref: MiRef, pos: int) {
puts("reload v");
puti(ref.vreg);
puts("@");
puti(pos);
System.ln();
var loc = Loc.Stack(getSlot(ref.vreg));
mov(ref.vreg, ref.assignment, loc, pos);
}
def save(ref: MiRef, pos: int) {
puts("save v");
puti(ref.vreg);
puts("@");
puti(pos);
System.ln();
var loc = Loc.Stack(getSlot(ref.vreg));
mov(ref.vreg, loc, ref.assignment, pos);
}
def mov(vreg: int, dest: Loc, src: Loc, pos: int) {
var u = Use.new(vreg).is(src);
var d = Def.new(vreg).is(dest);
var save = Instr.new(MOV, [d, u]);
moves = List.new((save, pos), moves);
}
def init() {
for (i < rcontents.length) rcontents[i] = (null, 0);
for (i < rnextfree.length) rnextfree[i] = byte.!(i + 1);
for (i < rprevfree.length) rprevfree[i] = byte.!(i - 1);
rprevfree[0] = FREE_LIST;
rnextfree[FREE_LIST] = 0;
}
def getSlot(vreg: int) -> i20 {
var slot = vstack[vreg];
return if(slot == 0, vstack[vreg] = ++stack, slot);
}
}
def ADD = 1;
def SUB = 2;
def CALL = 3;
def MOV = 4;
def RET = 5;
def PARAMS = 6;
// Helper for creating instruction sequences.
class Assembler {
new() {
instrs[ipos++] = Instr.new(PARAMS, []);
}
def add(a: int, b: int) -> int { return op3(ADD, a, b); }
def sub(a: int, b: int) -> int { return op3(SUB, a, b); }
def call(a: int, b: int) -> int { return op3(CALL, a, b); }
def ret(a: Array<int>) {
instrs[ipos++] = Instr.new(RET, Arrays.map(a, Use.new));
}
def newParam() -> int {
var vreg = vregs++;
var d = Def.new(vreg).at(REGS[vreg]);
instrs[0] = Instr.new(PARAMS, Arrays.append(d, instrs[0].operands));
return vreg;
}
def extract() -> Array<Instr> {
var result = Array<Instr>.new(ipos);
for (i < ipos) result[i] = instrs[i];
return result;
}
def varCount() -> int {
return vregs;
}
private var instrs = Array<Instr>.new(100);
private var ipos = 0;
private var vregs = 0;
private def op3(opcode: int, a: int, b: int) -> int {
var vreg = vregs++;
instrs[ipos++] = Instr.new(opcode, [Def.new(vreg), Use.new(a), Use.new(b)]);
return vreg;
}
}
def puts = System.puts;
def puti = System.puti;
def putc = System.putc;
def printAssignment(r: Loc) {
match (r) {
None => ;
Reg(reg) => {
puts("=%");
puts(reg.name);
}
Stack(slot) => {
puts("=#");
puti(slot);
}
}
}
def printRef(r: MiRef) {
if (r == null) return;
putc('v');
puti(r.vreg);
if (r.assignment != Loc.None) {
puts("=");
print(r.assignment);
} else if (r.constraint != NONE) {
puts("in{");
var first = true;
for (reg in Reg.set.all) {
if (r.constraint >= reg) {
if (!first) puts(",");
print(reg);
first = false;
}
}
puts("}");
}
putc(' ');
}
def printInstrs(instrs: Array<Instr>) {
for (j < instrs.length) {
var i = instrs[j];
puti(j);
puts(": ");
match (i.opcode) {
ADD => puts("add ");
SUB => puts("sub ");
CALL => puts("call ");
MOV => puts("mov ");
RET => puts("ret ");
PARAMS => puts("param ");
}
for (o in i.operands) printRef(o);
System.ln();
}
}
def print<T>(v: T) {
if (string.?(v)) return System.puts(string.!(v));
if (Reg.?(v)) {
System.puts("%");
System.puts(Reg.!(v).name);
return;
}
if (Loc.?(v)) {
var loc = Loc.!(v);
match (loc) {
None => ;
Reg(reg) => {
puts("%");
puts(reg.name);
}
Stack(slot) => {
puts("#");
puti(slot);
}
}
}
if (int.?(v)) return System.puti(int.!(v));
if (Array<Instr>.?(v)) printInstrs(Array<Instr>.!(v));
}
def main() {
var asm = Assembler.new();
var p0 = asm.newParam(), p1 = asm.newParam();
var x = asm.add(p0, p1);
asm.ret([x]);
var instrs = asm.extract();
print(instrs);
puts("--allocated--\n");
instrs = Allocator.new(asm.varCount()).allocate(instrs);
print(instrs);
}