kervinck / gigatron-rom

System, apps and tooling for the Gigatron TTL microcomputer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

lcc: compiler crash

kervinck opened this issue · comments

$ cat test2.c
struct S {
  char c;                       // 'int c' works...
};
int f(int c, struct S *s)
{
  return s->c = c;              // just 's->c = c' without return works...
}
$ make test2.gt1
Utils/lcc/build/lcc -ILibs -c test2.c -o test2.o
Utils/lcc/build/lcc: fatal error in Utils/lcc/build/rcc
make: *** [test2.o] Error 1
$

Edit: see simplification below

Crash happens in emitasm, before returning:

emitasm(0x7fc2a3012338, ASGNU1, (none)) (action)

In

        act = IR->x._actions[rulenum];
[...]
                act(p);

(Note: rulenum == 26)

Jumping to:

static void inst_strunc(Node p)
[...]
        unsigned to = p->kids[0]->syms[0]->x.regnode->number;

Was introduced with 5916cb2

p->kids[0]->syms[0]->x.regnode is a null pointer.

(Note: p->kids[0]->syms[RX].x.regnode is a null pointer as well)

dumptree(p) after entering inst_strunc() gives:

ASGNU1(VREGP(1), CVUU1(INDIRI2(ADDRFP2(c))))

Simplification of test program that crashes LCC:

char x;
int f(int c)
{
  return x = c;
}

Interestingly, this was commented out in e58bf0c

Utils/lcc/src/gen.c:

//	case CVI: case CVU: case CVP:
//		if (optype(p->op) != F
//		&&  opsize(p->op) <= p->syms[0]->u.c.v.i)
//			p->op = LOAD + opkind(p->op);
//		break;

If we re-enable, the compilation completes without crashing LCC itself. Resulting output:

asm.defun('_f')
asm.push()
asm.ldwi(0xc0)
asm.call('enter')
asm.ldi(6)
asm.call('ldloc')
asm.stw('r7')
asm.ldwi('_x')
asm.stw('r6')
asm.ldw('r7')
asm.poke('r6')
asm.ldw('r7')
asm.stw('rv')
asm.label('.L1')
asm.ldwi(0x600)
asm.call('leave')
asm.ldi(2)
asm.addw('sp')
asm.stw('sp')
asm.ldw('rv')
asm.pop()
asm.ret()
asm.defun('_x')
asm.dx([0] * 1)

This looks correct to me and gttest passes. However......... Libs/Example.c doesn't work anymore. There are many changes in the emitted code (mostly ANDI $ff instructions are now gone) and, for example, __lookup/LUP is broken:

Before:
0cd3  21 48                    LDW   $48                |!H|
0cd5  7f 00                    LUP   $00                |..|
0cd7  82 ff                    ANDI  $ff                |..|
0cd9  f0 3c                    POKE  $3c                |.<|
0cdb  b4 cb                    SYS   134                |..|

After:
0cc2  21 48                    LDW   $48                |!H|
0cc4  7f 00                    LUP   $00                |..|
0cc6  21 3a                    LDW   $3a                |!:| <-- ???
0cc8  f0 3c                    POKE  $3c                |.<|
0cca  b4 cb                    SYS   134                |..|

Close, but no cigar.

This would be a good point to ask @pgavlin for some insights :-)

This is the point at which I wish that I had gone back and commented things up a bit more.

I disabled the conversion of CVI/CVU/CVP to LOAD because it was breaking the backend's assumption that all LOADs are from vAC to a virtual register or vice-versa. We could probably tweak things such that the conversion works, but I'm not 100% certain what those tweaks would be offhand.

It's a bit strange that the register allocator appears not to be allocating those nodes... I'll try running cpp and rcc manually (rather than via the driver) to get debug output.

I can work-around it in my C library and made a note in my updated Libs/stdio/fputc.c that found the issue.

This issue should be closed since glcc fixes it.