From 90d0b9a3913583ed1f7da323d33ccb265af0ff48 Mon Sep 17 00:00:00 2001 From: MESYETI Date: Mon, 25 Nov 2024 14:41:17 +0000 Subject: [PATCH 1/7] improve fib example --- examples/fib.cal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/fib.cal b/examples/fib.cal index 5c53565..814dbfc 100644 --- a/examples/fib.cal +++ b/examples/fib.cal @@ -3,11 +3,11 @@ include "std/io.cal" func fib cell n -> cell res begin if n 1 <= then - n return + n else n 1 - fib n 2 - fib - + return + + end end From 4ec8c432bd6fbdde68f0f012c2dd53a76db3dc6e Mon Sep 17 00:00:00 2001 From: MESYETI Date: Sun, 1 Dec 2024 17:38:32 +0000 Subject: [PATCH 2/7] ptr syntax parses --- TODO.md | 6 ++ editors/micro_callisto.yaml | 2 +- examples/alias.cal | 2 +- examples/inheritance.cal | 4 +- examples/unions.cal | 2 +- source/backends/arm64.d | 91 ++++++++++++------------ source/backends/lua.d | 65 ++++++++++-------- source/backends/rm86.d | 59 ++++++++-------- source/backends/uxn.d | 59 ++++++++-------- source/backends/x86_64.d | 88 +++++++++++++----------- source/compiler.d | 63 ++++++++++------- source/parser.d | 133 +++++++++++++++++++----------------- source/stackCheck.d | 5 +- 13 files changed, 318 insertions(+), 261 deletions(-) diff --git a/TODO.md b/TODO.md index 78d8ef2..535ec98 100644 --- a/TODO.md +++ b/TODO.md @@ -2,3 +2,9 @@ - For loops - Make if/while have a scope - move global constructor calls to let statement +- Make constructors and destructors work on aliased and inherited types +- I think renamed externs are broken? + +## Pointers +Functions `CompileFuncDef`, `CompileLet`, `CompileArray`, `CompileExtern` must be updated +- Add support for them when using constructors and destructors diff --git a/editors/micro_callisto.yaml b/editors/micro_callisto.yaml index a4aae37..a63d977 100644 --- a/editors/micro_callisto.yaml +++ b/editors/micro_callisto.yaml @@ -7,7 +7,7 @@ rules: - statement: "\\b(func|end|begin|asm|include|inline|if|then|elseif|else|while|do)\\b" - statement: "\\b(let|enable|requires|struct|version|return|const|enum|restrict)\\b" - statement: "\\b(continue|break|union|alias|overwrite|error|extern|call|raw)\\b" - - statement: "\\b(implement|as|try|catch|throw|unsafe|man)\\b" + - statement: "\\b(implement|as|try|catch|throw|unsafe|man|ptr)\\b" - type: "\\b(addr|void|u8|i8|u16|i16|u32|i32|u64|i64|size|usize|cell|array)\\b" - constant.string: diff --git a/examples/alias.cal b/examples/alias.cal index 6302abf..b9a10d9 100644 --- a/examples/alias.cal +++ b/examples/alias.cal @@ -2,7 +2,7 @@ include "cores/select.cal" include "std/io.cal" alias int cell -"int.sizeof = " printstr int.sizeof printdec new_line +"int.sizeof = " printstr int.sizeOf printdec new_line let int myInt 65 -> myInt diff --git a/examples/inheritance.cal b/examples/inheritance.cal index 6ba14b7..7b4010a 100644 --- a/examples/inheritance.cal +++ b/examples/inheritance.cal @@ -10,7 +10,7 @@ struct Building : Thing end "Thing.name = " printstr Thing.name printdec new_line -"Thing.sizeof = " printstr Thing.sizeof printdec new_line +"Thing.sizeof = " printstr Thing.sizeOf printdec new_line "Building.name = " printstr Building.name printdec new_line "Building.numWindows = " printstr Building.numWindows printdec new_line -"Building.sizeof = " printstr Building.sizeof printdec new_line +"Building.sizeof = " printstr Building.sizeOf printdec new_line diff --git a/examples/unions.cal b/examples/unions.cal index d5107d1..f513486 100644 --- a/examples/unions.cal +++ b/examples/unions.cal @@ -6,7 +6,7 @@ union MyUnion Array end -"MyUnion.sizeof = " printstr MyUnion.sizeof printdec new_line +"MyUnion.sizeof = " printstr MyUnion.sizeOf printdec new_line let MyUnion foo diff --git a/source/backends/arm64.d b/source/backends/arm64.d index e3b3ef5..a30a44b 100644 --- a/source/backends/arm64.d +++ b/source/backends/arm64.d @@ -21,16 +21,16 @@ private enum WordType { } private struct Word { - WordType type; - bool inline; - Node[] inlineNodes; - bool error; - Type[] params; + WordType type; + bool inline; + Node[] inlineNodes; + bool error; + UsedType[] params; // for C words - Type ret; - bool isVoid; - string symbolName; + UsedType ret; + bool isVoid; + string symbolName; } class BackendARM64 : CompilerBackend { @@ -71,9 +71,9 @@ class BackendARM64 : CompilerBackend { // built in structs types ~= Type("Array", 24, true, [ - StructEntry(GetType("usize"), "length"), - StructEntry(GetType("usize"), "memberSize"), - StructEntry(GetType("addr"), "elements") + StructEntry(UsedType(GetType("usize"), false), "length"), + StructEntry(UsedType(GetType("usize"), false), "memberSize"), + StructEntry(UsedType(GetType("addr"), false), "elements") ]); NewConst("Array.length", 0); NewConst("Array.memberSize", 8); @@ -81,14 +81,16 @@ class BackendARM64 : CompilerBackend { NewConst("Array.sizeof", 8 * 3); types ~= Type("Exception", 24 + 8, true, [ - StructEntry(GetType("bool"), "error"), - StructEntry(GetType("Array"), "msg") + StructEntry(UsedType(GetType("bool"), false), "error"), + StructEntry(UsedType(GetType("Array"), false), "msg") ]); NewConst("Exception.bool", 0); NewConst("Exception.msg", 8); NewConst("Exception.sizeof", 24 + 8); - globals ~= Global("_cal_exception", GetType("Exception"), false, 0); + globals ~= Global( + "_cal_exception", UsedType(GetType("Exception"), false), false, 0 + ); foreach (ref type ; types) { NewConst(format("%s.sizeof", type.name), cast(long) type.size); @@ -573,14 +575,14 @@ class BackendARM64 : CompilerBackend { thisFunc = node.name; - Type[] params; + UsedType[] params; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - params ~= GetType(type); + params ~= UsedType(GetType(type.name), type.ptr); } if (node.inline) { @@ -622,10 +624,10 @@ class BackendARM64 : CompilerBackend { // allocate parameters size_t paramSize = node.params.length * 8; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - if (GetType(type).isStruct) { + if (GetType(type.name).isStruct && !type.ptr) { Error(node.error, "Structures cannot be used in function parameters"); } } @@ -641,7 +643,8 @@ class BackendARM64 : CompilerBackend { Variable var; var.name = param; - var.type = GetType(type); + var.type.type = GetType(type.name); + var.type.ptr = type.ptr; var.offset = cast(uint) offset; offset += var.Size(); variables ~= var; @@ -811,8 +814,8 @@ class BackendARM64 : CompilerBackend { } override void CompileLet(LetNode node) { - if (!TypeExists(node.varType)) { - Error(node.error, "Undefined type '%s'", node.varType); + if (!TypeExists(node.varType.name)) { + Error(node.error, "Undefined type '%s'", node.varType.name); } if (VariableExists(node.name) || (node.name in words)) { Error(node.error, "Variable name '%s' already used", node.name); @@ -824,7 +827,8 @@ class BackendARM64 : CompilerBackend { if (inScope) { Variable var; var.name = node.name; - var.type = GetType(node.varType); + var.type.type = GetType(node.varType.name); + var.type.ptr = node.varType.ptr; var.offset = 0; var.array = node.array; var.arraySize = node.arraySize; @@ -854,7 +858,8 @@ class BackendARM64 : CompilerBackend { } Global global; - global.type = GetType(node.varType); + global.type.type = GetType(node.varType.name); + global.type.ptr = node.varType.ptr; global.array = node.array; global.arraySize = node.arraySize; global.name = node.name; @@ -878,13 +883,14 @@ class BackendARM64 : CompilerBackend { } } - if (!TypeExists(node.arrayType)) { - Error(node.error, "Type '%s' doesn't exist", node.arrayType); + if (!TypeExists(node.arrayType.name)) { + Error(node.error, "Type '%s' doesn't exist", node.arrayType.name); } - array.type = GetType(node.arrayType); - array.global = !inScope || node.constant; - arrays ~= array; + array.type.type = GetType(node.arrayType.name); + array.type.ptr = node.arrayType.ptr; + array.global = !inScope || node.constant; + arrays ~= array; if (!inScope || node.constant) { LoadAddress("x9", format("__array_%d_meta", arrays.length - 1)); @@ -915,9 +921,10 @@ class BackendARM64 : CompilerBackend { variables ~= var; // create metadata variable - var.type = GetType("Array"); - var.offset = 0; - var.array = false; + var.type.type = GetType("Array"); + var.type.ptr = false; + var.offset = 0; + var.array = false; foreach (ref var2 ; variables) { var2.offset += var.Size(); @@ -942,7 +949,7 @@ class BackendARM64 : CompilerBackend { override void CompileString(StringNode node) { auto arrayNode = new ArrayNode(node.error); - arrayNode.arrayType = "u8"; + arrayNode.arrayType = new TypeNode(node.error, "u8", false); arrayNode.constant = node.constant; foreach (ref ch ; node.value) { @@ -1003,22 +1010,22 @@ class BackendARM64 : CompilerBackend { word.type = WordType.C; foreach (ref param ; node.types) { - if (!TypeExists(param)) { - Error(node.error, "Unknown type '%s'", param); + if (!TypeExists(param.name)) { + Error(node.error, "Unknown type '%s'", param.name); } - word.params ~= GetType(param); + word.params ~= UsedType(GetType(param.name), param.ptr); } - if (node.retType == "void") { + if ((node.retType.name == "void") && !node.retType.ptr) { word.isVoid = true; } else { - if (!TypeExists(node.retType)) { - Error(node.error, "Unknown type '%s'", node.retType); + if (!TypeExists(node.retType.name)) { + Error(node.error, "Unknown type '%s'", node.retType.name); } - word.ret = GetType(node.retType); + word.ret = UsedType(GetType(node.retType.name), node.retType.ptr); } word.symbolName = node.func; diff --git a/source/backends/lua.d b/source/backends/lua.d index 9f1bdfe..e6d714d 100644 --- a/source/backends/lua.d +++ b/source/backends/lua.d @@ -28,11 +28,11 @@ private enum WordType { } private struct Word { - WordType type; - bool inline; - Node[] inlineNodes; - bool error; - Type[] params; + WordType type; + bool inline; + Node[] inlineNodes; + bool error; + UsedType[] params; } class BackendLua : CompilerBackend { @@ -56,9 +56,9 @@ class BackendLua : CompilerBackend { // built in structs types ~= Type("Array", 3, true, [ - StructEntry(GetType("usize"), "length"), - StructEntry(GetType("usize"), "memberSize"), - StructEntry(GetType("addr"), "elements") + StructEntry(UsedType(GetType("usize"), false), "length"), + StructEntry(UsedType(GetType("usize"), false), "memberSize"), + StructEntry(UsedType(GetType("addr"), false), "elements") ]); NewConst("Array.length", 0); NewConst("Array.memberSize", 1); @@ -66,8 +66,8 @@ class BackendLua : CompilerBackend { NewConst("Array.sizeof", 3); types ~= Type("Exception", 3 + 1, true, [ - StructEntry(GetType("bool"), "error"), - StructEntry(GetType("Array"), "msg") + StructEntry(UsedType(GetType("bool"), false), "error"), + StructEntry(UsedType(GetType("Array"), false), "msg") ]); NewConst("Exception.bool", 0); NewConst("Exception.msg", 1); @@ -78,7 +78,8 @@ class BackendLua : CompilerBackend { } globals ~= Global( - "_cal_exception", GetType("Exception"), false, 0, new GlobalExtra(globalStack) + "_cal_exception", UsedType(GetType("Exception"), false), false, 0, + new GlobalExtra(globalStack) ); globalStack += globals[$ - 1].Size(); } @@ -286,14 +287,14 @@ class BackendLua : CompilerBackend { thisFunc = node.name; - Type[] params; + UsedType[] params; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - params ~= GetType(type); + params ~= UsedType(GetType(type.name), type.ptr); } if (node.inline) { @@ -317,14 +318,16 @@ class BackendLua : CompilerBackend { // allocate parameters size_t paramSize = node.params.length; + foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - if (GetType(type).isStruct) { + if (GetType(type.name).isStruct && !type.ptr) { Error(node.error, "Structures cannot be used in function parameters"); } } + if ((paramSize > 0) && !node.manual) { output ~= format("vsp = vsp - %d\n", paramSize); foreach (ref var ; variables) { @@ -337,7 +340,8 @@ class BackendLua : CompilerBackend { Variable var; var.name = param; - var.type = GetType(type); + var.type.type = GetType(type.name); + var.type.ptr = type.ptr; var.offset = cast(uint) offset; offset += var.Size(); variables ~= var; @@ -491,8 +495,8 @@ class BackendLua : CompilerBackend { } override void CompileLet(LetNode node) { - if (!TypeExists(node.varType)) { - Error(node.error, "Undefined type '%s'", node.varType); + if (!TypeExists(node.varType.name)) { + Error(node.error, "Undefined type '%s'", node.varType.name); } if (VariableExists(node.name) || (node.name in words)) { Error(node.error, "Variable name '%s' already used", node.name); @@ -504,7 +508,8 @@ class BackendLua : CompilerBackend { if (inScope) { Variable var; var.name = node.name; - var.type = GetType(node.varType); + var.type.type = GetType(node.varType.name); + var.type.ptr = node.varType.ptr; var.offset = 0; var.array = node.array; var.arraySize = node.arraySize; @@ -537,7 +542,8 @@ class BackendLua : CompilerBackend { Global global; global.name = node.name; - global.type = GetType(node.varType); + global.type.type = GetType(node.varType.name); + global.type.ptr = node.varType.ptr; global.array = node.array; global.arraySize = node.arraySize; global.extra = extra; @@ -571,12 +577,13 @@ class BackendLua : CompilerBackend { } } - if (!TypeExists(node.arrayType)) { - Error(node.error, "Type '%s' doesn't exist", node.arrayType); + if (!TypeExists(node.arrayType.name)) { + Error(node.error, "Type '%s' doesn't exist", node.arrayType.name); } - array.type = GetType(node.arrayType); - array.global = !inScope || node.constant; + array.type.type = GetType(node.arrayType.name); + array.type.ptr = node.arrayType.ptr; + array.global = !inScope || node.constant; if (!inScope || node.constant) { arrayStack -= array.Size(); @@ -622,7 +629,7 @@ class BackendLua : CompilerBackend { variables ~= var; // create metadata variable - var.type = GetType("Array"); + var.type = UsedType(GetType("Array"), false); var.offset = 0; var.array = false; @@ -649,7 +656,7 @@ class BackendLua : CompilerBackend { override void CompileString(StringNode node) { auto arrayNode = new ArrayNode(node.error); - arrayNode.arrayType = "cell"; + arrayNode.arrayType = new TypeNode(node.error, "cell", false); arrayNode.constant = node.constant; foreach (ref ch ; node.value) { diff --git a/source/backends/rm86.d b/source/backends/rm86.d index eb57fb2..b08ae56 100644 --- a/source/backends/rm86.d +++ b/source/backends/rm86.d @@ -12,11 +12,11 @@ import callisto.compiler; import callisto.language; private struct Word { - bool raw; - bool inline; - Node[] inlineNodes; - bool error; - Type[] params; + bool raw; + bool inline; + Node[] inlineNodes; + bool error; + UsedType[] params; } private struct RM86Opts { @@ -47,9 +47,9 @@ class BackendRM86 : CompilerBackend { // built in structs types ~= Type("Array", 6, true, [ - StructEntry(GetType("usize"), "length"), - StructEntry(GetType("usize"), "memberSize"), - StructEntry(GetType("addr"), "elements") + StructEntry(UsedType(GetType("usize"), false), "length"), + StructEntry(UsedType(GetType("usize"), false), "memberSize"), + StructEntry(UsedType(GetType("addr"), false), "elements") ]); NewConst("Array.length", 0); NewConst("Array.memberSize", 2); @@ -57,8 +57,8 @@ class BackendRM86 : CompilerBackend { NewConst("Array.sizeof", 2 * 3); types ~= Type("Exception", 6 + 2, true, [ - StructEntry(GetType("bool"), "error"), - StructEntry(GetType("Array"), "msg") + StructEntry(UsedType(GetType("bool"), false), "error"), + StructEntry(UsedType(GetType("Array"), false), "msg") ]); NewConst("Exception.bool", 0); NewConst("Exception.msg", 2); @@ -68,7 +68,9 @@ class BackendRM86 : CompilerBackend { NewConst(format("%s.sizeof", type.name), cast(long) type.size); } - globals ~= Global("_cal_exception", GetType("Exception"), false, 0); + globals ~= Global( + "_cal_exception", UsedType(GetType("Exception"), false), false, 0 + ); } override void NewConst(string name, long value, ErrorInfo error = ErrorInfo.init) { @@ -372,14 +374,14 @@ class BackendRM86 : CompilerBackend { thisFunc = node.name; - Type[] params; + UsedType[] params; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - params ~= GetType(type); + params ~= UsedType(GetType(type.name), type.ptr); } if (node.inline) { @@ -407,10 +409,10 @@ class BackendRM86 : CompilerBackend { // allocate parameters size_t paramSize = node.params.length * 2; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - if (GetType(type).isStruct) { + if (GetType(type.name).isStruct && !type.ptr) { Error(node.error, "Structures cannot be used in function parameters"); } } @@ -426,7 +428,8 @@ class BackendRM86 : CompilerBackend { Variable var; var.name = param; - var.type = GetType(type); + var.type.type = GetType(type.name); + var.type.ptr = type.ptr; var.offset = cast(uint) offset; offset += var.Size(); variables ~= var; @@ -594,8 +597,8 @@ class BackendRM86 : CompilerBackend { } override void CompileLet(LetNode node) { - if (!TypeExists(node.varType)) { - Error(node.error, "Undefined type '%s'", node.varType); + if (!TypeExists(node.varType.name)) { + Error(node.error, "Undefined type '%s'", node.varType.name); } if (VariableExists(node.name) || (node.name in words)) { Error(node.error, "Variable name '%s' already used", node.name); @@ -607,7 +610,7 @@ class BackendRM86 : CompilerBackend { if (inScope) { Variable var; var.name = node.name; - var.type = GetType(node.varType); + var.type = UsedType(GetType(node.varType.name), node.varType.ptr); var.offset = 0; var.array = node.array; var.arraySize = node.arraySize; @@ -637,7 +640,7 @@ class BackendRM86 : CompilerBackend { } Global global; - global.type = GetType(node.varType); + global.type = UsedType(GetType(node.varType.name), node.varType.ptr); global.array = node.array; global.arraySize = node.arraySize; global.name = node.name; @@ -665,11 +668,11 @@ class BackendRM86 : CompilerBackend { } } - if (!TypeExists(node.arrayType)) { - Error(node.error, "Type '%s' doesn't exist", node.arrayType); + if (!TypeExists(node.arrayType.name)) { + Error(node.error, "Type '%s' doesn't exist", node.arrayType.name); } - array.type = GetType(node.arrayType); + array.type = UsedType(GetType(node.arrayType.name), node.arrayType.ptr); array.global = !inScope || node.constant; arrays ~= array; @@ -707,7 +710,7 @@ class BackendRM86 : CompilerBackend { variables ~= var; // create metadata variable - var.type = GetType("Array"); + var.type = UsedType(GetType("Array"), false); var.offset = 0; var.array = false; @@ -733,7 +736,7 @@ class BackendRM86 : CompilerBackend { override void CompileString(StringNode node) { auto arrayNode = new ArrayNode(node.error); - arrayNode.arrayType = "u8"; + arrayNode.arrayType = new TypeNode(node.error, "u8", false); arrayNode.constant = node.constant; foreach (ref ch ; node.value) { diff --git a/source/backends/uxn.d b/source/backends/uxn.d index 5905bf7..453848a 100644 --- a/source/backends/uxn.d +++ b/source/backends/uxn.d @@ -12,11 +12,11 @@ import callisto.compiler; import callisto.language; private struct Word { - bool raw; - bool inline; - Node[] inlineNodes; - bool error; - Type[] params; + bool raw; + bool inline; + Node[] inlineNodes; + bool error; + UsedType[] params; } class BackendUXN : CompilerBackend { @@ -40,9 +40,9 @@ class BackendUXN : CompilerBackend { // built in structs types ~= Type("Array", 6, true, [ - StructEntry(GetType("usize"), "length"), - StructEntry(GetType("usize"), "memberSize"), - StructEntry(GetType("addr"), "elements") + StructEntry(UsedType(GetType("usize"), false), "length"), + StructEntry(UsedType(GetType("usize"), false), "memberSize"), + StructEntry(UsedType(GetType("addr"), false), "elements") ]); NewConst("Array.length", 0); NewConst("Array.memberSize", 2); @@ -50,8 +50,8 @@ class BackendUXN : CompilerBackend { NewConst("Array.sizeof", 2 * 3); types ~= Type("Exception", 6 + 2, true, [ - StructEntry(GetType("bool"), "error"), - StructEntry(GetType("Array"), "msg") + StructEntry(UsedType(GetType("bool"), false), "error"), + StructEntry(UsedType(GetType("Array"), false), "msg") ]); NewConst("Exception.bool", 0); NewConst("Exception.msg", 2); @@ -61,7 +61,9 @@ class BackendUXN : CompilerBackend { NewConst(format("%s.sizeof", type.name), cast(long) type.size); } - globals ~= Global("_cal_exception", GetType("Exception"), false, 0); + globals ~= Global( + "_cal_exception", UsedType(GetType("Exception"), false), false, 0 + ); } override string[] GetVersions() => [ @@ -330,14 +332,14 @@ class BackendUXN : CompilerBackend { thisFunc = node.name; - Type[] params; + UsedType[] params; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - params ~= GetType(type); + params ~= UsedType(GetType(type.name), type.ptr); } if (node.inline) { @@ -365,10 +367,10 @@ class BackendUXN : CompilerBackend { // allocate parameters size_t paramSize = node.params.length * 2; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - if (GetType(type).isStruct) { + if (GetType(type.name).isStruct && !type.ptr) { Error(node.error, "Structures cannot be used in function parameters"); } } @@ -384,7 +386,7 @@ class BackendUXN : CompilerBackend { Variable var; var.name = param; - var.type = GetType(type); + var.type = UsedType(GetType(type.name), type.ptr); var.offset = cast(uint) offset; offset += var.Size(); variables ~= var; @@ -548,8 +550,8 @@ class BackendUXN : CompilerBackend { } override void CompileLet(LetNode node) { - if (!TypeExists(node.varType)) { - Error(node.error, "Undefined type '%s'", node.varType); + if (!TypeExists(node.varType.name)) { + Error(node.error, "Undefined type '%s'", node.varType.name); } if (VariableExists(node.name) || (node.name in words)) { Error(node.error, "Variable name '%s' already used", node.name); @@ -561,7 +563,7 @@ class BackendUXN : CompilerBackend { if (inScope) { Variable var; var.name = node.name; - var.type = GetType(node.varType); + var.type = UsedType(GetType(node.varType.name), node.varType.ptr); var.offset = 0; var.array = node.array; var.arraySize = node.arraySize; @@ -587,7 +589,7 @@ class BackendUXN : CompilerBackend { } else { Global global; - global.type = GetType(node.varType); + global.type = UsedType(GetType(node.varType.name), node.varType.ptr); global.array = node.array; global.arraySize = node.arraySize; global.name = node.name; @@ -598,11 +600,11 @@ class BackendUXN : CompilerBackend { override void CompileArray(ArrayNode node) { Array array; - if (!TypeExists(node.arrayType)) { - Error(node.error, "Type '%s' doesn't exist", node.arrayType); + if (!TypeExists(node.arrayType.name)) { + Error(node.error, "Type '%s' doesn't exist", node.arrayType.name); } - array.type = GetType(node.arrayType); + array.type = UsedType(GetType(node.arrayType.name), node.arrayType.ptr); foreach (ref elem ; node.elements) { switch (elem.type) { @@ -618,6 +620,7 @@ class BackendUXN : CompilerBackend { } default: { Error(elem.error, "Type '%s' can't be used in array literal"); + // TODO: orphan format specifier } } } @@ -652,7 +655,7 @@ class BackendUXN : CompilerBackend { variables ~= var; // create metadata variable - var.type = GetType("Array"); + var.type = UsedType(GetType("Array"), false); var.offset = 0; var.array = false; @@ -681,7 +684,7 @@ class BackendUXN : CompilerBackend { override void CompileString(StringNode node) { auto arrayNode = new ArrayNode(node.error); - arrayNode.arrayType = "u8"; + arrayNode.arrayType = new TypeNode(node.error, "u8", false); arrayNode.constant = node.constant; foreach (ref ch ; node.value) { diff --git a/source/backends/x86_64.d b/source/backends/x86_64.d index 2e4f578..fe0e074 100644 --- a/source/backends/x86_64.d +++ b/source/backends/x86_64.d @@ -20,16 +20,16 @@ private enum WordType { } private struct Word { - WordType type; - bool inline; - Node[] inlineNodes; - bool error; - Type[] params; + WordType type; + bool inline; + Node[] inlineNodes; + bool error; + UsedType[] params; // for C words - Type ret; - bool isVoid; - string symbolName; + UsedType ret; + bool isVoid; + string symbolName; } class BackendX86_64 : CompilerBackend { @@ -42,6 +42,8 @@ class BackendX86_64 : CompilerBackend { bool useLibc; this() { + addrSize = 8; + version (linux) { defaultOS = "linux"; } @@ -73,9 +75,9 @@ class BackendX86_64 : CompilerBackend { // built in structs types ~= Type("Array", 24, true, [ - StructEntry(GetType("usize"), "length"), - StructEntry(GetType("usize"), "memberSize"), - StructEntry(GetType("addr"), "elements") + StructEntry(UsedType(GetType("usize"), false), "length"), + StructEntry(UsedType(GetType("usize"), false), "memberSize"), + StructEntry(UsedType(GetType("addr"), false), "elements") ]); NewConst("Array.length", 0); NewConst("Array.memberSize", 8); @@ -83,8 +85,8 @@ class BackendX86_64 : CompilerBackend { NewConst("Array.sizeof", 8 * 3); types ~= Type("Exception", 24 + 8, true, [ - StructEntry(GetType("bool"), "error"), - StructEntry(GetType("Array"), "msg") + StructEntry(UsedType(GetType("bool"), false), "error"), + StructEntry(UsedType(GetType("Array"), false), "msg") ]); NewConst("Exception.error", 0); NewConst("Exception.msg", 8); @@ -94,7 +96,9 @@ class BackendX86_64 : CompilerBackend { NewConst(format("%s.sizeof", type.name), cast(long) type.size); } - globals ~= Global("_cal_exception", GetType("Exception"), false, 0); + globals ~= Global( + "_cal_exception", UsedType(GetType("Exception"), false), false, 0 + ); } override void NewConst(string name, long value, ErrorInfo error = ErrorInfo.init) { @@ -643,14 +647,14 @@ class BackendX86_64 : CompilerBackend { thisFunc = node.name; - Type[] params; + UsedType[] params; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - params ~= GetType(type); + params ~= UsedType(GetType(type.name), type.ptr); } if (node.inline) { @@ -689,10 +693,10 @@ class BackendX86_64 : CompilerBackend { // allocate parameters size_t paramSize = node.params.length * 8; foreach (ref type ; node.paramTypes) { - if (!TypeExists(type)) { - Error(node.error, "Type '%s' doesn't exist", type); + if (!TypeExists(type.name)) { + Error(node.error, "Type '%s' doesn't exist", type.name); } - if (GetType(type).isStruct) { + if (GetType(type.name).isStruct && !type.ptr) { Error(node.error, "Structures cannot be used in function parameters"); } } @@ -708,7 +712,8 @@ class BackendX86_64 : CompilerBackend { Variable var; var.name = param; - var.type = GetType(type); + var.type.type = GetType(type.name); + var.type.ptr = type.ptr; var.offset = cast(uint) offset; offset += var.Size(); variables ~= var; @@ -884,8 +889,8 @@ class BackendX86_64 : CompilerBackend { } override void CompileLet(LetNode node) { - if (!TypeExists(node.varType)) { - Error(node.error, "Undefined type '%s'", node.varType); + if (!TypeExists(node.varType.name)) { + Error(node.error, "Undefined type '%s'", node.varType.name); } if (VariableExists(node.name) || (node.name in words)) { Error(node.error, "Variable name '%s' already used", node.name); @@ -897,7 +902,8 @@ class BackendX86_64 : CompilerBackend { if (inScope) { Variable var; var.name = node.name; - var.type = GetType(node.varType); + var.type.type = GetType(node.varType.name); + var.type.ptr = node.varType.ptr; var.offset = 0; var.array = node.array; var.arraySize = node.arraySize; @@ -927,7 +933,8 @@ class BackendX86_64 : CompilerBackend { } Global global; - global.type = GetType(node.varType); + global.type.type = GetType(node.varType.name); + global.type.ptr = node.varType.ptr; global.array = node.array; global.arraySize = node.arraySize; global.name = node.name; @@ -951,13 +958,14 @@ class BackendX86_64 : CompilerBackend { } } - if (!TypeExists(node.arrayType)) { - Error(node.error, "Type '%s' doesn't exist", node.arrayType); + if (!TypeExists(node.arrayType.name)) { + Error(node.error, "Type '%s' doesn't exist", node.arrayType.name); } - array.type = GetType(node.arrayType); - array.global = !inScope || node.constant; - arrays ~= array; + array.type.type = GetType(node.arrayType.name); + array.type.ptr = node.arrayType.ptr; + array.global = !inScope || node.constant; + arrays ~= array; if (!inScope || node.constant) { output ~= format("mov rax, __array_%d_meta\n", arrays.length - 1); @@ -986,7 +994,7 @@ class BackendX86_64 : CompilerBackend { variables ~= var; // create metadata variable - var.type = GetType("Array"); + var.type = UsedType(GetType("Array"), false); var.offset = 0; var.array = false; @@ -1011,7 +1019,7 @@ class BackendX86_64 : CompilerBackend { override void CompileString(StringNode node) { auto arrayNode = new ArrayNode(node.error); - arrayNode.arrayType = "u8"; + arrayNode.arrayType = new TypeNode(node.error, "u8", false); arrayNode.constant = node.constant; foreach (ref ch ; node.value) { @@ -1075,22 +1083,22 @@ class BackendX86_64 : CompilerBackend { word.type = WordType.C; foreach (ref param ; node.types) { - if (!TypeExists(param)) { - Error(node.error, "Unknown type '%s'", param); + if (!TypeExists(param.name)) { + Error(node.error, "Unknown type '%s'", param.name); } - word.params ~= GetType(param); + word.params ~= UsedType(GetType(param.name), param.ptr); } - if (node.retType == "void") { + if ((node.retType.name == "void") && !node.retType.ptr) { word.isVoid = true; } else { - if (!TypeExists(node.retType)) { - Error(node.error, "Unknown type '%s'", node.retType); + if (!TypeExists(node.retType.name)) { + Error(node.error, "Unknown type '%s'", node.retType.name); } - word.ret = GetType(node.retType); + word.ret = UsedType(GetType(node.retType.name), node.retType.ptr); } word.symbolName = node.func; diff --git a/source/compiler.d b/source/compiler.d index e20c1f4..b440f02 100644 --- a/source/compiler.d +++ b/source/compiler.d @@ -11,12 +11,14 @@ import callisto.error; import callisto.parser; import callisto.language; +ubyte addrSize; // in bytes, set by backend + struct StructEntry { - Type type; - string name; - bool array; - size_t size; - size_t offset; + UsedType type; + string name; + bool array; + size_t size; + size_t offset; } struct StructVariable { @@ -33,24 +35,33 @@ struct Type { bool hasDeinit; } +struct UsedType { + Type type; + bool ptr; + + alias type this; + + size_t Size() => ptr? addrSize : type.size; +} + struct Variable { - string name; - Type type; - uint offset; // SP + offset to access - bool array; - ulong arraySize; + string name; + UsedType type; + uint offset; // SP + offset to access + bool array; + ulong arraySize; - size_t Size() => array? arraySize * type.size : type.size; + size_t Size() => array? arraySize * type.Size() : type.Size(); } struct Global { - string name; - Type type; - bool array; - ulong arraySize; - void* extra; + string name; + UsedType type; + bool array; + ulong arraySize; + void* extra; - size_t Size() => array? arraySize * type.size : type.size; + size_t Size() => array? arraySize * type.Size() : type.Size(); } struct Constant { @@ -59,11 +70,11 @@ struct Constant { struct Array { string[] values; - Type type; + UsedType type; bool global; void* extra; - size_t Size() => type.size * values.length; + size_t Size() => type.Size() * values.length; } class CompilerBackend { @@ -140,15 +151,18 @@ class CompilerBackend { } foreach (ref member ; node.members) { - if (!TypeExists(member.type)) { - Error(node.error, "Type '%s' doesn't exist", member.type); + if (!TypeExists(member.type.name)) { + Error(node.error, "Type '%s' doesn't exist", member.type.name); } if (members.canFind(member.name)) { Error(node.error, "Duplicate member '%s'", member.name); } + UsedType memberType = UsedType(GetType(member.type.name), member.type.ptr); + memberType.ptr = member.type.ptr; + auto newMember = StructEntry( - GetType(member.type), member.name, member.array, member.size, offset + memberType, member.name, member.array, member.size, offset ); entries ~= newMember; members ~= member.name; @@ -161,7 +175,7 @@ class CompilerBackend { NewConst(format("%s.%s", node.name, member.name), member.offset); } - NewConst(format("%s.sizeof", node.name), offset); + NewConst(format("%s.sizeOf", node.name), offset); types ~= Type(node.name, offset, true, entries); } @@ -183,7 +197,7 @@ class CompilerBackend { NewConst(format("%s.min", node.name), node.values.minElement()); NewConst(format("%s.max", node.name), node.values.maxElement()); - NewConst(format("%s.sizeof", node.name), GetType(node.name).size); + NewConst(format("%s.sizeOf", node.name), GetType(node.name).size); } void CompileConst(ConstNode node) { @@ -505,6 +519,7 @@ class Compiler { void Compile(Node[] nodes) { assert(backend !is null); + assert(addrSize != 0); backend.compiler = this; backend.Init(); diff --git a/source/parser.d b/source/parser.d index 8e2d463..e8d1ddd 100644 --- a/source/parser.d +++ b/source/parser.d @@ -10,6 +10,7 @@ import callisto.lexer; enum NodeType { Null, + Type, Word, Integer, FuncDef, @@ -34,8 +35,7 @@ enum NodeType { Implement, Set, TryCatch, - Unsafe, - Type + Unsafe } class Node { @@ -47,6 +47,25 @@ class Node { } } +class TypeNode : Node { + string name; + bool ptr; + + this(ErrorInfo perror) { + type = NodeType.Type; + error = perror; + } + + this(ErrorInfo perror, string pname, bool pptr) { + type = NodeType.Type; + name = pname; + ptr = pptr; + error = perror; + } + + override string toString() => format("%s%s", ptr? "ptr " : "", name); +} + class WordNode : Node { string name; @@ -82,16 +101,16 @@ class IntegerNode : Node { } class FuncDefNode : Node { - string name; - Node[] nodes; - bool inline; - bool raw; - string[] paramTypes; - string[] params; - bool errors; - bool manual; - bool unsafe; - string[] returnTypes; + string name; + Node[] nodes; + bool inline; + bool raw; + TypeNode[] paramTypes; + string[] params; + bool errors; + bool manual; + bool unsafe; + TypeNode[] returnTypes; this(ErrorInfo perror) { type = NodeType.FuncDef; @@ -217,10 +236,10 @@ class WhileNode : Node { } class LetNode : Node { - string varType; - string name; - bool array; - size_t arraySize; + TypeNode varType; + string name; + bool array; + size_t arraySize; this(ErrorInfo perror) { type = NodeType.Let; @@ -276,9 +295,9 @@ class VersionNode : Node { } class ArrayNode : Node { - string arrayType; - Node[] elements; - bool constant; + TypeNode arrayType; + Node[] elements; + bool constant; this(ErrorInfo perror) { type = NodeType.Array; @@ -309,10 +328,10 @@ class StringNode : Node { } struct StructMember { - string type; - string name; - bool array; - size_t size; + TypeNode type; + string name; + bool array; + size_t size; string toString() { return array? @@ -435,8 +454,8 @@ class ExternNode : Node { string asName; // for C extern - string[] types; - string retType; + TypeNode[] types; + TypeNode retType; this(ErrorInfo perror) { type = NodeType.Extern; @@ -544,18 +563,6 @@ class UnsafeNode : Node { } } -class TypeNode : Node { - string typeName; - bool ptr; - - this(ErrorInfo perror) { - type = NodeType.Type; - error = perror; - } - - override string toString() => format("%s%s", ptr? "ptr " : "", type); -} - class ParserError : Exception { this() { super("", "", 0); @@ -612,6 +619,24 @@ class Parser { (tokens[i].contents == identifier); } + Node ParseType() { + auto ret = new TypeNode(GetError()); + Expect(TokenType.Identifier); + + if (IsIdentifier("ptr")) { + ret.ptr = true; + + Next(); + Expect(TokenType.Identifier); + ret.name = tokens[i].contents; + } + else { + ret.name = tokens[i].contents; + } + + return ret; + } + Node ParseFuncDef(bool inline) { auto ret = new FuncDefNode(GetError()); ret.inline = inline; @@ -636,8 +661,7 @@ class Parser { Next(); while (!IsIdentifier("begin") && !IsIdentifier("->")) { - Expect(TokenType.Identifier); - ret.paramTypes ~= tokens[i].contents; + ret.paramTypes ~= cast(TypeNode) ParseType(); Next(); Expect(TokenType.Identifier); ret.params ~= tokens[i].contents; @@ -648,8 +672,7 @@ class Parser { Next(); while (!IsIdentifier("begin")) { - Expect(TokenType.Identifier); - ret.returnTypes ~= tokens[i].contents; // return type + ret.returnTypes ~= cast(TypeNode) ParseType(); // return type Next(); Expect(TokenType.Identifier); // return name, ignored @@ -848,7 +871,7 @@ class Parser { Expect(TokenType.Identifier); } - ret.varType = tokens[i].contents; + ret.varType = cast(TypeNode) ParseType(); Next(); Expect(TokenType.Identifier); ret.name = tokens[i].contents; @@ -899,7 +922,7 @@ class Parser { Next(); Expect(TokenType.Identifier); - ret.arrayType = tokens[i].contents; + ret.arrayType = cast(TypeNode) ParseType(); Next(); while (tokens[i].type != TokenType.RSquare) { @@ -976,7 +999,7 @@ class Parser { Expect(TokenType.Identifier); } - member.type = tokens[i].contents; + member.type = cast(TypeNode) ParseType(); Next(); Expect(TokenType.Identifier); member.name = tokens[i].contents; @@ -1155,7 +1178,7 @@ class Parser { Next(); Expect(TokenType.Identifier); - ret.retType = tokens[i].contents; + ret.retType = cast(TypeNode) ParseType(); Next(); Expect(TokenType.Identifier); @@ -1176,7 +1199,7 @@ class Parser { break; } - ret.types ~= tokens[i].contents; + ret.types ~= cast(TypeNode) ParseType(); } } else { @@ -1304,24 +1327,6 @@ class Parser { return ret; } - Node ParseType() { - auto ret = new TypeNode(GetError()); - Expect(TokenType.Identifier); - - if (IsIdentifier("ptr")) { - ret.ptr = true; - - Next(); - Expect(TokenType.Identifier); - ret.typeName = tokens[i].contents; - } - else { - ret.typeName = tokens[i].contents; - } - - return ret; - } - Node ParseStatement() { switch (tokens[i].type) { case TokenType.Integer: { diff --git a/source/stackCheck.d b/source/stackCheck.d index aba429d..482b29d 100644 --- a/source/stackCheck.d +++ b/source/stackCheck.d @@ -298,7 +298,10 @@ class StackChecker { if (node.externType == ExternType.C) { words[name] = Word( - false, Effect(node.retType == "void"? 0 : 1, node.types.length) + false, Effect( + ((node.retType.name == "void") && !node.retType.ptr)? 0 : 1, + node.types.length + ) ); } else { From 5cf3784f36e67753a8fa59eac3bf026675e705d6 Mon Sep 17 00:00:00 2001 From: MESYETI Date: Thu, 5 Dec 2024 12:29:06 +0000 Subject: [PATCH 3/7] x86_64 --- source/backends/x86_64.d | 191 +++++++++++++++++++++++++-------------- source/stackCheck.d | 5 +- 2 files changed, 128 insertions(+), 68 deletions(-) diff --git a/source/backends/x86_64.d b/source/backends/x86_64.d index fe0e074..826fb60 100644 --- a/source/backends/x86_64.d +++ b/source/backends/x86_64.d @@ -407,64 +407,77 @@ class BackendX86_64 : CompilerBackend { } } - void PushGlobalValue(Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false) { + void PushGlobalValue( + Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } if (size != 8) { output ~= "xor rax, rax\n"; } - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); - } - string symbol = format("__global_%s", var.name.Sanitise()); - switch (size) { - case 1: output ~= format("mov al, [%s", symbol); break; - case 2: output ~= format("mov ax, [%s", symbol); break; - case 4: output ~= format("mov eax, [%s", symbol); break; - case 8: output ~= format("mov rax, [%s", symbol); break; - default: Error(node.error, "Bad variable type size"); - } + if (deref) { + output ~= format("mov rbx, [%s]\n", symbol); - if (offset == 0) output ~= "]\n"; - else output ~= format(" + %d]\n", offset); + switch (size) { + case 1: output ~= format("mov al, [rbx + %d]\n", offset); break; + case 2: output ~= format("mov ax, [rbx + %d]\n", offset); break; + case 4: output ~= format("mov eax, [rbx + %d]\n", offset); break; + case 8: output ~= format("mov rax, [rbx + %d]\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov al, [%s + %d]\n", symbol, offset); break; + case 2: output ~= format("mov ax, [%s + %d]\n", symbol, offset); break; + case 4: output ~= format("mov eax, [%s + %d]\n", symbol, offset); break; + case 8: output ~= format("mov rax, [%s + %d]\n", symbol, offset); break; + default: Error(node.error, "Bad variable type size"); + } + } output ~= "mov [r15], rax\n"; output ~= "add r15, 8\n"; } - void PushVariableValue(Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false) { + void PushVariableValue( + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = var.type.size; - } - - output ~= "mov rdi, rsp\n"; - if (var.offset > 0) { - output ~= format("add rdi, %d\n", var.offset); - } - - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + size = var.type.Size(); } if (size != 8) { output ~= "xor rax, rax\n"; } - switch (size) { - case 1: output ~= format("mov al, [rdi"); break; - case 2: output ~= format("mov ax, [rdi"); break; - case 4: output ~= format("mov eax, [rdi"); break; - case 8: output ~= format("mov rax, [rdi"); break; - default: Error(node.error, "Bad variable type size"); - } + if (deref) { + output ~= format("mov rbx, [rsp + %d]\n", var.offset); - if (offset == 0) output ~= "]\n"; - else output ~= format(" + %d]\n", offset); + switch (size) { + case 1: output ~= format("mov al, [rbx + %d]\n", offset); break; + case 2: output ~= format("mov ax, [rbx + %d]\n", offset); break; + case 4: output ~= format("mov eax, [rbx + %d]\n", offset); break; + case 8: output ~= format("mov rax, [rbx + %d]\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov al, [rsp + %d]\n", offset + var.offset); break; + case 2: output ~= format("mov ax, [rsp + %d]\n", offset + var.offset); break; + case 4: output ~= format("mov eax, [rsp + %d]\n", offset + var.offset); break; + case 8: output ~= format("mov rax, [rsp + %d]\n", offset + var.offset); break; + default: Error(node.error, "Bad variable type size"); + } + } output ~= "mov [r15], rax\n"; output ~= "add r15, 8\n"; @@ -609,10 +622,18 @@ class BackendX86_64 : CompilerBackend { auto structVar = GetStructVariable(node, node.name); if (GlobalExists(name)) { - PushGlobalValue(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + PushGlobalValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (VariableExists(name)) { - PushVariableValue(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + PushVariableValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else if (node.name in consts) { @@ -1247,63 +1268,91 @@ class BackendX86_64 : CompilerBackend { variables = []; } - void SetVariable(Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false) { + void SetVariable( + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } output ~= "sub r15, 8\n"; output ~= "mov rax, [r15]\n"; - if (var.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); - } + if (deref) { + output ~= format("mov rbx, [rsp + %d]\n", var.offset); - switch (size) { - case 1: output ~= format("mov [rsp + %d], al\n", var.offset + offset); break; - case 2: output ~= format("mov [rsp + %d], ax\n", var.offset + offset); break; - case 4: output ~= format("mov [rsp + %d], eax\n", var.offset + offset); break; - case 8: output ~= format("mov [rsp + %d], rax\n", var.offset + offset); break; - default: Error(node.error, "Bad variable type size"); + switch (size) { + case 1: output ~= format("mov [rbx + %d], al\n", offset); break; + case 2: output ~= format("mov [rbx + %d], ax\n", offset); break; + case 4: output ~= format("mov [rbx + %d], eax\n", offset); break; + case 8: output ~= format("mov [rbx + %d], rax\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov [rsp + %d], al\n", var.offset + offset); break; + case 2: output ~= format("mov [rsp + %d], ax\n", var.offset + offset); break; + case 4: output ~= format("mov [rsp + %d], eax\n", var.offset + offset); break; + case 8: output ~= format("mov [rsp + %d], rax\n", var.offset + offset); break; + default: Error(node.error, "Bad variable type size"); + } } } void SetGlobal( Node node, Global global, size_t size = 0, size_t offset = 0, - bool member = false + bool member = false, bool deref = false ) { if (size == 0) { - size = global.type.size; + size = global.type.Size(); } output ~= "sub r15, 8\n"; output ~= "mov rax, [r15]\n"; - if (global.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); - } - string symbol = format("__global_%s", global.name.Sanitise()); - if (size != 8) { - output ~= "xor rbx, rbx\n"; - output ~= format("mov [%s + %d], rbx\n", symbol, offset); - } + if (deref) { + output ~= format("mov rbx, [%s]\n", symbol); - switch (size) { - case 1: output ~= format("mov [%s + %d], al\n", symbol, offset); break; - case 2: output ~= format("mov [%s + %d], ax\n", symbol, offset); break; - case 4: output ~= format("mov [%s + %d], eax\n", symbol, offset); break; - case 8: output ~= format("mov [%s + %d], rax\n", symbol, offset); break; - default: Error(node.error, "Bad variable type size"); + switch (size) { + case 1: output ~= format("mov [rbx + %d], al\n", offset); break; + case 2: output ~= format("mov [rbx + %d], ax\n", offset); break; + case 4: output ~= format("mov [rbx + %d], eax\n", offset); break; + case 8: output ~= format("mov [rbx + %d], rax\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov [%s + %d], al\n", symbol, offset); break; + case 2: output ~= format("mov [%s + %d], ax\n", symbol, offset); break; + case 4: output ~= format("mov [%s + %d], eax\n", symbol, offset); break; + case 8: output ~= format("mov [%s + %d], rax\n", symbol, offset); break; + default: Error(node.error, "Bad variable type size"); + } } } override void CompileSet(SetNode node) { if (VariableExists(node.var)) { - SetVariable(node, GetVariable(node.var)); + auto var = GetVariable(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + + SetVariable(node, var); } else if (GlobalExists(node.var)) { + auto var = GetGlobal(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + SetGlobal(node, GetGlobal(node.var)); } else if (IsStructMember(node.var)) { @@ -1311,10 +1360,18 @@ class BackendX86_64 : CompilerBackend { auto structVar = GetStructVariable(node, node.var); if (VariableExists(name)) { - SetVariable(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + SetVariable( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (GlobalExists(name)) { - SetGlobal(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + SetGlobal( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else { diff --git a/source/stackCheck.d b/source/stackCheck.d index 482b29d..06b88b7 100644 --- a/source/stackCheck.d +++ b/source/stackCheck.d @@ -118,7 +118,10 @@ class StackChecker { Pop(node, word.effect.pop); Push(node, word.effect.push); } - else if (identifiers.canFind(node.name)) { + else if ( + identifiers.canFind(node.name) || + identifiers.canFind(node.name.split('.')[0]) + ) { Push(node, 1); } else { From a3d9bfeaad05805a9b5028f8894dfe6c66a1ee5f Mon Sep 17 00:00:00 2001 From: MESYETI Date: Thu, 5 Dec 2024 12:58:28 +0000 Subject: [PATCH 4/7] rm86 --- source/backends/rm86.d | 171 +++++++++++++++++++++++++++-------------- 1 file changed, 115 insertions(+), 56 deletions(-) diff --git a/source/backends/rm86.d b/source/backends/rm86.d index b08ae56..2b35e19 100644 --- a/source/backends/rm86.d +++ b/source/backends/rm86.d @@ -33,6 +33,7 @@ class BackendRM86 : CompilerBackend { RM86Opts opts; this() { + addrSize = 2; defaultOS = "dos"; types ~= Type("u8", 1); @@ -217,53 +218,70 @@ class BackendRM86 : CompilerBackend { output ~= "__stack: times 512 dw 0\n"; } - void PushVariableValue(Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false) { + void PushVariableValue( + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = var.type.size; - } - - output ~= "mov di, sp\n"; - if (var.offset > 0) { - output ~= format("add di, %d\n", var.offset + offset); - } - - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + size = var.type.Size(); } if (size != 2) { output ~= "xor ax, ax\n"; } - switch (size) { - case 1: output ~= format("mov al, [di]\n"); break; - case 2: output ~= format("mov ax, [di]\n"); break; - default: Error(node.error, "Bad variable type size"); + output ~= "mov di, sp\n"; + + if (deref) { + output ~= format("mov bx, [di + %d]\n", var.offset); + + switch (size) { + case 1: output ~= format("mov al, [bx + %d]\n", offset); break; + case 2: output ~= format("mov ax, [bx + %d]\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov al, [di + %d]\n", var.offset + offset); break; + case 2: output ~= format("mov ax, [di + %d]\n", var.offset + offset); break; + default: Error(node.error, "Bad variable type size"); + } } output ~= "mov [si], ax\n"; output ~= "add si, 2\n"; } - void PushGlobalValue(Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false) { + void PushGlobalValue( + Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } if (size != 2) { output ~= "xor ax, ax\n"; } - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); - } - string symbol = format("__global_%s", var.name.Sanitise()); - switch (size) { - case 1: output ~= format("mov al, [%s + %d]\n", symbol, offset); break; - case 2: output ~= format("mov ax, [%s + %d]\n", symbol, offset); break; - default: Error(node.error, "Bad variable type size"); + if (deref) { + output ~= format("mov bx, [%s]\n", symbol); + + switch (size) { + case 1: output ~= format("mov al, [bx + %d]\n", offset); break; + case 2: output ~= format("mov ax, [bx + %d]\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov al, [%s + %d]\n", symbol, offset); break; + case 2: output ~= format("mov ax, [%s + %d]\n", symbol, offset); break; + default: Error(node.error, "Bad variable type size"); + } } output ~= "mov [si], ax\n"; @@ -342,10 +360,18 @@ class BackendRM86 : CompilerBackend { auto structVar = GetStructVariable(node, node.name); if (GlobalExists(name)) { - PushGlobalValue(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + PushGlobalValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (VariableExists(name)) { - PushVariableValue(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + PushVariableValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else if (node.name in consts) { @@ -927,46 +953,59 @@ class BackendRM86 : CompilerBackend { variables = []; } - void SetVariable(Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false) { + void SetVariable( + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = var.type.size; - } - - if (var.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + size = var.type.Size(); } - output ~= "mov bx, sp\n"; + output ~= "mov di, sp\n"; - string addr = var.offset == 0? "bx" : format("bx + %d", var.offset); + if (deref) { + output ~= format("mov bx, [di + %d]\n", var.offset); - switch (size) { - case 1: output ~= format("mov [%s], al\n", addr); break; - case 2: output ~= format("mov [%s], ax\n", addr); break; - default: Error(node.error, "Bad variable type size"); + switch (size) { + case 1: output ~= format("mov [bx + %d], al\n", offset); break; + case 2: output ~= format("mov [bx + %d], ax\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov [di + %d], al\n", var.offset + offset); break; + case 2: output ~= format("mov [di + %d], ax\n", var.offset + offset); break; + default: Error(node.error, "Bad variable type size"); + } } } - void SetGlobal(Node node, Global global, size_t size = 0, size_t offset = 0, bool member = false) { + void SetGlobal( + Node node, Global global, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false + ) { if (size == 0) { - size = global.type.size; - } - - if (global.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + size = global.type.Size(); } string symbol = format("__global_%s", global.name.Sanitise()); - if (size != 2) { - output ~= "xor bx, bx\n"; - output ~= format("mov [%s], bx\n", symbol); - } + if (deref) { + output ~= format("mov bx, [%s]\n", symbol); - switch (size) { - case 1: output ~= format("mov [%s], al\n", symbol); break; - case 2: output ~= format("mov [%s], ax\n", symbol); break; - default: Error(node.error, "Bad variable type size"); + switch (size) { + case 1: output ~= format("mov [bx + %d], al\n", offset); break; + case 2: output ~= format("mov [bx + %d], ax\n", offset); break; + default: Error(node.error, "Bad variable type size"); + } + } + else { + switch (size) { + case 1: output ~= format("mov [%s], al\n", symbol); break; + case 2: output ~= format("mov [%s], ax\n", symbol); break; + default: Error(node.error, "Bad variable type size"); + } } } @@ -975,9 +1014,21 @@ class BackendRM86 : CompilerBackend { output ~= "mov ax, [si]\n"; if (VariableExists(node.var)) { - SetVariable(node, GetVariable(node.var)); + auto var = GetVariable(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + + SetVariable(node, var); } else if (GlobalExists(node.var)) { + auto var = GetGlobal(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + SetGlobal(node, GetGlobal(node.var)); } else if (IsStructMember(node.var)) { @@ -985,10 +1036,18 @@ class BackendRM86 : CompilerBackend { auto structVar = GetStructVariable(node, node.var); if (VariableExists(name)) { - SetVariable(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + SetVariable( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (GlobalExists(name)) { - SetGlobal(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + SetGlobal( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else { From 0cbeba8daceae71fe81ef740ac63aa3a32336b9d Mon Sep 17 00:00:00 2001 From: MESYETI Date: Thu, 5 Dec 2024 18:09:47 +0000 Subject: [PATCH 5/7] lua + fixes across all backends --- examples/tak.cal | 2 +- source/backends/lua.d | 124 +++++++++++++++++++++++++++++---------- source/backends/rm86.d | 12 ++++ source/backends/x86_64.d | 13 +++- 4 files changed, 117 insertions(+), 34 deletions(-) diff --git a/examples/tak.cal b/examples/tak.cal index 2529068..c23c9e0 100644 --- a/examples/tak.cal +++ b/examples/tak.cal @@ -12,4 +12,4 @@ func tak cell x cell y cell z -> cell res begin end end -7 4 8 tak printdec 10 printch +48 20 12 tak printdec 10 printch diff --git a/source/backends/lua.d b/source/backends/lua.d index e6d714d..549fcfa 100644 --- a/source/backends/lua.d +++ b/source/backends/lua.d @@ -47,6 +47,8 @@ class BackendLua : CompilerBackend { ulong arrayStack = 524287; this() { + addrSize = 1; + // built in integer types types ~= Type("addr", 1); types ~= Type("size", 1); @@ -168,42 +170,45 @@ class BackendLua : CompilerBackend { void PushVariableValue( Node node, Variable var, size_t size = 0, size_t offset = 0, - bool member = false + bool member = false, bool deref = false ) { if (size == 0) { - size = var.type.size; - } - - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + size = var.type.Size(); } if (size != 1) { - Error(node.error, "Bad variable type size"); + Error(node.error, "Bad variable type size (%d)", size); } - output ~= format("mem[dsp] = mem[vsp + %d]\n", var.offset); + if (deref) { + output ~= format("mem[dsp] = mem[mem[vsp + %d] + %d]\n", var.offset, offset); + } + else { + output ~= format("mem[dsp] = mem[vsp + %d]\n", var.offset + offset); + } output ~= "dsp = dsp + 1\n"; } void PushGlobalValue( - Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false + Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } auto extra = cast(GlobalExtra*) var.extra; - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + if (size != 1) { + Error(node.error, "Bad variable type size (%d)", size); } - if (var.type.size != 1) { - Error(node.error, "Bad variable type size"); + if (deref) { + output ~= format("mem[dsp] = mem[mem[%d] + %d]\n", extra.addr, offset); + } + else { + output ~= format("mem[dsp] = mem[%d]\n", extra.addr + offset); } - - output ~= format("mem[dsp] = mem[%d]\n", extra.addr); output ~= "dsp = dsp + 1\n"; } @@ -245,9 +250,21 @@ class BackendLua : CompilerBackend { } } else if (VariableExists(node.name)) { + auto var = GetVariable(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushVariableValue(node, GetVariable(node.name)); } else if (GlobalExists(node.name)) { + auto var = GetGlobal(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushGlobalValue(node, GetGlobal(node.name)); } else if (IsStructMember(node.name)) { @@ -255,10 +272,18 @@ class BackendLua : CompilerBackend { auto structVar = GetStructVariable(node, node.name); if (GlobalExists(name)) { - PushGlobalValue(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + PushGlobalValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (VariableExists(name)) { - PushVariableValue(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + PushVariableValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else if (node.name in consts) { @@ -821,36 +846,63 @@ class BackendLua : CompilerBackend { void SetGlobal( Node node, Global global, size_t size = 0, size_t offset = 0, - bool member = false + bool member = false, bool deref = false ) { if (size == 0) { - size = global.type.size; + size = global.type.Size(); } - auto extra = cast(GlobalExtra*) global.extra; - - if (global.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + if (size != 1) { + Error(node.error, "Bad variable type size"); } - output ~= format("mem[%d] = cal_pop()\n", extra.addr); + auto extra = cast(GlobalExtra*) global.extra; + + if (deref) { + output ~= format("mem[mem[%d] + %d] = cal_pop()\n", extra.addr, offset); + } + else { + output ~= format("mem[%d] = cal_pop()\n", extra.addr + offset); + } } void SetVariable( - Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false ) { - if (var.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + if (size == 0) { + size = var.type.Size(); + } + + if (size != 1) { + Error(node.error, "Bad variable type size"); } - output ~= format("mem[vsp + %d] = cal_pop()\n", var.offset); + if (deref) { + output ~= format("mem[mem[vsp + %d] + %d] = cal_pop()\n", var.offset, offset); + } + else { + output ~= format("mem[vsp + %d] = cal_pop()\n", var.offset + offset); + } } override void CompileSet(SetNode node) { if (VariableExists(node.var)) { - SetVariable(node, GetVariable(node.var)); + auto var = GetVariable(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + + SetVariable(node, var); } else if (GlobalExists(node.var)) { + auto var = GetGlobal(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + SetGlobal(node, GetGlobal(node.var)); } else if (IsStructMember(node.var)) { @@ -858,10 +910,18 @@ class BackendLua : CompilerBackend { auto structVar = GetStructVariable(node, node.var); if (VariableExists(name)) { - SetVariable(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + SetVariable( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (GlobalExists(name)) { - SetGlobal(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + SetGlobal( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else { diff --git a/source/backends/rm86.d b/source/backends/rm86.d index 2b35e19..932bb59 100644 --- a/source/backends/rm86.d +++ b/source/backends/rm86.d @@ -350,9 +350,21 @@ class BackendRM86 : CompilerBackend { } } else if (VariableExists(node.name)) { + auto var = GetVariable(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushVariableValue(node, GetVariable(node.name)); } else if (GlobalExists(node.name)) { + auto var = GetGlobal(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushGlobalValue(node, GetGlobal(node.name)); } else if (IsStructMember(node.name)) { diff --git a/source/backends/x86_64.d b/source/backends/x86_64.d index 826fb60..c0809c0 100644 --- a/source/backends/x86_64.d +++ b/source/backends/x86_64.d @@ -611,10 +611,21 @@ class BackendX86_64 : CompilerBackend { return; } else if (VariableExists(node.name)) { + auto var = GetVariable(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushVariableValue(node, GetVariable(node.name)); - return; } else if (GlobalExists(node.name)) { + auto var = GetGlobal(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushGlobalValue(node, GetGlobal(node.name)); } else if (IsStructMember(node.name)) { From a62445bcff948eb744e9d902e1880c96dcc32336 Mon Sep 17 00:00:00 2001 From: MESYETI Date: Thu, 5 Dec 2024 20:24:08 +0000 Subject: [PATCH 6/7] uxn --- source/backends/uxn.d | 157 +++++++++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 48 deletions(-) diff --git a/source/backends/uxn.d b/source/backends/uxn.d index 453848a..94cd1e0 100644 --- a/source/backends/uxn.d +++ b/source/backends/uxn.d @@ -28,6 +28,8 @@ class BackendUXN : CompilerBackend { uint currentLoop; this() { + addrSize = 2; + types ~= Type("u8", 1); types ~= Type("i8", 1); types ~= Type("u16", 2); @@ -182,23 +184,37 @@ class BackendUXN : CompilerBackend { } void PushVariableValue( - Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false ) { if (size == 0) { - size = var.type.size; - } - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + size = var.type.Size(); } - if (var.offset == 0) { - output ~= ".vsp LDZ2\n"; + if (deref) { + if (var.offset == 0) { + output ~= ".vsp LDZ2\n"; + } + else { + output ~= format(".vsp LDZ2 #%.4x ADD2\n", var.offset); + } + + output ~= "LDA2\n"; + + if (offset != 0) { + output ~= format("#%.4x ADD2\n", offset); + } } else { - output ~= format(".vsp LDZ2 #%.4x ADD2\n", var.offset); + if (var.offset + offset == 0) { + output ~= ".vsp LDZ2\n"; + } + else { + output ~= format(".vsp LDZ2 #%.4x ADD2\n", var.offset + offset); + } } - switch (var.type.size) { + switch (size) { case 1: output ~= "LDA NIP\n"; break; case 2: output ~= "LDA2\n"; break; default: Error(node.error, "Bad variable type size"); @@ -206,19 +222,24 @@ class BackendUXN : CompilerBackend { } void PushGlobalValue( - Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false + Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } output ~= format(";global_%s\n", var.name.Sanitise()); - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + if (deref) { + output ~= "LDA2\n"; + } + + if (offset != 0) { + output ~= format("#%.4x ADD2\n", offset); } - switch (var.type.size) { + switch (size) { case 1: output ~= "LDA NIP\n"; break; case 2: output ~= "LDA2\n"; break; default: Error(node.error, "Bad variable type size"); @@ -287,9 +308,21 @@ class BackendUXN : CompilerBackend { } } else if (VariableExists(node.name)) { + auto var = GetVariable(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushVariableValue(node, GetVariable(node.name)); } else if (GlobalExists(node.name)) { + auto var = GetGlobal(node.name); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push value of structures"); + } + PushGlobalValue(node, GetGlobal(node.name)); } else if (IsStructMember(node.name)) { @@ -297,10 +330,18 @@ class BackendUXN : CompilerBackend { auto structVar = GetStructVariable(node, node.name); if (GlobalExists(name)) { - PushGlobalValue(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + PushGlobalValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (VariableExists(name)) { - PushVariableValue(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + PushVariableValue( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else if (node.name in consts) { @@ -852,50 +893,50 @@ class BackendUXN : CompilerBackend { } void SetVariable( - Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false + Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false ) { if (size == 0) { - size = var.type.size; - } - if (var.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + size = var.type.Size(); } - if (var.offset == 0) { - switch (var.type.size) { - case 1: output ~= "NIP .vsp LDZ2 STA\n"; break; - case 2: output ~= ".vsp LDZ2 STA2\n"; break; - default: Error(node.error, "Bad variable type size"); - } + string where = ".vsp LDZ2"; + + if (var.offset != 0) { + where ~= format(" #%.4x ADD2", var.offset); } - else { - switch (var.type.size) { - case 1: { - output ~= format("NIP .vsp LDZ2 #%.4X ADD2 STA\n", var.offset); - break; - } - case 2: { - output ~= format(".vsp LDZ2 #%.4X ADD2 STA2\n", var.offset); - break; - } - default: Error(node.error, "Bad variable type size"); - } + if (deref) { + where ~= " LDA2"; + } + if (offset != 0) { + where ~= format(" #%.4x ADD2", offset); + } + + switch (size) { + case 1: output ~= format("NIP %s STA\n", where); break; + case 2: output ~= format("%s STA2\n", where); break; + default: Error(node.error, "Bad variable type size"); } } void SetGlobal( - Node node, Global global, size_t size = 0, size_t offset = 0, bool member = false + Node node, Global global, size_t size = 0, size_t offset = 0, bool member = false, + bool deref = false ) { if (size == 0) { - size = global.type.size; - } - if (global.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + size = global.type.Size(); } string symbol = format("global_%s", global.name.Sanitise()); - switch (global.type.size) { + if (deref) { + symbol ~= format(" LDA2"); + } + if (offset != 0) { + symbol ~= format(" #%.4x ADD2", offset); + } + + switch (size) { case 1: output ~= format("NIP ;%s STA\n", symbol); break; case 2: output ~= format(";%s STA2\n", symbol); break; default: Error(node.error, "Bad variable type size"); @@ -904,9 +945,21 @@ class BackendUXN : CompilerBackend { override void CompileSet(SetNode node) { if (VariableExists(node.var)) { - SetVariable(node, GetVariable(node.var)); + auto var = GetVariable(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + + SetVariable(node, var); } else if (GlobalExists(node.var)) { + auto var = GetGlobal(node.var); + + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + SetGlobal(node, GetGlobal(node.var)); } else if (IsStructMember(node.var)) { @@ -914,10 +967,18 @@ class BackendUXN : CompilerBackend { auto structVar = GetStructVariable(node, node.var); if (VariableExists(name)) { - SetVariable(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + + SetVariable( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } else if (GlobalExists(name)) { - SetGlobal(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + + SetGlobal( + node, var, structVar.size, structVar.offset, true, var.type.ptr + ); } } else { From 7f1c8fd0eea086e8046993043b4b404e13f261eb Mon Sep 17 00:00:00 2001 From: Finn Coffey Date: Fri, 6 Dec 2024 18:42:43 +1100 Subject: [PATCH 7/7] Pointers on arm64 --- source/backends/arm64.d | 118 +++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 37 deletions(-) diff --git a/source/backends/arm64.d b/source/backends/arm64.d index a30a44b..9855e1f 100644 --- a/source/backends/arm64.d +++ b/source/backends/arm64.d @@ -43,6 +43,8 @@ class BackendARM64 : CompilerBackend { bool useLibc; this() { + addrSize = 8; + version (linux) { defaultOS = "linux"; } @@ -363,17 +365,20 @@ class BackendARM64 : CompilerBackend { } } - void PushGlobalValue(Node node, Global var, size_t size = 0, size_t offset = 0, bool member = false) { + void PushGlobalValue( + Node node, Global var, size_t size = 0, size_t offset = 0, + bool member = false, bool deref = false + ) { if (size == 0) { - size = var.type.size; - } - - if (var.type.isStruct && !member) { - Error(node.error, "Can't push value of struct"); + size = var.type.Size(); } LoadAddress("x9", format("__global_%s", var.name.Sanitise())); + if (deref) { + output ~= "ldr x9, [x9]\n"; + } + switch (size) { case 1: output ~= format("ldrb w9, [x9, #%d]\n", offset); break; case 2: output ~= format("ldrh w9, [x9, #%d]\n", offset); break; @@ -385,22 +390,32 @@ class BackendARM64 : CompilerBackend { output ~= "str x9, [x19], #8\n"; } - void PushVariableValue(Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false) { + void PushVariableValue( + Node node, Variable var, size_t size = 0, size_t offset = 0, + bool member = false, bool deref = false + ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } if (var.type.isStruct && !member) { Error(node.error, "Can't push value of struct"); } - offset += var.offset; + string base; + if (deref) { + output ~= format("ldr x9, [x20, #%d]\n", var.offset); + base = "x9"; + } else { + offset += var.offset; + base = "x20"; + } switch (size) { - case 1: output ~= format("ldrb w9, [x20, #%d]\n", offset); break; - case 2: output ~= format("ldrh w9, [x20, #%d]\n", offset); break; - case 4: output ~= format("ldr w9, [x20, #%d]\n", offset); break; - case 8: output ~= format("ldr x9, [x20, #%d]\n", offset); break; + case 1: output ~= format("ldrb w9, [%s, #%d]\n", base, offset); break; + case 2: output ~= format("ldrh w9, [%s, #%d]\n", base, offset); break; + case 4: output ~= format("ldr w9, [%s, #%d]\n", base, offset); break; + case 8: output ~= format("ldr x9, [%s, #%d]\n", base, offset); break; default: Error(node.error, "Bad variable type size"); } @@ -533,20 +548,30 @@ class BackendARM64 : CompilerBackend { } } else if (VariableExists(node.name)) { - PushVariableValue(node, GetVariable(node.name)); + auto var = GetVariable(node.name); + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push struct value"); + } + PushVariableValue(node, var); } else if (GlobalExists(node.name)) { - PushGlobalValue(node, GetGlobal(node.name)); + auto var = GetGlobal(node.name); + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't push struct value"); + } + PushGlobalValue(node, var); } else if (IsStructMember(node.name)) { string name = node.name[0 .. node.name.countUntil(".")]; auto structVar = GetStructVariable(node, node.name); if (GlobalExists(name)) { - PushGlobalValue(node, GetGlobal(name), structVar.size, structVar.offset, true); + auto var = GetGlobal(name); + PushGlobalValue(node, var, structVar.size, structVar.offset, true, var.type.ptr); } else if (VariableExists(name)) { - PushVariableValue(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + PushVariableValue(node, var, structVar.size, structVar.offset, true, var.type.ptr); } } else if (node.name in consts) { @@ -1157,41 +1182,50 @@ class BackendARM64 : CompilerBackend { variables = []; } - void SetVariable(Node node, Variable var, size_t size = 0, size_t offset = 0, bool member = false) { + void SetVariable( + Node node, Variable var, size_t size = 0, size_t offset = 0, + bool member = false, bool deref = false + ) { if (size == 0) { - size = var.type.size; + size = var.type.Size(); } output ~= "ldr x9, [x19, #-8]!\n"; - if (var.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); + string base; + if (deref) { + output ~= format("ldr x10, [x20, #%d]\n", var.offset); + base = "x10"; + } else { + offset += var.offset; + base = "x20"; } - offset += var.offset; - switch (size) { - case 1: output ~= format("strb w9, [x20, #%d]\n", offset); break; - case 2: output ~= format("strh w9, [x20, #%d]\n", offset); break; - case 4: output ~= format("str w9, [x20, #%d]\n", offset); break; - case 8: output ~= format("str x9, [x20, #%d]\n", offset); break; + case 1: output ~= format("strb w9, [%s, #%d]\n", base, offset); break; + case 2: output ~= format("strh w9, [%s, #%d]\n", base, offset); break; + case 4: output ~= format("str w9, [%s, #%d]\n", base, offset); break; + case 8: output ~= format("str x9, [%s, #%d]\n", base, offset); break; default: Error(node.error, "Bad variable type size"); } } - void SetGlobal(Node node, Global global, size_t size = 0, size_t offset = 0, bool member = false) { + void SetGlobal( + Node node, Global global, size_t size = 0, size_t offset = 0, + bool member = false, bool deref = false + ) { if (size == 0) { - size = global.type.size; + size = global.type.Size(); } output ~= "ldr x9, [x19, #-8]!\n"; - if (global.type.isStruct && !member) { - Error(node.error, "Can't set struct value"); - } - LoadAddress("x10", format("__global_%s", global.name.Sanitise())); + if (deref) { + output ~= "ldr x10, [x10]\n"; + } + switch (size) { case 1: output ~= format("strb w9, [x10, #%d]\n", offset); break; case 2: output ~= format("strh w9, [x10, #%d]\n", offset); break; @@ -1203,20 +1237,30 @@ class BackendARM64 : CompilerBackend { override void CompileSet(SetNode node) { if (VariableExists(node.var)) { - SetVariable(node, GetVariable(node.var)); + auto var = GetVariable(node.var); + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + SetVariable(node, var); } else if (GlobalExists(node.var)) { - SetGlobal(node, GetGlobal(node.var)); + auto var = GetGlobal(node.var); + if (var.type.isStruct && !var.type.ptr) { + Error(node.error, "Can't set struct value"); + } + SetGlobal(node, var); } else if (IsStructMember(node.var)) { string name = node.var[0 .. node.var.countUntil(".")]; auto structVar = GetStructVariable(node, node.var); if (VariableExists(name)) { - SetVariable(node, GetVariable(name), structVar.size, structVar.offset, true); + auto var = GetVariable(name); + SetVariable(node, var, structVar.size, structVar.offset, true, var.type.ptr); } else if (GlobalExists(name)) { - SetGlobal(node, GetGlobal(name), structVar.size, structVar. offset, true); + auto var = GetGlobal(name); + SetGlobal(node, var, structVar.size, structVar. offset, true, var.type.ptr); } } else {