git: 9front

Download patch

ref: c55f98098b80c3dabdf48506779310d32cbc67b4
parent: f759154db8dcdb632ad1233812e0f3a6a5936b34
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 30 19:30:13 EDT 2016

8c: fix double compiling FNX complex lvalue in cgen64()

sugen() calls cgen64() speculatively so that when cgen64() returns
zero, it will fall back and compile 64-bit copy.

the bug was that cgen64() compiled the left hand side and then recursively
called cgen64() again, which didnt handle the memory copy so it returned
zero and sugen() would compile the left hand side again resulting in two
function calls being emited.

some code that reproduced the issue:

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

typedef struct
{
	char x[10];
	vlong a;
} X;

X a;
X *f(void) { return &a; }

void
main(int argc, char *argv[])
{
	f()->a = a.a;
}

producing:

TEXT	f+0(SB),0,$0
	MOVL	$a+0(SB),AX
	RET	,
	RET	,
	TEXT	main+0(SB),0,$0
	CALL	,f+0(SB)
	CALL	,f+0(SB)			<- bug
	MOVL	AX,CX
	LEAL	a+12(SB),DX
	MOVL	(DX),AX
	MOVL	AX,12(CX)
	MOVL	4(DX),AX
	MOVL	AX,16(CX)
	RET	,
	GLOBL	a+0(SB),$20
	END	,

--- a/sys/src/cmd/8c/cgen64.c
+++ b/sys/src/cmd/8c/cgen64.c
@@ -1577,9 +1577,9 @@
 
 	if(nn != Z && nn->complex >= FNX){
 		reglcgen(&nod1, nn, Z);
-		m = cgen64(n, &nod1);
+		cgen(n, &nod1);
 		regfree(&nod1);
-		return m;
+		return 1;
 	}
 
 	switch(n->op) {
--