shithub: riscv

Download patch

ref: cbe45e78f988184938ab63f8bac28632058e5810
parent: cf69bb920a53a2cbecc42e4299b7ed12818d39dc
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Aug 2 15:48:25 EDT 2020

7c: fix wrong type on OASxxx operations

the bug can be reproduced with the following test case:

#include <u.h>
#include <libc.h>

void
main()
{
	int size = 1;
	size*=1.5;
	exits(0);
}

this produces the following assembly:

	TEXT	main+0(SB),0,$16
	MOVW	$1,R1
	FCVTZSDW	$1.50000000000000000e+00,R2	<- tries to convert rhs to int??
	MULW	R2,R1,R2 <- multiplication done in int? bug!
	MOV	$0,R0
	BL	,exits+0(SB)
	RETURN	,
	END	,

the confusion comes from the *= operation using the wrong type
for the multiplication. in this case we should use the float
type of the rhs, do the operation, and then convert the result
back to int type of the lhs.

this change ports the same logic from 5c's getasop().

--- a/sys/src/cmd/7c/cgen.c
+++ b/sys/src/cmd/7c/cgen.c
@@ -287,28 +287,25 @@
 				reglcgen(&nod2, l, Z);
 			else
 				nod2 = *l;
-			regalloc(&nod, n, nn);
-			cgen(r, &nod);
+			regalloc(&nod1, r, Z);
+			cgen(r, &nod1);
 		} else {
-			regalloc(&nod, n, nn);
-			cgen(r, &nod);
+			regalloc(&nod1, r, Z);
+			cgen(r, &nod1);
 			if(l->addable < INDEXED)
 				reglcgen(&nod2, l, Z);
 			else
 				nod2 = *l;
 		}
-		regalloc(&nod1, n, Z);
-		gopcode(OAS, &nod2, Z, &nod1);
-		if(nod1.type->etype != nod.type->etype){
-			regalloc(&nod3, &nod, Z);
-			gmove(&nod1, &nod3);
-			regfree(&nod1);
-			nod1 = nod3;
-		}
-		gopcode(o, &nod, &nod1, &nod);
+		if(nod1.type == nod2.type || !typefd[nod1.type->etype])
+			regalloc(&nod, &nod2, nn);
+		else
+			regalloc(&nod, &nod1, Z);
+		gmove(&nod2, &nod);
+		gopcode(o, &nod1, &nod, &nod);
 		gmove(&nod, &nod2);
 		if(nn != Z)
-			gmove(&nod, nn);
+			gmove(&nod2, nn);
 		regfree(&nod);
 		regfree(&nod1);
 		if(l->addable < INDEXED)