summaryrefslogtreecommitdiff
path: root/sys/src/cmd/7c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2020-08-02 19:48:25 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2020-08-02 19:48:25 +0200
commitcbe45e78f988184938ab63f8bac28632058e5810 (patch)
tree7c897e92986a24dd3d6f1c27016fbf74ede57bf9 /sys/src/cmd/7c
parentcf69bb920a53a2cbecc42e4299b7ed12818d39dc (diff)
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().
Diffstat (limited to 'sys/src/cmd/7c')
-rw-r--r--sys/src/cmd/7c/cgen.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/sys/src/cmd/7c/cgen.c b/sys/src/cmd/7c/cgen.c
index 2e6010b81..d7536aad0 100644
--- a/sys/src/cmd/7c/cgen.c
+++ b/sys/src/cmd/7c/cgen.c
@@ -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)