Skip to content

Commit 6935145

Browse files
Fixing a ton of issues, adding null/nullptr/NULL, adding unit tests
1 parent a551498 commit 6935145

18 files changed

+491
-52
lines changed

buildscripts/tests/0.lls

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
array<i32, 10> arr = {
2+
char("T"), char("E"), char("S"), char("T"), char("t"), char("e"), char("s"), char("t"), char("!"), char("?")
3+
};
4+
5+
text kernel32dll = "Kernel32.dll";
6+
text writeFileA = "WriteFile";
7+
8+
voidptr kernel32dll_handle = load_library(kernel32dll);
9+
voidptr writeFileAAddr = get_proc_address(kernel32dll_handle, writeFileA);
10+
11+
extern_func<u8 (voidptr, ptr<i8>, u32, ptr<u32>, voidptr)> writeFileAFunc = cast<extern_func<u8 (voidptr, ptr<i8>, u32, ptr<u32>, voidptr)>>(writeFileAAddr);
12+
13+
voidptr stdOutHandle;
14+
15+
text getStdHandle = "GetStdHandle";
16+
voidptr getStdHandleAddr = get_proc_address(kernel32dll_handle, getStdHandle);
17+
extern_func<voidptr (u32)> getStdHandleFunc = cast<extern_func<voidptr (u32)>>(getStdHandleAddr);
18+
19+
u32 STD_OUTPUT_HANDLE = cast<u32>(-11);
20+
stdOutHandle = getStdHandleFunc(STD_OUTPUT_HANDLE);
21+
22+
text content = "Test0";
23+
24+
i32 i = 0;
25+
u32 _unused;
26+
27+
while (i < countof(arr))
28+
{
29+
valueof(content + 4) = cast<i8>(valueof(arr + i));
30+
31+
writeFileAFunc(stdOutHandle, content, countof(content) - 1, addressof(_unused), null);
32+
33+
i++;
34+
}

buildscripts/tests/0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TestTTestETestSTestTTesttTesteTestsTesttTest!Test?

buildscripts/unittest.csx

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#r "System"
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.IO;
6+
using System.Text;
7+
8+
void Fail(string error)
9+
{
10+
Console.WriteLine(error);
11+
Environment.Exit(-1);
12+
}
13+
14+
string CallProcess(string processName, string args, out int exitCode)
15+
{
16+
StringBuilder outputBuilder;
17+
System.Diagnostics.ProcessStartInfo processStartInfo;
18+
System.Diagnostics.Process process;
19+
20+
outputBuilder = new StringBuilder();
21+
22+
processStartInfo = new System.Diagnostics.ProcessStartInfo();
23+
processStartInfo.CreateNoWindow = true;
24+
processStartInfo.RedirectStandardOutput = true;
25+
processStartInfo.RedirectStandardInput = true;
26+
processStartInfo.UseShellExecute = false;
27+
processStartInfo.Arguments = args;
28+
processStartInfo.FileName = processName;
29+
30+
process = new System.Diagnostics.Process();
31+
process.StartInfo = processStartInfo;
32+
process.EnableRaisingEvents = true;
33+
34+
process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler
35+
(
36+
delegate(object sender, System.Diagnostics.DataReceivedEventArgs e)
37+
{
38+
outputBuilder.Append(e.Data);
39+
}
40+
);
41+
42+
process.Start();
43+
process.BeginOutputReadLine();
44+
process.WaitForExit();
45+
process.CancelOutputRead();
46+
47+
exitCode = process.ExitCode;
48+
49+
return outputBuilder.ToString();
50+
}
51+
52+
try
53+
{
54+
Directory.CreateDirectory("tmp");
55+
56+
string scriptFile = "tmp/code.lls";
57+
string byteCodeFile = "tmp/bytecode.lls";
58+
59+
var tests = Directory.GetFiles("tests/", "*.lls");
60+
61+
Console.WriteLine($"\nRunning {tests.Count()} UnitTest(s)...\n");
62+
63+
foreach (var test in tests)
64+
{
65+
Console.WriteLine($"Testing {test} ...");
66+
67+
File.Copy(test, scriptFile, true);
68+
69+
string output = CallProcess("..\\builds\\bin\\llsc.exe", $"{scriptFile} -S+ -dbgdb -o=\"{byteCodeFile}\"", out int exitCode);
70+
71+
if (exitCode != 0)
72+
Fail($"Failed to compile test {test}\n\n{output}");
73+
74+
output = CallProcess("..\\builds\\bin\\llscript_exec.exe", byteCodeFile, out exitCode);
75+
76+
if (exitCode != 0)
77+
Fail($"Failed to execute test {test}\n\n{output}");
78+
79+
var expected = File.ReadAllText(test.Replace("lls", "txt"));
80+
81+
if (expected != output)
82+
Fail($"Invalid output for test {test}\n\nExpected: ({expected.Length} chars) '{expected}'\nRetrieved: ({output.Length} chars) '{output}'");
83+
}
84+
85+
Console.WriteLine("\nAll UnitTests succeeded!");
86+
}
87+
catch (Exception e)
88+
{
89+
Console.WriteLine($"Failed with error: {e.Message}\n{e}");
90+
}
91+
92+
Directory.Delete("tmp", true);

