Browse Source

Fix ASH and LSH for int64 operand.

k_john_gough_cp 12 years ago
parent
commit
7db7ceb0dd
3 changed files with 69 additions and 39 deletions
  1. 16 5
      gpcp/ExprDesc.cp
  2. 42 34
      gpcp/JavaMaker.cp
  3. 11 0
      gpcp/MsilMaker.cp

+ 16 - 5
gpcp/ExprDesc.cp

@@ -934,7 +934,7 @@ MODULE ExprDesc;
             END;
           END;
       (* ---------------------------- *)
-	  (* QUESTION: should this be extended to LONGINT? *)
+      (* Extended to LONGINT (1:01:2013) *)
       (* ---------------------------- *)
       | Builtin.ashP :
           IF    act.tide < 2 THEN prc.ExprError(22);
@@ -942,19 +942,26 @@ MODULE ExprDesc;
           ELSE
             IF ~arg0.isIntExpr() THEN arg0.ExprError(37) END;
             IF ~arg1.isIntExpr() THEN arg1.ExprError(37) END;
+	   (* NO FOLDING IN THIS VERSION *)
             IF (arg0.kind = numLt) & (arg1.kind = numLt) THEN
               rslt := mkNumLt(ASH(arg0(LeafX).value.int(),
                 arg1(LeafX).value.int()));
             ELSE
-              IF arg0.type # Builtin.intTp THEN
+	   *)
+	      IF arg0.type = Builtin.lIntTp THEN
+                dstT := Builtin.lIntTp;
+              ELSIF arg0.type # Builtin.intTp THEN
                 arg0 := convert(arg0, Builtin.intTp);
+		dstT := Builtin.intTp;
               END;
               IF arg1.type # Builtin.intTp THEN
                 arg1 := convert(arg1, Builtin.intTp);
               END;
               rslt := newBinaryX(ashInt, arg0, arg1);
+	   (*
             END;
-            rslt.type := Builtin.intTp;
+            *)
+            rslt.type := dstT;
           END;
       (* ---------------------------- *)
       | Builtin.lshP :
@@ -963,14 +970,18 @@ MODULE ExprDesc;
           ELSE
             IF ~arg0.isIntExpr() THEN arg0.ExprError(37) END;
             IF ~arg1.isIntExpr() THEN arg1.ExprError(37) END;
-            IF arg0.type # Builtin.intTp THEN
+			(* FIXME, no folding yet ... *)
+			IF arg0.type = Builtin.lIntTp THEN
+			  dstT := Builtin.lIntTp;
+            ELSIF arg0.type # Builtin.intTp THEN
               arg0 := convert(arg0, Builtin.intTp);
+			  dstT := Builtin.intTp;
             END;
             IF arg1.type # Builtin.intTp THEN
               arg1 := convert(arg1, Builtin.intTp);
             END;
             rslt := newBinaryX(lshInt, arg0, arg1);
-            rslt.type := Builtin.intTp;
+            rslt.type := dstT;
           END;
       (* ---------------------------- *)
       | Builtin.rotP :

+ 42 - 34
gpcp/JavaMaker.cp

@@ -1344,20 +1344,10 @@ MODULE JavaMaker;
         IF exp.lKid.type IS Ty.Vector THEN
           e.PushVecElemHandle(lOp, rOp);
           out.GetVecElement(dst);                 (* load the element   *)
-(* 
- *        vTp := lOp.type(Ty.Vector);
- *        e.PushValue(lOp, lOp.type);             (* push array designator*)
- *        out.GetVecArr(vTp.elemTp);
- *        e.PushValue(rOp, rOp.type);             (* push index value   *)
- *        out.GetVecElement(vTp.elemTp);          (* load the element   *)
- *)
         ELSE
 		  IF rOp.type = NIL THEN rOp.type := Bi.intTp END;
           e.PushValue(lOp, lOp.type);             (* push arr. desig.   *)
           e.PushValue(rOp, rOp.type);             (* push index value   *)
-(*
- *        out.GetElement(dst);                    (* load the element   *)
- *)
           out.GetElement(lOp.type(Ty.Array).elemTp);  (* load the element   *)
           IF dst = Bi.uBytTp THEN e.UbyteClear() END;
         END;
@@ -1652,52 +1642,70 @@ MODULE JavaMaker;
 		END;
     (* -------------------------------- *)
     | Xp.ashInt, Xp.lshInt :
-(* FIXME: What about long types (here but not for .NET???) *)
         e.PushValue(lOp, lOp.type);
