Browse Source

compiler: fix C size_t and pointer sentinels

Eric Streit 11 hours ago
parent
commit
a898a558aa

+ 2 - 0
compiler/run_tests.sh

@@ -49,6 +49,8 @@ expect_fail() {
 mkdir -p gen_ssa
 expect_run t_minimal.mod 0
 expect_run t_longstr.mod 42
+expect_run t_csize.mod 42
+expect_run t_ptrsentinel.mod 42
 expect_run t_exit.mod 7
 expect_run t_arith.mod 25
 expect_run showcase1.mod 50

+ 8 - 0
compiler/src/Lower.mod

@@ -1789,6 +1789,14 @@ PROCEDURE LowerBuiltinExpr (n: AST.Node; nm: SymTab.Name;
         ELSIF ((c1 = SymTab.ClReal) OR (c1 = SymTab.ClSReal))
            AND ((c2 = SymTab.ClReal) OR (c2 = SymTab.ClSReal)) THEN
           t := vt
+        ELSIF ((c1 = SymTab.ClInt) OR (c1 = SymTab.ClByte)
+            OR (c1 = SymTab.ClSByte) OR (c1 = SymTab.ClWord16)
+            OR (c1 = SymTab.ClSWord16) OR (c1 = SymTab.ClLong))
+           AND (c2 = SymTab.ClPtr) THEN
+          IF (c1 # SymTab.ClLong) AND NOT QbeGen.IsImm(q) THEN
+            QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q)
+          END;
+          t := vt
         ELSIF (c1 = SymTab.ClSet) AND (c2 = SymTab.ClInt) THEN
           (* a set as its (first) machine word *)
           QbeGen.LoadW(q, qa); QbeGen.CopyOp(qa, q); t := vt

+ 13 - 0
compiler/src/M2.atg

@@ -4509,6 +4509,19 @@ PRODUCTIONS
                                                ELSIF (c1 = SymTab.ClPtr)
   AND (c2 = SymTab.ClPtr) THEN
                                                  t := vt
+                                               ELSIF ((c1 = SymTab.ClInt)
+                                                   OR (c1 = SymTab.ClByte)
+                                                   OR (c1 = SymTab.ClSByte)
+                                                   OR (c1 = SymTab.ClWord16)
+                                                   OR (c1 = SymTab.ClSWord16)
+                                                   OR (c1 = SymTab.ClLong))
+  AND (c2 = SymTab.ClPtr) THEN
+                                                 IF (c1 # SymTab.ClLong)
+                                                    AND NOT QbeGen.IsImm(q) THEN
+                                                   QbeGen.WidenLong(q, qa);
+                                                   QbeGen.CopyOp(qa, q)
+                                                 END;
+                                                 t := vt
                                                ELSIF ((c1 = SymTab.ClProc)
   AND (c2 = SymTab.ClProc))
   OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))

+ 3 - 2
compiler/src/SymTab.mod

@@ -4112,8 +4112,9 @@ PROCEDURE Init;
     Predef("COMPLEX32", KindPredef, dReal);
     Predef("COMPLEX64", KindPredef, dReal);
     Predef("COMPLEX128", KindPredef, dReal);
-    Predef("CSIZE_T", KindPredef, dCard);
-    Predef("CSSIZE_T", KindPredef, dInt);
+    (* size_t/ssize_t are pointer-sized on the supported amd64 target. *)
+    Predef("CSIZE_T", KindPredef, dLong);
+    Predef("CSSIZE_T", KindPredef, dLong);
     Predef("COFF_T", KindPredef, dLong);
     (* ISO SYSTEM constants: LOC is a byte, so 8 bits per LOC and 4
        LOCs per 32-bit word. *)

+ 12 - 0
compiler/tests/t_csize.mod

@@ -0,0 +1,12 @@
+MODULE TCsize;
+(* C size_t/ssize_t are 64-bit on amd64. *)
+FROM SYSTEM IMPORT CSIZE_T, CSSIZE_T, COFF_T;
+VAR ExitCode : INTEGER;
+BEGIN
+  IF (SIZE(CSIZE_T) = 8) AND (SIZE(CSSIZE_T) = 8)
+     AND (SIZE(COFF_T) = 8) THEN
+    ExitCode := 42
+  ELSE
+    ExitCode := 1
+  END
+END TCsize.

+ 9 - 0
compiler/tests/t_ptrsentinel.mod

@@ -0,0 +1,9 @@
+MODULE TPtrSentinel;
+(* Integer-to-ADDRESS conversion supports C sentinel values. *)
+FROM SYSTEM IMPORT ADDRESS, VAL;
+VAR ExitCode : INTEGER;
+    p : ADDRESS;
+BEGIN
+  p := VAL(ADDRESS, -1);
+  IF p # NIL THEN ExitCode := 42 ELSE ExitCode := 1 END
+END TPtrSentinel.

+ 24 - 0
docs/c-binding-compiler-notes.md

@@ -22,6 +22,30 @@ The practical limit is still set by the scanner/grammar buffers and
 `AST.MaxTxtLen` (255).  Keep very large SQL scripts below that limit or
 build them through a character buffer.
 
+## C scalar widths and pointer sentinels
+
+`SYSTEM.CSIZE_T` and `SYSTEM.CSSIZE_T` now use the 64-bit integer
+representation on the supported amd64 target.  This matches C
+`size_t`/`ssize_t`; `SYSTEM.COFF_T` was already 64-bit.
+
+Covered by:
+
+```text
+compiler/tests/t_csize.mod
+```
+
+`VAL(ADDRESS, integer)` now supports pointer sentinels such as:
+
+```modula2
+p := VAL(ADDRESS, -1);
+```
+
+Covered by:
+
+```text
+compiler/tests/t_ptrsentinel.mod
+```
+
 ## `ADR` on arrays
 
 Current behavior: