ref: bc10c7a08bd185058966b1c8d410a24dc15189e5
parent: 8c3467b7bef2bbc46e2736a89184022a7c979e38
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)
--
⑨