llsc/llsc.csproj

+2-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
<OutputPath>..\builds\bin\</OutputPath>
2121
<BaseIntermediateOutputPath>intermediate\obj\x64\Debug\</BaseIntermediateOutputPath>
2222
<IntermediateOutputPath>$(BaseIntermediateOutputPath)</IntermediateOutputPath>
23-
<DefineConstants>
24-
</DefineConstants>
23+
<DefineConstants></DefineConstants>
2524
<ErrorReport>prompt</ErrorReport>
2625
<WarningLevel>4</WarningLevel>
2726
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -33,8 +32,7 @@
3332
<OutputPath>..\builds\bin\</OutputPath>
3433
<BaseIntermediateOutputPath>intermediate\obj\x64\Release\</BaseIntermediateOutputPath>
3534
<IntermediateOutputPath>$(BaseIntermediateOutputPath)</IntermediateOutputPath>
36-
<DefineConstants>
37-
</DefineConstants>
35+
<DefineConstants></DefineConstants>
3836
<ErrorReport>prompt</ErrorReport>
3937
<WarningLevel>4</WarningLevel>
4038
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

llsc/src/ByteCodeState.cs

+16
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,22 @@ public void CopyValueToPosition(CValue sourceValue, Position position, SharedVal
787787
instructions.Add(new LLI_MovRegisterToStackOffset_NBytes(register, stackSize, position.stackOffsetForward, (int)size));
788788
}
789789
}
790+
else if (sourceValue is CNullValue)
791+
{
792+
var bytes = BitConverter.GetBytes((ulong)0);
793+
794+
if (position.inRegister)
795+
{
796+
instructions.Add(new LLI_MovImmToRegister(position.registerIndex, bytes));
797+
}
798+
else
799+
{
800+
var register = GetFreeIntegerRegister(stackSize);
801+
802+
instructions.Add(new LLI_MovImmToRegister(register, bytes));
803+
instructions.Add(new LLI_MovRegisterToStackOffset(register, stackSize, position.stackOffsetForward));
804+
}
805+
}
790806
else
791807
{
792808
if (!sourceValue.hasPosition)

llsc/src/CFunction.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ public class CFunction
1717
public readonly long callStackSize;
1818
public List<Node> nodes;
1919
public Scope scope;
20-
public LLI_Label_PseudoInstruction functionStartLabel = new LLI_Label_PseudoInstruction(),
21-
functionEndLabel = new LLI_Label_PseudoInstruction();
20+
public LLI_Label_PseudoInstruction functionStartLabel, functionEndLabel;
2221

2322
public CFunction(string name, CType returnType, IEnumerable<FunctionParameter> parameters, string file, int line)
2423
{
@@ -28,6 +27,9 @@ public CFunction(string name, CType returnType, IEnumerable<FunctionParameter> p
2827
this.file = file;
2928
this.line = line;
3029

30+
functionStartLabel = new LLI_Label_PseudoInstruction($"Function Start Label for '{this}' ({file}:{line})");
31+
functionEndLabel = new LLI_Label_PseudoInstruction($"Function End Label for '{this}' ({file}:{line})");
32+
3133
minStackSize.Value = 8; // Return Address.
3234

3335
// + Return Value Ptr if not void or in register.

llsc/src/CInstruction.cs

+54-9
Original file line numberDiff line numberDiff line change
@@ -1403,9 +1403,6 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
14031403
}
14041404

14051405
byteCodeState.instructions.Add(new LLI_NegateRegister(rightRegisterIndex));
1406-
1407-
if (right.type is PtrCType)
1408-
14091406
byteCodeState.instructions.Add(new LLI_AddRegister(leftRegisterIndex, rightRegisterIndex));
14101407

14111408
left.remainingReferences--;
@@ -1935,7 +1932,7 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
19351932

19361933
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
19371934
{
1938-
int rvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(rvalue, stackSize);
1935+
int rvalueRegisterIndex = byteCodeState.MoveValueToAnyRegister(rvalue, stackSize);
19391936

19401937
if (lvalue is CNamedValue || lvalue is CGlobalValueReference)
19411938
{
@@ -1990,7 +1987,7 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
19901987

19911988
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
19921989
{
1993-
int rvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(rvalue, stackSize);
1990+
int rvalueRegisterIndex = byteCodeState.MoveValueToAnyRegister(rvalue, stackSize);
19941991

19951992
if (lvalue is CNamedValue || lvalue is CGlobalValueReference)
19961993
{
@@ -2047,7 +2044,7 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
20472044

20482045
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
20492046
{
2050-
int rvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(rvalue, stackSize);
2047+
int rvalueRegisterIndex = byteCodeState.MoveValueToAnyRegister(rvalue, stackSize);
20512048

20522049
if (lvalue is CNamedValue || lvalue is CGlobalValueReference)
20532050
{
@@ -2104,7 +2101,7 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
21042101

21052102
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
21062103
{
2107-
int rvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(rvalue, stackSize);
2104+
int rvalueRegisterIndex = byteCodeState.MoveValueToAnyRegister(rvalue, stackSize);
21082105

21092106
if (lvalue is CNamedValue || lvalue is CGlobalValueReference)
21102107
{
@@ -2161,7 +2158,7 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
21612158

21622159
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
21632160
{
2164-
int rvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(right, stackSize);
2161+
int rvalueRegisterIndex = byteCodeState.MoveValueToAnyRegister(right, stackSize);
21652162

21662163
if (left is CNamedValue || left is CGlobalValueReference)
21672164
{
@@ -2216,7 +2213,7 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
22162213

22172214
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
22182215
{
2219-
int rvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(right, stackSize);
2216+
int rvalueRegisterIndex = byteCodeState.MoveValueToAnyRegister(right, stackSize);
22202217

22212218
if (left is CNamedValue || left is CGlobalValueReference)
22222219
{
@@ -2334,4 +2331,52 @@ public override void GetLLInstructions(ref ByteCodeState byteCodeState)
23342331
}
23352332
}
23362333
}
2334+
2335+
public class CInstruction_Negate : CInstruction
2336+
{
2337+
CValue value;
2338+
SharedValue<long> stackSize;
2339+
CValue resultingValue;
2340+
2341+
public CInstruction_Negate(CValue value, SharedValue<long> stackSize, out CValue resultingValue, string file, int line) : base(file, line)
2342+
{
2343+
if (value.type is BuiltInCType && (value.type as BuiltInCType).IsUnsigned())
2344+
Compiler.Error($"Attempting to negate unsigned value '{value}'. This requires a cast.", file, line);
2345+
2346+
this.value = value;
2347+
this.stackSize = stackSize;
2348+
2349+
this.resultingValue = new CValue(file, line, value.type, false, true) { description = $"-({value})" };
2350+
2351+
resultingValue = this.resultingValue;
2352+
}
2353+
2354+
public override void GetLLInstructions(ref ByteCodeState byteCodeState)
2355+
{
2356+
if (!value.isInitialized)
2357+
Compiler.Error($"Cannot perform operator on uninitialized lvalue {value}.", file, line);
2358+
2359+
int lvalueRegisterIndex = byteCodeState.CopyValueToAnyRegister(value, stackSize);
2360+
2361+
using (var registerLock = byteCodeState.LockRegister(lvalueRegisterIndex))
2362+
{
2363+
if (value is CNamedValue || value is CGlobalValueReference)
2364+
{
2365+
if (value is CNamedValue)
2366+
byteCodeState.MoveValueToHome(value as CNamedValue, stackSize);
2367+
else if (value is CGlobalValueReference)
2368+
throw new NotImplementedException();
2369+
}
2370+
2371+
byteCodeState.instructions.Add(new LLI_NegateRegister(lvalueRegisterIndex));
2372+
2373+
value.remainingReferences--;
2374+
2375+
byteCodeState.registers[lvalueRegisterIndex] = resultingValue;
2376+
resultingValue.hasPosition = true;
2377+
resultingValue.position.inRegister = true;
2378+
resultingValue.position.registerIndex = lvalueRegisterIndex;
2379+
}
2380+
}
2381+
}
23372382
}

llsc/src/CValue.cs

+11-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ public virtual CValue MakeCastableClone(CType targetType, Scope scope, ref ByteC
7373

7474
public class CConstIntValue : CValue
7575
{
76-
public ulong uvalue { get; protected set; }
76+
public ulong uvalue { get; set; }
7777

78-
public long ivalue { get; protected set; }
78+
public long ivalue { get; set; }
7979

8080
public CType smallestPossibleSignedType { get; protected set; } = null;
8181

@@ -213,7 +213,7 @@ public override CValue DeepClone(Scope scope, ref ByteCodeState byteCodeState)
213213

214214
public class CConstFloatValue : CValue
215215
{
216-
public double value { get; protected set; }
216+
public double value { get; set; }
217217

218218
protected CConstFloatValue() : base() { }
219219

@@ -311,4 +311,12 @@ public CGlobalValueReference(CType type, string file, int line, bool isConst) :
311311

312312
public override string ToString() => "unnamed global (?) value [" + (isConst ? "const " : "") + type + (string.IsNullOrWhiteSpace(description) ? "" : $" '{description}'") + "]";
313313
}
314+
315+
public class CNullValue : CValue
316+
{
317+
public CNullValue(string file, int line) : base(file, line, new PtrCType(VoidCType.Instance), true, true)
318+
{
319+
320+
}
321+
}
314322
}

0 commit comments

Comments
 (0)