193 lines
7.1 KiB
HTML
193 lines
7.1 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Blockly zu LLVM IR - Final</title>
|
|
<style>
|
|
body { font-family: sans-serif; }
|
|
#container { display: flex; }
|
|
#outputArea { margin-left: 20px; }
|
|
#codeOutput { width: 500px; height: 580px; font-family: 'Courier New', Courier, monospace; font-size: 14px; white-space: pre-wrap; border: 1px solid #ccc; }
|
|
#blocklyDiv { height: 600px; width: 800px; }
|
|
.button-bar { margin-bottom: 10px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>LLVM IR (.dll) Generator</h1>
|
|
<p>Bauen Sie links Ihre Logik. Rechts erscheint der LLVM-Code, der zu einer 64-Bit DLL für Windows kompiliert werden kann.</p>
|
|
|
|
<div class="button-bar">
|
|
<button onclick="saveWorkspace()">Speichern</button>
|
|
<button onclick="loadWorkspace()">Letzten Stand laden</button>
|
|
<button onclick="generateAndPostCode()">Code generieren und posten</button>
|
|
</div>
|
|
|
|
<div id="container">
|
|
<div id="blocklyDiv"></div>
|
|
<div id="outputArea">
|
|
<h2>Erzeugter LLVM-Code:</h2>
|
|
<textarea id="codeOutput" readonly></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://unpkg.com/blockly/blockly_compressed.js"></script>
|
|
<script src="https://unpkg.com/blockly/blocks_compressed.js"></script>
|
|
<script src="https://unpkg.com/blockly/msg/de.js"></script>
|
|
|
|
<script>
|
|
window.onload = function() {
|
|
|
|
let workspace;
|
|
|
|
// === LLVM-IR-GENERATOR (FINALE VERSION) ===
|
|
Blockly.LLVM = new Blockly.Generator('LLVM');
|
|
Blockly.LLVM.ORDER_ATOMIC = 0;
|
|
Blockly.LLVM.ORDER_NONE = 99;
|
|
|
|
// --- Block-Definitionen für die Toolbox ---
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "host_log_integer",
|
|
"message0": "Logge Integer %1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "VALUE",
|
|
"check": "Number"
|
|
}
|
|
],
|
|
"previousStatement": null,
|
|
"nextStatement": null,
|
|
"colour": 290,
|
|
"tooltip": "Sendet einen Integer-Wert an den Delphi-Host.",
|
|
"helpUrl": ""
|
|
}
|
|
]);
|
|
|
|
// --- Generator-Implementierungen ---
|
|
|
|
Blockly.LLVM.regCounter = 0;
|
|
Blockly.LLVM.newReg = function() {
|
|
return '%' + (Blockly.LLVM.regCounter++);
|
|
};
|
|
|
|
Blockly.LLVM.workspaceToCode = function(workspace) {
|
|
Blockly.LLVM.regCounter = 1;
|
|
const allVariables = workspace.getAllVariables();
|
|
let varAllocations = '';
|
|
if (allVariables.length > 0) {
|
|
allVariables.forEach(v => {
|
|
const safeVarName = v.name.replace(/ /g, '_');
|
|
varAllocations += ` @${safeVarName} = common global i32 0\n`;
|
|
});
|
|
}
|
|
|
|
const topBlock = workspace.getTopBlocks(true)[0];
|
|
const code = topBlock ? Blockly.LLVM.blockToCode(topBlock) : '';
|
|
|
|
let moduleCode = `target triple = "x86_64-pc-win32"\n\n`;
|
|
moduleCode += `@gLogIntProc = common global void (i32)* null\n\n`;
|
|
if (varAllocations) {
|
|
moduleCode += '; Global Variables\n';
|
|
moduleCode += varAllocations + '\n';
|
|
}
|
|
moduleCode += 'define dllexport void @StarteLogik(void (i32)* %LogIntProc) {\n';
|
|
moduleCode += 'entry:\n';
|
|
moduleCode += ' store void (i32)* %LogIntProc, void (i32)** @gLogIntProc\n\n';
|
|
moduleCode += code.split('\n').map(line => line ? ' ' + line : '').join('\n');
|
|
moduleCode += '\n ret void\n';
|
|
moduleCode += '}\n';
|
|
return moduleCode;
|
|
};
|
|
|
|
Blockly.LLVM.scrub_ = function(block, code) {
|
|
const nextBlock = block.nextConnection && block.nextConnection.targetBlock();
|
|
const nextCode = nextBlock ? Blockly.LLVM.blockToCode(nextBlock) : '';
|
|
return code + nextCode;
|
|
};
|
|
|
|
Blockly.LLVM.forBlock['variables_set'] = function(block) {
|
|
const varName = block.workspace.getVariableById(block.getFieldValue('VAR')).name.replace(/ /g, '_');
|
|
const value = Blockly.LLVM.valueToCode(block, 'VALUE', Blockly.LLVM.ORDER_ATOMIC) || '0';
|
|
return `store i32 ${value}, i32* @${varName}\n`;
|
|
};
|
|
|
|
Blockly.LLVM.forBlock['math_change'] = function(block) {
|
|
const varName = block.workspace.getVariableById(block.getFieldValue('VAR')).name.replace(/ /g, '_');
|
|
const delta = Blockly.LLVM.valueToCode(block, 'DELTA', Blockly.LLVM.ORDER_ATOMIC) || '0';
|
|
|
|
const loadReg = Blockly.LLVM.newReg();
|
|
const addReg = Blockly.LLVM.newReg();
|
|
|
|
let code = '';
|
|
code += `${loadReg} = load i32, i32* @${varName}\n`;
|
|
code += `${addReg} = add nsw i32 ${loadReg}, ${delta}\n`;
|
|
code += `store i32 ${addReg}, i32* @${varName}\n`;
|
|
return code;
|
|
};
|
|
|
|
Blockly.LLVM.forBlock['variables_get'] = function(block) {
|
|
const varName = block.workspace.getVariableById(block.getFieldValue('VAR')).name.replace(/ /g, '_');
|
|
return ['@' + varName, Blockly.LLVM.ORDER_ATOMIC];
|
|
};
|
|
|
|
Blockly.LLVM.forBlock['math_number'] = function(block) {
|
|
return [String(block.getFieldValue('NUM')), Blockly.LLVM.ORDER_ATOMIC];
|
|
};
|
|
|
|
Blockly.LLVM.forBlock['host_log_integer'] = function(block) {
|
|
const varName = Blockly.LLVM.valueToCode(block, 'VALUE', Blockly.LLVM.ORDER_ATOMIC) || '@unknown';
|
|
|
|
const valueReg = Blockly.LLVM.newReg();
|
|
const logPtrReg = Blockly.LLVM.newReg();
|
|
|
|
let code = '';
|
|
code += `${valueReg} = load i32, i32* ${varName}\n`;
|
|
code += `${logPtrReg} = load void (i32)*, void (i32)** @gLogIntProc\n`;
|
|
code += `call void ${logPtrReg}(i32 ${valueReg})\n`;
|
|
return code;
|
|
};
|
|
|
|
// === INITIALISIERUNG VON BLOCKLY ===
|
|
|
|
const toolboxXml = `
|
|
<xml>
|
|
<category name="Variablen" colour="%{BKY_VARIABLES_HUE}" custom="VARIABLE"></category>
|
|
<category name="Mathematik" colour="%{BKY_MATH_HUE}">
|
|
<block type="math_number"></block>
|
|
<block type="math_change">
|
|
<value name="DELTA"><shadow type="math_number"><field name="NUM">1</field></shadow></value>
|
|
</block>
|
|
</category>
|
|
<category name="Host" colour="290">
|
|
<block type="host_log_integer"></block>
|
|
</category>
|
|
</xml>`;
|
|
|
|
workspace = Blockly.inject('blocklyDiv', {
|
|
toolbox: toolboxXml
|
|
});
|
|
|
|
function generateAndPostCode() {
|
|
const code = Blockly.LLVM.workspaceToCode(workspace);
|
|
if (window.chrome && window.chrome.webview) {
|
|
window.chrome.webview.postMessage(code);
|
|
} else {
|
|
console.log("PostMessage an Host nicht verfügbar. Code in Konsole ausgegeben:");
|
|
console.log(code);
|
|
}
|
|
}
|
|
window.generateAndPostCode = generateAndPostCode;
|
|
|
|
window.saveWorkspace = function() { const state = Blockly.serialization.workspaces.save(workspace); localStorage.setItem('blocklyWorkspace', JSON.stringify(state)); alert('Arbeitsbereich gespeichert!'); }
|
|
window.loadWorkspace = function() { const stateString = localStorage.getItem('blocklyWorkspace'); if (!stateString) { return; } const state = JSON.parse(stateString); Blockly.serialization.workspaces.load(state, workspace); }
|
|
function updateCode(event) { if (event.isUiEvent) return; const code = Blockly.LLVM.workspaceToCode(workspace); document.getElementById('codeOutput').value = code; }
|
|
workspace.addChangeListener(updateCode);
|
|
loadWorkspace();
|
|
};
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|