diff --git a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs index a94a5e6e..3b2ee23e 100644 --- a/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs +++ b/Cesium.CodeGen/Ir/Expressions/FunctionCallExpression.cs @@ -117,15 +117,16 @@ public override IExpression Lower(IDeclarationScope scope) { if (index >= firstVarArgArgument) { - var expressionType = a.GetExpressionType(scope); + var loweredArg = a.Lower(scope); + var expressionType = loweredArg.GetExpressionType(scope); if (expressionType.Equals(scope.CTypeSystem.Float)) { // Seems to be float always use float-point registers and as such we need to covert to double. - return new TypeCastExpression(scope.CTypeSystem.Double, a.Lower(scope)); + return new TypeCastExpression(scope.CTypeSystem.Double, loweredArg); } else { - return a.Lower(scope); + return loweredArg; } } diff --git a/Cesium.Compiler/stdlib/stdio.h b/Cesium.Compiler/stdlib/stdio.h index 483c4efb..21f58282 100644 --- a/Cesium.Compiler/stdlib/stdio.h +++ b/Cesium.Compiler/stdlib/stdio.h @@ -1,18 +1,21 @@ #pragma once +typedef void FILE; + +#define stdin 0 +#define stdout 1 +#define stderr 2 + __cli_import("Cesium.Runtime.StdIoFunctions::PutS") int puts(char *s); __cli_import("Cesium.Runtime.StdIoFunctions::PrintF") int printf(char* s, ...); +__cli_import("Cesium.Runtime.StdIoFunctions::FPrintF") +int fprintf(FILE* stream, char* s, ...); + __cli_import("Cesium.Runtime.StdIoFunctions::PutChar") int putchar(char _Character); -typedef void FILE; - -#define stdin 0 -#define stdout 1 -#define stderr 2 - __cli_import("Cesium.Runtime.StdIoFunctions::PutC") int putc(char _Character, FILE* stream); diff --git a/Cesium.Compiler/stdlib/stdlib.h b/Cesium.Compiler/stdlib/stdlib.h index a80fdba2..453767e8 100644 --- a/Cesium.Compiler/stdlib/stdlib.h +++ b/Cesium.Compiler/stdlib/stdlib.h @@ -39,3 +39,6 @@ void abort(void); #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 + +__cli_import("Cesium.Runtime.StdLibFunctions::Atoi") +int atoi(const char* str); diff --git a/Cesium.Runtime/StdIoFunctions.cs b/Cesium.Runtime/StdIoFunctions.cs index 98329c79..b4e0d4d4 100644 --- a/Cesium.Runtime/StdIoFunctions.cs +++ b/Cesium.Runtime/StdIoFunctions.cs @@ -20,6 +20,12 @@ record class StreamHandle private static List handles = new(); + private const int StdIn = 0; + + private const int StdOut = 1; + + private const int StdErr = 2; + static StdIoFunctions() { handles.Add(new StreamHandle() @@ -87,6 +93,11 @@ public static int PutC(byte character, void* stream) } public static int PrintF(byte* str, void* varargs) + { + return FPrintF((void*)(IntPtr)StdOut, str, varargs); + } + + public static int FPrintF(void* stream, byte* str, void* varargs) { var formatString = Unmarshal(str); if (formatString == null) @@ -94,6 +105,20 @@ public static int PrintF(byte* str, void* varargs) return -1; } + var streamHandle = GetStreamHandle(stream); + if (streamHandle == null) + { + return -1; + } + + var streamWriterAccessor = streamHandle.Writer; + if (streamWriterAccessor == null) + { + return -1; + } + + var streamWriter = streamWriterAccessor(); + int currentPosition = 0; var formatStartPosition = formatString.IndexOf('%', currentPosition); int consumedArgs = 0; @@ -101,7 +126,7 @@ public static int PrintF(byte* str, void* varargs) while (formatStartPosition >= 0) { var lengthTillPercent = formatStartPosition - currentPosition; - Console.Write(formatString.Substring(currentPosition, lengthTillPercent)); + streamWriter.Write(formatString.Substring(currentPosition, lengthTillPercent)); consumedBytes += lengthTillPercent; int addition = 1; string formatSpecifier = formatString[formatStartPosition + addition].ToString(); @@ -115,12 +140,12 @@ public static int PrintF(byte* str, void* varargs) { case "s": string? stringValue = Unmarshal((byte*)((long*)varargs)[consumedArgs]); - Console.Write(stringValue); + streamWriter.Write(stringValue); consumedBytes += stringValue?.Length ?? 0; consumedArgs++; break; case "c": - Console.Write((char)(byte)((long*)varargs)[consumedArgs]); + streamWriter.Write((char)(byte)((long*)varargs)[consumedArgs]); consumedBytes++; consumedArgs++; break; @@ -129,7 +154,7 @@ public static int PrintF(byte* str, void* varargs) case "i": int intValue = (int)((long*)varargs)[consumedArgs]; var intValueString = intValue.ToString(); - Console.Write(intValueString); + streamWriter.Write(intValueString); consumedBytes += intValueString.Length; consumedArgs++; break; @@ -137,24 +162,28 @@ public static int PrintF(byte* str, void* varargs) case "lu": uint uintValue = (uint)((long*)varargs)[consumedArgs]; var uintValueString = uintValue.ToString(); - Console.Write(uintValueString); + streamWriter.Write(uintValueString); consumedBytes += uintValueString.Length; consumedArgs++; break; case "f": var floatNumber = ((double*)varargs)[consumedArgs]; string floatNumberString = floatNumber.ToString("F6"); - Console.Write(floatNumberString); + streamWriter.Write(floatNumberString); consumedBytes += floatNumberString.Length; consumedArgs++; break; case "p": nint pointerValue = ((nint*)varargs)[consumedArgs]; string pointerValueString = pointerValue.ToString("X"); - Console.Write(pointerValueString); + streamWriter.Write(pointerValueString); consumedBytes += pointerValueString.Length; consumedArgs++; break; + case "%": + streamWriter.Write('%'); + consumedBytes += 1; + break; default: throw new FormatException($"Format specifier {formatSpecifier} is not supported"); } @@ -164,7 +193,7 @@ public static int PrintF(byte* str, void* varargs) } string remainderString = formatString.Substring(currentPosition); - Console.Write(remainderString); + streamWriter.Write(remainderString); return consumedBytes + remainderString.Length; } diff --git a/Cesium.Runtime/StdLibFunctions.cs b/Cesium.Runtime/StdLibFunctions.cs index 963d5ee2..06681e5c 100644 --- a/Cesium.Runtime/StdLibFunctions.cs +++ b/Cesium.Runtime/StdLibFunctions.cs @@ -113,4 +113,10 @@ public static void Free(void* ptr) return NativeMemory.AlignedAlloc(size, alignment); #endif } + + public static int Atoi(byte* ptr) + { + var str = StdIoFunctions.Unmarshal(ptr); + return Convert.ToInt32(str); + } }