// ── Pure LLVM IR code generation — zero-DOM, flat DFA model ─────────── // // Every block is an LLVM IR label. Every edge is a `br` instruction. // Decisions become `br i1 %cond, label %yes, label %no`. // Error handling becomes `br i1 %result, label %err, label %ok`. (function () { "use strict"; var CodeGen = {}; // ── String pool ───────────────────────────────────────────────────── var _strPool = []; CodeGen.resetStringPool = function () { _strPool = []; }; CodeGen.getStringPool = function () { return _strPool; }; /** * Registers a string literal and returns its unique index. */ CodeGen.allocString = function (s) { var idx = _strPool.indexOf(s); if (idx === -1) { idx = _strPool.length; _strPool.push(s); } return idx; }; /** * Escapes a JS string for LLVM IR `c"..."` constant, and produces * the full `getelementptr` reference for use as a call argument. */ CodeGen.llvmStringArg = function (str, idx) { var escaped = ""; for (var i = 0; i < str.length; i++) { var ch = str.charCodeAt(i); if (ch === 0x22) escaped += "\\22"; else if (ch === 0x5C) escaped += "\\5C"; else if (ch === 0x0A) escaped += "\\0A"; else if (ch === 0x0D) escaped += "\\0D"; else if (ch === 0x09) escaped += "\\09"; else if (ch < 0x20 || ch > 0x7E) { escaped += "\\" + ch.toString(16).toUpperCase().padStart(2, "0"); } else { escaped += str[i]; } } var byteLen = str.length + 1; // includes null terminator return "i8* getelementptr inbounds ([" + byteLen + " x i8], [" + byteLen + " x i8]* @.str." + idx + ", i32 0, i32 0)"; }; /** * Generates the LLVM IR global constant for a string pool entry. */ CodeGen.stringGlobal = function (idx) { var str = _strPool[idx]; var escaped = "", byteLen = 0; for (var i = 0; i < str.length; i++) { var ch = str.charCodeAt(i); byteLen++; if (ch === 0x22) escaped += "\\22"; else if (ch === 0x5C) escaped += "\\5C"; else if (ch === 0x0A) escaped += "\\0A"; else if (ch === 0x0D) escaped += "\\0D"; else if (ch === 0x09) escaped += "\\09"; else if (ch < 0x20 || ch > 0x7E) { var h = ch.toString(16).toUpperCase(); escaped += "\\" + (h.length === 1 ? "0" : "") + h; } else { escaped += str[i]; } } byteLen++; // null terminator return "@.str." + idx + " = private unnamed_addr constant [" + byteLen + " x i8] c\"" + escaped + "\\00\""; }; // ── Flat DFA emit ─────────────────────────────────────────────────── CodeGen.emitFlat = function (entry) { var visited = new Set(); var parts = []; function bb(block) { return "bb_" + block.id; } function emit(block) { if (visited.has(block)) { parts.push(" br label %" + bb(block) + "\n"); return; } visited.add(block); parts.push("\n" + bb(block) + ":"); var own = block.generateOwnCode(); if (own) parts.push(own); var flow = block.wcNextFlow || block.nextFlow || []; var fc = ""; if (typeof block.generateFlowCode === "function") { fc = block.generateFlowCode(); // Replace bare label references with bb_ prefixed versions var replaced = ""; var pos = 0, m; while ((m = /label\s+%([\w.]+)/g).lastIndex = pos, m = m.exec(fc)) { replaced += fc.slice(pos, m.index) + "label %bb_" + m[1]; pos = m.index + m[0].length; } replaced += fc.slice(pos); fc = replaced; } else { for (var i = 0; i < flow.length; i++) { var t = flow[i].toElement; if (t) fc += " br label %" + bb(t) + "\n"; } } if (fc) parts.push("\n" + fc); for (var i = 0; i < flow.length; i++) { var t = flow[i].toElement; if (t) emit(t); } } emit(entry); return parts.join(""); }; // ── Full module assembly ──────────────────────────────────────────── CodeGen.generateIRFile = function (entryBlock, declarations, globals, prologue) { var lines = ["; ModuleID = \"wisecode\"", "target triple = \"x86_64-pc-linux-gnu\"", ""]; if (declarations) lines.push(declarations); if (globals) lines.push(globals); lines.push(""); lines.push("define i32 @main() {"); if (prologue) lines.push("entry:\n" + prologue + "\n br label %bb_" + entryBlock.id); lines.push(CodeGen.emitFlat(entryBlock)); lines.push("}"); lines.push(""); lines.push("; --- END ---"); return lines.join("\n"); }; // ── Export ────────────────────────────────────────────────────────── if (typeof module !== "undefined" && module.exports) { module.exports = CodeGen; } if (typeof window !== "undefined") { window.CodeGen = CodeGen; } })();