// File: /workspace/github_c_makefile_star2_O2/oridb[P]mc/parse/specialize.c
// Function: specializenode
static Node *
specializenode(Node *n, Tysubst *tsmap)
{
	Node *r;
	size_t i;

	if (!n)
		return NULL;
	r = mknode(n->loc, n->type);
	switch (n->type) {
	case Nuse:
		die("Node %s not allowed here\n", nodestr[n->type]);
		break;
	case Nexpr:
		r->expr.op = n->expr.op;
		r->expr.type = tysubst(n->expr.type, tsmap);
		if (n->expr.param)
			r->expr.param = tysubst(n->expr.param, tsmap);
		r->expr.isconst = n->expr.isconst;
		r->expr.nargs = n->expr.nargs;
		r->expr.idx = specializenode(n->expr.idx, tsmap);
		r->expr.args = xalloc(n->expr.nargs * sizeof(Node *));
		for (i = 0; i < n->expr.nargs; i++)
			r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
		break;
	case Nname:
		if (n->name.ns)
			r->name.ns = strdup(n->name.ns);
		r->name.name = strdup(n->name.name);
		break;
	case Nlit:
		r->lit.littype = n->lit.littype;
		r->lit.type = tysubst(n->expr.type, tsmap);
		switch (n->lit.littype) {
		case Lvoid:	break;
		case Lchr:	r->lit.chrval = n->lit.chrval;	break;
		case Lint:	r->lit.intval = n->lit.intval;	break;
		case Lflt:	r->lit.fltval = n->lit.fltval;	break;
		case Lstr:	r->lit.strval = n->lit.strval;	break;
		case Llbl:	r->lit.lblval = n->lit.lblval;	break;
		case Lbool:	r->lit.boolval = n->lit.boolval;	break;
		case Lfunc:	r->lit.fnval = specializenode(n->lit.fnval, tsmap);	break;
		}
		break;
	case Nifstmt:
		r->ifstmt.cond = specializenode(n->ifstmt.cond, tsmap);
		r->ifstmt.iftrue = specializenode(n->ifstmt.iftrue, tsmap);
		r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
		break;
	case Nloopstmt:
		r->loopstmt.scope = mkstab(0);
		r->loopstmt.scope->super = curstab();
		pushstab(r->loopstmt.scope);
		r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
		r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
		r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
		r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
		popstab();
		break;
	case Niterstmt:
		r->iterstmt.elt = specializenode(n->iterstmt.elt, tsmap);
		r->iterstmt.seq = specializenode(n->iterstmt.seq, tsmap);
		r->iterstmt.body = specializenode(n->iterstmt.body, tsmap);
		break;
	case Nmatchstmt:
		r->matchstmt.val = specializenode(n->matchstmt.val, tsmap);
		r->matchstmt.nmatches = n->matchstmt.nmatches;
		r->matchstmt.matches = xalloc(n->matchstmt.nmatches * sizeof(Node *));
		for (i = 0; i < n->matchstmt.nmatches; i++)
			r->matchstmt.matches[i] = specializenode(n->matchstmt.matches[i], tsmap);
		break;
	case Nmatch:
		r->match.pat = specializenode(n->match.pat, tsmap);
		r->match.block = specializenode(n->match.block, tsmap);
		break;
	case Nblock:
		r->block.scope = mkstab(0);
		r->block.scope->super = curstab();
		pushstab(r->block.scope);
		r->block.nstmts = n->block.nstmts;
		r->block.stmts = xalloc(sizeof(Node *) * n->block.nstmts);
		for (i = 0; i < n->block.nstmts; i++)
			r->block.stmts[i] = specializenode(n->block.stmts[i], tsmap);
		popstab();
		break;
	case Ndecl:
		r->decl.did = ndecls;
		/* sym */
		r->decl.env = n->decl.env;
		r->decl.name = specializenode(n->decl.name, tsmap);
		r->decl.type = tysubst(n->decl.type, tsmap);

		/* symflags */
		r->decl.isconst = n->decl.isconst;
		r->decl.isgeneric = n->decl.isgeneric;
		r->decl.isextern = n->decl.isextern;
		r->decl.isglobl = n->decl.isglobl;
		if (curstab())
			putdcl(curstab(), r);

		/* init */
		pushenv(r->decl.env);
		r->decl.init = specializenode(n->decl.init, tsmap);
		popenv(r->decl.env);
		lappend(&decls, &ndecls, r);
		break;
	case Nfunc:
		r->func.scope = mkstab(1);
		r->func.scope->super = curstab();
		r->func.env = n->func.env;
		pushstab(r->func.scope);
		pushenv(r->func.env);
		r->func.type = tysubst(n->func.type, tsmap);
		r->func.nargs = n->func.nargs;
		r->func.args = xalloc(sizeof(Node *) * n->func.nargs);
		for (i = 0; i < n->func.nargs; i++)
			r->func.args[i] = specializenode(n->func.args[i], tsmap);
		r->func.body = specializenode(n->func.body, tsmap);
		popenv(r->func.env);
		popstab();
		break;
	case Nimpl:
		die("trait/impl not implemented");
		break;
	case Nnone:
		die("Nnone should not be seen as node type!");
		break;
	}
	return r;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x1c89f
movq %rsi, %r14
movq %rdi, %r15
movl 0x8(%rdi), %esi
movq (%rdi), %rdi
callq 0x1b610
movq %rax, %rbx
movl 0x8(%r15), %eax
cmpq $0xd, %rax
ja 0x1cc05
leaq 0x168c7(%rip), %rcx     # 0x33128
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x18(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x18(%rbx)
movq 0x20(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x20(%rbx)
movq 0x28(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x28(%rbx)
jmp 0x1cc05
xorl %ebx, %ebx
jmp 0x1cc05
leaq 0x420b3(%rip), %rax     # 0x5e960
movq (%rax), %rax
movq %rax, 0x18(%rbx)
movq 0x38(%r15), %rax
movq %rax, 0x38(%rbx)
movq 0x20(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x20(%rbx)
movq 0x28(%r15), %rdi
movq %r14, %rsi
callq 0x1d25e
movq %rax, 0x28(%rbx)
movb 0x72(%r15), %al
movb %al, 0x72(%rbx)
movb 0x73(%r15), %al
movb %al, 0x73(%rbx)
movb 0x74(%r15), %al
movb %al, 0x74(%rbx)
movb 0x71(%r15), %al
movb %al, 0x71(%rbx)
callq 0x1d859
testq %rax, %rax
je 0x1c912
callq 0x1d859
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1deda
movq 0x38(%rbx), %rdi
callq 0x1d970
movq 0x30(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x30(%rbx)
movq 0x38(%rbx), %rdi
callq 0x1d9bb
leaq 0x4202d(%rip), %rdi     # 0x5e968
leaq 0x4201e(%rip), %rsi     # 0x5e960
movq %rbx, %rdx
callq 0x29b2d
jmp 0x1cc05
movl 0x18(%r15), %eax
movl %eax, 0x18(%rbx)
movq 0x20(%r15), %rdi
movq %r14, %rsi
callq 0x1d25e
movq %rax, 0x20(%rbx)
movl 0x18(%r15), %eax
cmpq $0x6, %rax
ja 0x1cc05
leaq 0x167e5(%rip), %rcx     # 0x33160
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x30(%r15), %eax
movl %eax, 0x30(%rbx)
jmp 0x1cc05
xorl %r12d, %r12d
xorl %edi, %edi
callq 0x1d73b
movq %rax, 0x18(%rbx)
callq 0x1d859
movq 0x18(%rbx), %rcx
movq %rax, (%rcx)
movq 0x18(%rbx), %rdi
callq 0x1d890
movq 0x20(%r15), %rdi
movq %rdi, 0x20(%rbx)
shlq $0x3, %rdi
callq 0x29aa7
movq %rax, 0x28(%rbx)
cmpq 0x20(%r15), %r12
jae 0x1cb5a
movq 0x28(%r15), %rax
movq (%rax,%r12,8), %rdi
movq %r14, %rsi
callq 0x1c82b
movq 0x28(%rbx), %rcx
movq %rax, (%rcx,%r12,8)
incq %r12
jmp 0x1c9c8
xorl %edi, %edi
callq 0x1d73b
movq %rax, 0x38(%rbx)
callq 0x1d859
movq 0x38(%rbx), %rcx
movq %rax, (%rcx)
movq 0x38(%rbx), %rdi
callq 0x1d890
movq 0x18(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x18(%rbx)
movq 0x20(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x20(%rbx)
movq 0x28(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x28(%rbx)
movq 0x30(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x30(%rbx)
jmp 0x1cb5a
movq 0x18(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x18(%rbx)
movq 0x20(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
jmp 0x1cc01
movq 0x18(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x18(%rbx)
movq 0x20(%r15), %rdi
movq %rdi, 0x20(%rbx)
shlq $0x3, %rdi
callq 0x29aa7
movq %rax, 0x28(%rbx)
xorl %r12d, %r12d
cmpq 0x20(%r15), %r12
jae 0x1cc05
movq 0x28(%r15), %rax
movq (%rax,%r12,8), %rdi
movq %r14, %rsi
callq 0x1c82b
movq 0x28(%rbx), %rcx
movq %rax, (%rcx,%r12,8)
incq %r12
jmp 0x1ca9d
pushq $0x1
popq %rdi
callq 0x1d73b
movq %rax, 0x20(%rbx)
callq 0x1d859
movq 0x20(%rbx), %rcx
movq %rax, (%rcx)
movq 0x18(%r15), %rax
movq %rax, 0x18(%rbx)
movq 0x20(%rbx), %rdi
callq 0x1d890
movq 0x18(%rbx), %rdi
callq 0x1d970
movq 0x28(%r15), %rdi
movq %r14, %rsi
callq 0x1d25e
movq %rax, 0x28(%rbx)
movq 0x30(%r15), %rdi
movq %rdi, 0x30(%rbx)
shlq $0x3, %rdi
callq 0x29aa7
movq %rax, 0x38(%rbx)
xorl %r12d, %r12d
cmpq 0x30(%r15), %r12
jae 0x1cb41
movq 0x38(%r15), %rax
movq (%rax,%r12,8), %rdi
movq %r14, %rsi
callq 0x1c82b
movq 0x38(%rbx), %rcx
movq %rax, (%rcx,%r12,8)
incq %r12
jmp 0x1cb1e
movq 0x40(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x40(%rbx)
movq 0x18(%rbx), %rdi
callq 0x1d9bb
callq 0x1d8d4
jmp 0x1cc05
movl 0x18(%r15), %eax
movl %eax, 0x18(%rbx)
movq 0x20(%r15), %rdi
movq %r14, %rsi
callq 0x1d25e
movq %rax, 0x20(%rbx)
movq 0x28(%r15), %rdi
testq %rdi, %rdi
je 0x1cb90
movq %r14, %rsi
callq 0x1d25e
movq %rax, 0x28(%rbx)
movl 0x30(%r15), %eax
movl %eax, 0x30(%rbx)
movq 0x40(%r15), %rax
movq %rax, 0x40(%rbx)
movq 0x48(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x48(%rbx)
movq 0x40(%r15), %rdi
shlq $0x3, %rdi
callq 0x29aa7
movq %rax, 0x50(%rbx)
xorl %r12d, %r12d
cmpq 0x40(%r15), %r12
jae 0x1cc05
movq 0x50(%r15), %rax
movq (%rax,%r12,8), %rdi
movq %r14, %rsi
callq 0x1c82b
movq 0x50(%rbx), %rcx
movq %rax, (%rcx,%r12,8)
incq %r12
jmp 0x1cbc3
movq 0x18(%r15), %rdi
testq %rdi, %rdi
je 0x1cbf8
callq 0x4340
movq %rax, 0x18(%rbx)
movq 0x20(%r15), %rdi
callq 0x4340
movq %rax, 0x20(%rbx)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movq 0x30(%r15), %rax
jmp 0x1cc3e
movsd 0x30(%r15), %xmm0
movsd %xmm0, 0x30(%rbx)
jmp 0x1cc05
movups 0x30(%r15), %xmm0
movups %xmm0, 0x30(%rbx)
jmp 0x1cc05
movq 0x30(%r15), %rdi
movq %r14, %rsi
callq 0x1c82b
movq %rax, 0x30(%rbx)
jmp 0x1cc05
leaq 0x41055(%rip), %rax     # 0x5dca0
movq 0x38(%rax), %rsi
leaq 0x16625(%rip), %rdi     # 0x3327b
xorl %eax, %eax
callq 0x1205c
leaq 0x156ed(%rip), %rdi     # 0x32351
jmp 0x1cc6d
leaq 0x16628(%rip), %rdi     # 0x33295
xorl %eax, %eax
callq 0x1205c