+		long := dst.isLongType();
         IF rOp.kind = Xp.numLt THEN
           indx := intValue(rOp);
           IF indx = 0 THEN  (* skip *)
-          ELSIF indx < 0 THEN
+          ELSIF indx < 0 THEN (* right shift *)
             out.PushInt(-indx);
-           (*
-            *  A literal, negative ASH might be
-            *  a long operation from a folded DIV.
-            *)
-            IF dst.isLongType() THEN 
-			  out.Code(Jvm.opc_lshr);
-            ELSIF exp.kind = Xp.ashInt THEN
-			  out.Code(Jvm.opc_ishr);
-            ELSE
-			  out.Code(Jvm.opc_iushr);
-            END;
-          ELSE
-            out.PushInt(indx);
-            out.Code(Jvm.opc_ishl);
-          END;
-        ELSE
+            IF long THEN
+			  IF exp.kind = Xp.ashInt THEN (* arith shift *)
+			    out.Code(Jvm.opc_lshr);
+			  ELSE (* logical shift *)
+			    out.Code(Jvm.opc_lushr);
+			  END;
+			ELSE (* integer sized *)
+			  IF exp.kind = Xp.ashInt THEN (* arith shift *)
+			    out.Code(Jvm.opc_ishr);
+			  ELSE (* logical shift *)
+			    out.Code(Jvm.opc_iushr);
+			  END;
+			END;
+		  ELSE (* a left shift *)
+		    out.PushInt(indx);
+		    IF long THEN
+              out.Code(Jvm.opc_lshl);
+			ELSE (* integer sized *)
+              out.Code(Jvm.opc_ishl);
+			END;
+		  END;
+        ELSE  (* variable sized shift *)
           tpLb := out.newLabel();
           exLb := out.newLabel();
          (*
           *  This is a variable shift. Do it the hard way.
           *  First, check the sign of the right hand op.
           *)
-          e.PushValue(rOp, rOp.type);
+          e.PushValue(rOp, Bi.intTp);
           out.Code(Jvm.opc_dup);
           out.CodeLb(Jvm.opc_iflt, tpLb);
          (*
           *  Positive selector ==> shift left;
           *)
-          out.Code(Jvm.opc_ishl);
+		  IF long THEN
+            out.Code(Jvm.opc_lshl);
+		  ELSE
+            out.Code(Jvm.opc_ishl);
+		  END;
           out.CodeLb(Jvm.opc_goto, exLb);
          (*
           *  Negative selector ==> shift right;
           *)
           out.DefLab(tpLb);
           out.Code(Jvm.opc_ineg);
-		  IF exp.kind = Xp.ashInt THEN
-            out.Code(Jvm.opc_ishr);
-		  ELSE
-            out.Code(Jvm.opc_iushr);
+		  IF long THEN
+		    IF exp.kind = Xp.ashInt THEN
+              out.Code(Jvm.opc_lshr);
+		    ELSE
+              out.Code(Jvm.opc_lushr);
+		    END;
+	      ELSE
+		    IF exp.kind = Xp.ashInt THEN
+              out.Code(Jvm.opc_ishr);
+		    ELSE
+              out.Code(Jvm.opc_iushr);
+			END;
 		  END;
           out.DefLab(exLb);
         END;

+ 11 - 0
gpcp/MsilMaker.cp

@@ -1738,6 +1738,7 @@ MODULE MsilMaker;
         ELSE
           tpLb := out.newLabel();
           exLb := out.newLabel();
+	      long := dst(Ty.Base).tpOrd = Ty.lIntN;
          (*
           *  This is a variable shift. Do it the hard way.
           *  First, check the sign of the right hand op.
@@ -1746,6 +1747,11 @@ MODULE MsilMaker;
           out.Code(Asm.opc_dup);
           out.PushInt(0);
           out.CodeLb(Asm.opc_blt, tpLb);
+		 (*
+		  *  Trim the shift index
+		  *)
+		  IF long THEN out.PushInt(63) ELSE out.PushInt(31) END;
+		  out.Code(Asm.opc_and);
          (*
           *  Positive selector ==> shift left;
           *)
@@ -1756,6 +1762,11 @@ MODULE MsilMaker;
           *)
           out.DefLab(tpLb);
           out.Code(Asm.opc_neg);
+		 (*
+		  *  Trim the shift index
+		  *)
+		  IF long THEN out.PushInt(63) ELSE out.PushInt(31) END;
+		  out.Code(Asm.opc_and);
 		  IF exp.kind = Xp.ashInt THEN
             out.Code(Asm.opc_shr);
 		  ELSE (* ==> exp.kind = lshInt *)