Browse Source

Patched passing of 3 (or more) dimensional arrays with missing dimensions (address had been computed wrongly, missing multiplication by lengths)

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6891 8c9fc860-2736-0410-a75d-ab315db34111
felixf 9 năm trước cách đây
mục cha
commit
7483ceffe9
2 tập tin đã thay đổi với 71 bổ sung3 xóa
  1. 23 1
      source/FoxIntermediateBackend.Mod
  2. 48 2
      source/Oberon.Execution.Test

+ 23 - 1
source/FoxIntermediateBackend.Mod

@@ -4347,7 +4347,7 @@ TYPE
 		END DivInt;
 
 		PROCEDURE IndexDesignator(x: SyntaxTree.IndexDesignator);
-		VAR length,res: IntermediateCode.Operand; type: SyntaxTree.Type; maxDim: LONGINT; array:Operand;
+		VAR length,res: IntermediateCode.Operand; type,ttype: SyntaxTree.Type; maxDim: LONGINT; array:Operand;
 			index: Operand; e: SyntaxTree.Expression;i: LONGINT; size: LONGINT; atype: SyntaxTree.ArrayType;
 		BEGIN
 			type := x.left.type.resolved;
@@ -4361,6 +4361,12 @@ TYPE
 
 			IntermediateCode.InitImmediate(res,addressType,0);
 			maxDim := x.parameters.Length()-1;
+			(*
+				computation rule:
+				a: ARRAY X,Y,Z OF Element with size S
+				a[i,j,k] -->
+				( ( ( ( i ) * Y  + j ) * Z) + k) * S 
+			*)
 			FOR i := 0 TO maxDim DO
 				e := x.parameters.GetExpression(i);
 				Evaluate(e,index);
@@ -4398,6 +4404,22 @@ TYPE
 				END;
 				ReleaseIntermediateOperand(length);
 			END;
+			
+			(* remaining open dimensions -- compute address *)
+			i := maxDim+1;
+			IF type IS SyntaxTree.ArrayType THEN
+				ttype := type(SyntaxTree.ArrayType).arrayBase.resolved;
+				WHILE (ttype IS SyntaxTree.ArrayType) & (ttype(SyntaxTree.ArrayType).form # SyntaxTree.Static) DO
+					length := ArrayLength(ttype,array.dimOffset+i-1,array.tag);
+					IF (length.mode # IntermediateCode.ModeImmediate) OR (length.intValue # 1) THEN
+						MulInt(res,res,length);
+					END;
+					ReleaseIntermediateOperand(length);
+					INC(i);
+					ttype := ttype(SyntaxTree.ArrayType).arrayBase.resolved;
+				END;
+			END;
+			
 			IF (type IS SyntaxTree.ArrayType) THEN
 				IF (type(SyntaxTree.ArrayType).form # SyntaxTree.Static) THEN
 					size := StaticSize(system, type);

+ 48 - 2
source/Oberon.Execution.Test

@@ -7815,7 +7815,7 @@ positive: pass variables and values to array of byte
 		ASSERT(LEN(a) = len);
 	END Pass;
 
-	PROCEDURE Test*;
+	PROCEDURE Test;
 	VAR i: LONGINT;
 	BEGIN
 		Pass(3,1);
@@ -7823,5 +7823,51 @@ positive: pass variables and values to array of byte
 		Pass(3+i,4);
 		Pass(65000, 2); 
 	END Test;
+	
+	BEGIN
+		Test;
+	END Test.
+	
+positive: pass three-dimensional arrays A[x,y,z] with missing dimensions, e.g. A[x]
+	
+	MODULE Test;
+
+	IMPORT SYSTEM; 
+
+	PROCEDURE Pass(CONST a: ARRAY OF SYSTEM.BYTE; adr, len: ADDRESS);
+	VAR i: LONGINT;
+	BEGIN
+		ASSERT(ADDRESS OF a[0] = adr);
+		ASSERT(LEN(a) = len);
+	END Pass;
+
+	PROCEDURE Test;
+	TYPE
+		R= RECORD a,b,c: LONGINT END;
+		S= ARRAY 3 OF LONGINT;
+	VAR 
+		b: POINTER TO ARRAY OF ARRAY OF ARRAY OF LONGINT;
+		c: POINTER TO ARRAY OF ARRAY OF ARRAY OF R;
+		d: POINTER TO ARRAY OF ARRAY OF ARRAY OF S;
+	BEGIN
+		NEW(b,7,8,9);
+		Pass(b^, ADDRESS OF b[0,0,0], LEN(b,0)*LEN(b,1)*LEN(b,2)*SIZEOF(LONGINT));
+		Pass(b[1], ADDRESS OF b[1,0,0], LEN(b,1)*LEN(b,2)*SIZEOF(LONGINT));
+		Pass(b[1,2], ADDRESS OF b[1,2,0], LEN(b,2)*SIZEOF(LONGINT));
+		Pass(b[1,2,3], ADDRESS OF b[1,2,3], SIZEOF(LONGINT));
+		NEW(c,7,8,9);
+		Pass(c^, ADDRESS OF c[0,0,0], LEN(c,0)*LEN(c,1)*LEN(c,2)*SIZEOF(R));
+		Pass(c[1], ADDRESS OF c[1,0,0], LEN(c,1)*LEN(c,2)*SIZEOF(R));
+		Pass(c[1,2], ADDRESS OF c[1,2,0], LEN(c,2)*SIZEOF(R));
+		Pass(c[1,2,3], ADDRESS OF c[1,2,3], SIZEOF(R));
+		NEW(d,7,8,9);
+		Pass(d^, ADDRESS OF d[0,0,0], LEN(d,0)*LEN(d,1)*LEN(d,2)*SIZEOF(S));
+		Pass(d[1], ADDRESS OF d[1,0,0], LEN(d,1)*LEN(d,2)*SIZEOF(S));
+		Pass(d[1,2], ADDRESS OF d[1,2,0], LEN(d,2)*SIZEOF(S));
+		Pass(d[1,2,3], ADDRESS OF d[1,2,3], SIZEOF(S));
+	END Test;
+
+	BEGIN
+		Test;
+	END Test.
 
-	END Test.