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().
This commit is contained in:
cinap_lenrek 2020-08-02 19:48:25 +02:00
parent cf69bb920a
commit cbe45e78f9

View file

@ -287,28 +287,25 @@ cgenrel(Node *n, Node *nn, int inrel)
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)