示例#1
0
文件: asm.c 项目: mtexier/ucc
enum asm_size asm_type_size(decl *d)
{
	if(decl_ptr_depth(d)){
		return ASM_SIZE_WORD;
	}else{
		switch(d->type->primitive){
			case type_enum:
			case type_int:
				return ASM_SIZE_WORD;

			case type_char:
				return ASM_SIZE_1;

			case type_void:
				ICE("type primitive is void");

			case type_typedef:
				return asm_type_size(d->type->tdef);

			case type_struct:
				ICE("asm_type_size of a struct - can't be word nor byte");

			case type_unknown:
				ICE("type primitive not set");
		}
	}

	ICE("asm_type_size switch error");
	return ASM_SIZE_WORD;
}
示例#2
0
文件: typecheck.cpp 项目: zeux/aike
static void instantiateType(Output& output, Ty* type)
{
	if (UNION_CASE(Instance, t, type))
	{
		assert(t->def || t->generic);

		if (t->def)
		{
			if (UNION_CASE(Struct, def, t->def))
			{
				if (t->tyargs.size == 0)
				{
					for (auto& arg: def->tyargs)
						t->tyargs.push(UNION_NEW(Ty, Unknown, {}));
				}
				else
				{
					if (t->tyargs.size != def->tyargs.size)
						output.error(t->location, "Expected %d type arguments but given %d", int(def->tyargs.size), int(t->tyargs.size));
				}
			}
			else
				ICE("Unknown TyDef kind %d", t->def->kind);
		}
		else
		{
			if (t->tyargs.size != 0)
				output.error(t->location, "Expected 0 type arguments but given %d", int(t->tyargs.size));
		}
	}
}
示例#3
0
文件: typecheck.cpp 项目: zeux/aike
static void typeUnary(Output& output, Ast::Unary* n, TypeConstraints* constraints)
{
	type(output, n->expr, constraints);

	if (n->op == UnaryOpNot)
	{
		n->type = UNION_NEW(Ty, Bool, {});
		typeMustEqual(n->expr, n->type, constraints, output);
	}
	else if (n->op == UnaryOpDeref)
	{
		if (UNION_CASE(Pointer, t, astType(n->expr)))
		{
			n->type = t->element;
		}
		else
		{
			n->type = UNION_NEW(Ty, Unknown, {});

			typeMustEqual(n->expr, UNION_NEW(Ty, Pointer, { n->type }), constraints, output);
		}
	}
	else if (n->op == UnaryOpNew)
	{
		n->type = UNION_NEW(Ty, Pointer, { astType(n->expr) });
	}
	else
	{
		ICE("Unknown UnaryOp %d", n->op);
	}
}
示例#4
0
const char *decl_store_to_str(const enum decl_storage s)
{
	static char buf[16]; /* "inline register" is the longest - just a fit */

	if(s & STORE_MASK_EXTRA){
		char *trail_space = NULL;
		*buf = '\0';

		if((s & STORE_MASK_EXTRA) == store_inline){
			strcpy(buf, "inline ");
			trail_space = buf + strlen("inline");
		}

		strcpy(buf + strlen(buf), decl_store_to_str(s & STORE_MASK_STORE));

		if(trail_space && trail_space[1] == '\0')
			*trail_space = '\0';

		return buf;
	}

	switch(s){
		case store_inline:
			ICE("inline");
		case store_default:
			return "";
		CASE_STR_PREFIX(store, auto);
		CASE_STR_PREFIX(store, static);
		CASE_STR_PREFIX(store, extern);
		CASE_STR_PREFIX(store, register);
		CASE_STR_PREFIX(store, typedef);
	}
	return NULL;
}
示例#5
0
文件: asm.c 项目: mtexier/ucc
void asm_declare_single_part(FILE *f, expr *e)
{
	if(!e->f_gen_1)
		ICE("unexpected global initaliser %s (no gen_1())", e->f_str());

	e->f_gen_1(e, f);
}
示例#6
0
enum visibility decl_visibility(decl *d)
{
	attribute *visibility = attribute_present(d, attr_visibility);
	if(visibility)
		return visibility->bits.visibility;

	switch((d->store & STORE_MASK_STORE)){
		case store_extern:
			/* no explicit visibility, -fvisibility doesn't affect extern decls */
			return VISIBILITY_DEFAULT;

		case store_default:
			/* if it's not in this translation unit it's essentially an extern decl */
			if(!decl_defined(d, 0))
				return VISIBILITY_DEFAULT;
			break;

		case store_static:
			break;

		case store_auto:
		case store_register:
		case store_typedef:
			ICE("shouldn't be calling decl_visibility() on a %s decl",
					decl_store_to_str(d->store & STORE_MASK_STORE));
	}

	return cc1_visibility_default;
}
示例#7
0
enum linkage decl_linkage(decl *d)
{
	/* global scoped or extern */
	decl *p = decl_proto(d);

	/* if first instance is static, we're internal */
	switch((enum decl_storage)(p->store & STORE_MASK_STORE)){
		case store_extern: return linkage_external;
		case store_static: return linkage_internal;

		case store_register:
		case store_auto:
		case store_typedef:
			return linkage_none;

		case store_inline:
			ICE("bad store");

		case store_default:
			break;
	}

	/* either global non-static or local */
	return d->sym && d->sym->type == sym_global
		? linkage_external
		: linkage_none;
}
示例#8
0
文件: type.c 项目: 8l/ucc-c-compiler
static unsigned type_hash2(
		const type *t, unsigned nest_hash(const type *))
{
	unsigned hash = t->type << 20 | (unsigned)(unsigned long)t;

	switch(t->type){
		case type_auto:
			ICE("auto type");

		case type_btype:
			hash |= t->bits.type->primitive | sue_hash(t->bits.type->sue);
			break;

		case type_tdef:
			hash |= nest_hash(t->bits.tdef.type_of->tree_type);
			hash |= 1 << 3;
			break;

		case type_ptr:
			if(t->bits.ptr.decayed_from)
				hash |= nest_hash(t->bits.ptr.decayed_from);
			break;

		case type_array:
			if(t->bits.array.size)
				hash |= nest_hash(t->bits.array.size->tree_type);
			hash |= 1 << t->bits.array.is_static;
			hash |= 1 << t->bits.array.is_vla;
			break;

		case type_block:
		case type_where:
			/* nothing */
			break;

		case type_func:
		{
			decl **i;

			for(i = t->bits.func.args->arglist; i && *i; i++)
				hash |= nest_hash((*i)->ref);

			break;
		}

		case type_cast:
			hash |= t->bits.cast.qual;
			break;

		case type_attr:
			hash |= t->bits.attr->type;
			break;
	}

	return hash;
}
示例#9
0
文件: typecheck.cpp 项目: zeux/aike
static void type(Output& output, Ast* root, TypeConstraints* constraints)
{
#define CALL(name, ...) else if (UNION_CASE(name, n, root)) type##name(output, n, constraints);

	if (false) ;
	UD_AST(CALL)
	else ICE("Unknown Ast kind %d", root->kind);

#undef CALL
}
示例#10
0
文件: type.c 项目: 8l/ucc-c-compiler
unsigned type_size(type *r, const where *from)
{
	switch(r->type){
		case type_auto:
			ICE("__auto_type");

		case type_btype:
			return btype_size(r->bits.type, from);

		case type_tdef:
		{
			decl *d = r->bits.tdef.decl;
			type *sub;

			if(d)
				return type_size(d->ref, from);

			sub = r->bits.tdef.type_of->tree_type;
			UCC_ASSERT(sub, "type_size for unfolded typedef");
			return type_size(sub, from);
		}

		case type_attr:
		case type_cast:
		case type_where:
			return type_size(r->ref, from);

		case type_ptr:
		case type_block:
			return platform_word_size();

		case type_func:
			/* function size is one, sizeof(main) is valid */
			return 1;

		case type_array:
		{
			integral_t sz;

			if(type_is_void(r->ref))
				die_at(from, "array of void");

			if(!r->bits.array.size)
				die_at(from, "array has an incomplete size");

			sz = const_fold_val_i(r->bits.array.size);

			return sz * type_size(r->ref, from);
		}
	}

	ucc_unreach(0);
}
示例#11
0
文件: asm.c 项目: 8l/ucc-c-compiler
static void static_val(enum section_type sec, type *ty, expr *e)
{
	consty k;

	memset(&k, 0, sizeof k);

	const_fold(e, &k);

	switch(k.type){
		case CONST_NEED_ADDR:
		case CONST_NO:
			ICE("non-constant expr-%s const=%d%s",
					e->f_str(),
					k.type,
					k.type == CONST_NEED_ADDR ? " (needs addr)" : "");
			break;

		case CONST_NUM:
			if(K_FLOATING(k.bits.num)){
				/* asm fp const */
				asm_out_fp(sec, ty, k.bits.num.val.f);
			}else{
				char buf[INTEGRAL_BUF_SIZ];
				asm_declare_init_type(sec, ty);
				integral_str(buf, sizeof buf, k.bits.num.val.i, e->tree_type);
				asm_out_section(sec, "%s", buf);
			}
			break;

		case CONST_ADDR:
			asm_declare_init_type(sec, ty);
			if(k.bits.addr.is_lbl)
				asm_out_section(sec, "%s", k.bits.addr.bits.lbl);
			else
				asm_out_section(sec, "%ld", k.bits.addr.bits.memaddr);
			break;

		case CONST_STRK:
			stringlit_use(k.bits.str->lit); /* must be before the label access */
			asm_declare_init_type(sec, ty);
			asm_out_section(sec, "%s", k.bits.str->lit->lbl);
			break;
	}

	/* offset in bytes, no mul needed */
	if(k.offset)
		asm_out_section(sec, " + %ld", k.offset);
	asm_out_section(sec, "\n");
}
示例#12
0
文件: asm.c 项目: 8l/ucc-c-compiler
void asm_out_fp(enum section_type sec, type *ty, floating_t f)
{
	switch(type_primitive(ty)){
		case type_float:
			{
				union { float f; unsigned u; } u;
				u.f = f;
				asm_out_section(sec, ".long %u # float %f\n", u.u, u.f);
				break;
			}

		case type_double:
			{
				union { double d; unsigned long ul; } u;
				u.d = f;
				asm_out_section(sec, ".quad %lu # double %f\n", u.ul, u.d);
				break;
			}
		case type_ldouble:
			ICE("TODO");
		default:
			ICE("bad float type");
	}
}
示例#13
0
文件: typecheck.cpp 项目: zeux/aike
static void typeBinary(Output& output, Ast::Binary* n, TypeConstraints* constraints)
{
	type(output, n->left, constraints);
	type(output, n->right, constraints);

	if (n->op == BinaryOpAnd || n->op == BinaryOpOr)
	{
		n->type = UNION_NEW(Ty, Bool, {});

		typeMustEqual(n->left, n->type, constraints, output);
		typeMustEqual(n->right, n->type, constraints, output);
	}
	else
	{
		ICE("Unknown BinaryOp %d", n->op);
	}
}
示例#14
0
static void fold_const_expr_if(expr *e, consty *k)
{
	consty consts[3];
	int res;

	const_fold(e->expr, &consts[0]);
	const_fold(e->rhs,  &consts[2]);

	if(e->lhs)
		const_fold(e->lhs, &consts[1]);
	else
		consts[1] = consts[0];

	/* only evaluate lhs/rhs' constness if we need to */
	if(!CONST_AT_COMPILE_TIME(consts[0].type)){
		k->type = CONST_NO;
		return;
	}

	switch(consts[0].type){
		case CONST_NUM:
		{
			numeric *n = &consts[0].bits.num;
			res = n->suffix & VAL_FLOATING ? n->val.f : n->val.i;
			break;
		}
		case CONST_ADDR:
		case CONST_STRK:
			res = 1;
			break;

		case CONST_NEED_ADDR:
		case CONST_NO:
			ICE("buh");
	}

	res = res ? 1 : 2; /* index into consts */

	if(!CONST_AT_COMPILE_TIME(consts[res].type)){
		k->type = CONST_NO;
	}else{
		memcpy_safe(k, &consts[res]);
		k->nonstandard_const = consts[res == 1 ? 2 : 1].nonstandard_const;
	}
}
示例#15
0
文件: impl.c 项目: 8l/ucc-c-compiler
enum flag_cmp op_to_flag(enum op_type op)
{
	switch(op){
#define OP(x) case op_ ## x: return flag_ ## x
		OP(eq);
		OP(ne);
		OP(le);
		OP(lt);
		OP(ge);
		OP(gt);
#undef OP

		default:
			break;
	}

	ICE("invalid op");
	return -1;
}
示例#16
0
const out_val *gen_expr_funcall(const expr *e, out_ctx *octx)
{
	const out_val *fn_ret;

	if(0){
		out_comment(octx, "start manual __asm__");
		ICE("same");
#if 0
		fprintf(cc_out[SECTION_TEXT], "%s\n", e->funcargs[0]->data_store->data.str);
#endif
		out_comment(octx, "end manual __asm__");
	}else{
		/* continue with normal funcall */
		const out_val *fn, **args = NULL;

		fn = gen_expr(e->expr, octx);

		if(e->funcargs){
			expr **aiter;

			for(aiter = e->funcargs; *aiter; aiter++){
				expr *earg = *aiter;
				const out_val *arg;

				/* should be of size int or larger (for integral types)
				 * or double (for floating types)
				 */
				arg = gen_expr(earg, octx);
				dynarray_add(&args, arg);
			}
		}

		/* consumes fn and args */
		fn_ret = gen_call(e->expr, NULL, fn, args, octx, &e->expr->where);

		dynarray_free(const out_val **, args, NULL);

		if(!expr_func_passable(GEN_CONST_CAST(expr *, e)))
			out_ctrl_end_undefined(octx);
	}

	return fn_ret;
}
示例#17
0
文件: asm.c 项目: 8l/ucc-c-compiler
int asm_table_lookup(type *r)
{
	int sz;
	int i;

	if(!r)
		sz = type_primitive_size(type_long); /* or ptr */
	else if(type_is(r, type_array) || type_is(r, type_func))
		/* special case for funcs and arrays */
		sz = platform_word_size();
	else
		sz = type_size(r, NULL);

	for(i = 0; i < ASM_TABLE_LEN; i++)
		if(asm_type_table[i].sz == sz)
			return i;

	ICE("no asm type index for byte size %d", sz);
	return -1;
}
示例#18
0
文件: str.c 项目: 8l/ucc-c-compiler
static char *word_strstr(char *haystack, char *needle)
{
	const int nlen = strlen(needle);
	char *i;

	if(!strstr(haystack, needle))
		return NULL;

	for(i = haystack; *i; i++)
		if(*i == '"'){
			i = str_quotefin(i + 1);
			if(!i)
				ICE("terminating quote not found\nhaystack = >>%s<<\nneedle = >>%s<<",
						haystack, needle);
		}else if(!strncmp(i, needle, nlen)){
			return i;
		}

	return NULL;
}
示例#19
0
stmt *stmt_new(
		func_fold_stmt *f_fold,
		func_gen_stmt *f_gen,
		func_gen_stmt *f_gen_style,
		func_str_stmt *f_str,
		void (*init)(stmt *),
		symtable *stab)
{
	stmt *s = umalloc(sizeof *s);
	where_cc1_current(&s->where);

	UCC_ASSERT(stab, "no symtable for statement");
	s->symtab = stab;

	s->f_fold = f_fold;

	switch(cc1_backend){
		case BACKEND_ASM:
			s->f_gen = f_gen;
			break;
		case BACKEND_PRINT:
		case BACKEND_STYLE:
			s->f_gen = f_gen_style;
			break;
		default:
			ICE("bad backend");
	}

	s->f_str  = f_str;

	init(s);

	s->kills_below_code =
		   stmt_kind(s, break)
		|| stmt_kind(s, return)
		|| stmt_kind(s, goto)
		|| stmt_kind(s, continue);

	return s;
}
示例#20
0
static void preproc_pop(void)
{
	if(!file_stack_idx)
		ICE("file stack idx = 0 on pop()");

	free(file_stack[file_stack_idx].fname);

	file_stack_idx--;

#ifdef DO_CHDIR
	if(curwdfd != -1){
		if(fchdir(curwdfd) == -1)
			ppdie(p, "chdir(-): %s", strerror(errno));
		close(curwdfd);
	}
#endif

	/* restore state */
	current_line  = file_stack[file_stack_idx].line_no;
	set_current_fname(file_stack[file_stack_idx].fname);

	preproc_emit_line_info_top(LINEINFO_RETURN_TO_FILE);
}
示例#21
0
void preproc_pop(void)
{
	if(!file_stack_idx)
		ICE("file stack idx = 0 on pop()");

	free(file_stack[file_stack_idx].fname);

	file_stack_idx--;

#ifdef DO_CHDIR
	if(curwdfd != -1){
		if(fchdir(curwdfd) == -1)
			ppdie(p, "chdir(-): %s", strerror(errno));
		close(curwdfd);
	}
#endif

	/* restore state */
	current_line  = file_stack[file_stack_idx].line_no - 1;
	current_fname = file_stack[file_stack_idx].fname;

	preproc_out_info();
}
示例#22
0
char *word_strstr(char *haystack, char *needle)
{
	const int nlen = strlen(needle);
	char *i;

	if(!strstr(haystack, needle))
		return NULL;

	for(i = haystack; *i; i++)
		if(*i == '"'){
refind:
			i = strchr(i + 1, '"');
			if(!i)
				ICE("terminating quote not found\nhaystack = >>%s<<\nneedle = >>%s<<",
						haystack, needle);
			else if(i[-1] == '\\')
				goto refind;
		}else if(!strncmp(i, needle, nlen)){
			return i;
		}

	return NULL;
}
示例#23
0
void expr_mutate(expr *e, func_mutate_expr *f,
		func_fold *f_fold,
		func_str *f_str,
		func_gen *f_gen,
		func_gen *f_gen_str,
		func_gen *f_gen_style
		)
{
	e->f_fold = f_fold;
	e->f_str  = f_str;

	switch(cc1_backend){
		case BACKEND_ASM:   e->f_gen = f_gen;       break;
		case BACKEND_PRINT: e->f_gen = f_gen_str;   break;
		case BACKEND_STYLE: e->f_gen = f_gen_style; break;
		default: ICE("bad backend");
	}

	e->f_const_fold = NULL;
	e->f_lea = NULL;

	f(e);
}
示例#24
0
文件: typecheck.cpp 项目: zeux/aike
static void typeFnDecl(Output& output, Ast::FnDecl* n, TypeConstraints* constraints)
{
	if (n->body)
	{
		type(output, n->body, constraints);

		if (UNION_CASE(Function, fnty, n->var->type))
		{
			if (fnty->ret->kind != Ty::KindVoid)
				typeMustEqual(n->body, fnty->ret, constraints, output);
		}
		else
			ICE("FnDecl type is not Function");
	}
	else
	{
		if (!constraints)
			typeMustKnow(n->var->type, output, n->var->location);
	}

	if (!n->type)
		n->type = UNION_NEW(Ty, Void, {});
}
示例#25
0
static char *read_line(void)
{
	FILE *f;
	char *line;
	int newline;

re_read:
	if(file_stack_idx < 0)
		ICE("file stack idx = 0 on read()");
	f = file_stack[file_stack_idx].file;

	line = fline(f, &newline);

	if(!line){
		if(ferror(f))
			die("read():");

		fclose(f);
		if(file_stack_idx > 0){
			free(dirname_pop());
			preproc_pop();
			goto re_read;
		}else{
			if(!prev_newline){
				CPP_WARN(WNEWLINE, "no newline at end-of-file");
			}
		}

		return NULL;
	}

	prev_newline = newline;
	current_line++;

	return line;
}
示例#26
0
static void print_decl_init(decl_init *di)
{
	switch(di->type){
		case decl_init_scalar:
			idt_printf("scalar:\n");
			gen_str_indent++;
			print_expr(di->bits.expr);
			gen_str_indent--;
			break;

		case decl_init_copy:
			ICE("copy in print");
			break;

		case decl_init_brace:
		{
			decl_init *s;
			int i;

			idt_printf("brace\n");

			gen_str_indent++;
			for(i = 0; (s = di->bits.ar.inits[i]); i++){
				if(s == DYNARRAY_NULL){
					idt_printf("[%d] = <zero init>\n", i);
				}else if(s->type == decl_init_copy){
					idt_printf("[%d] = copy from range_store[%ld]\n",
							i, (long)DECL_INIT_COPY_IDX(s, di));
				}else{
					const int need_brace = s->type == decl_init_brace;

					/* ->member not printed */
#ifdef DINIT_WITH_STRUCT
					if(s->spel)
						idt_printf(".%s", s->spel);
					else
#endif
						idt_printf("[%d]", i);

					fprintf(cc1_out, " = %s\n", need_brace ? "{" : "");

					gen_str_indent++;
					print_decl_init(s);
					gen_str_indent--;

					if(need_brace)
						idt_printf("}\n");
				}
			}
			gen_str_indent--;

			if(di->bits.ar.range_inits){
				struct init_cpy *icpy;

				idt_printf("range store:\n");
				gen_str_indent++;

				for(i = 0; (icpy = di->bits.ar.range_inits[i]); i++){
					idt_printf("store[%d]:\n", i);
					gen_str_indent++;
					print_decl_init(icpy->range_init);
					gen_str_indent--;
					if(icpy->first_instance){
						idt_printf("first expr:\n");
						gen_str_indent++;
						print_expr(icpy->first_instance);
						gen_str_indent--;
					}
				}
				gen_str_indent--;
			}
		}
	}
}
示例#27
0
static void print_type_eng(type *ref)
{
	if(!ref)
		return;

	print_type_eng(ref->ref);

	switch(ref->type){
		case type_auto:
			ICE("__auto_type");

		case type_cast:
			if(ref->bits.cast.is_signed_cast)
				fprintf(cc1_out, "%s ", ref->bits.cast.signed_true ? "signed" : "unsigned");
			else
				fprintf(cc1_out, "%s", type_qual_to_str(ref->bits.cast.qual, 1));
			break;

		case type_ptr:
			fprintf(cc1_out, "pointer to ");
			break;

		case type_block:
			fprintf(cc1_out, "block returning ");
			break;

		case type_func:
		{
#ifdef ENGLISH_PRINT_ARGLIST
			funcargs *fargs = ref->bits.func.args;
			decl **iter;
#endif

			fputs("function", cc1_out);

#ifdef ENGLISH_PRINT_ARGLIST
			fputc('(', cc1_out);
			if(fargs->arglist){

				for(iter = fargs->arglist; iter && *iter; iter++){
					print_decl(*iter, PDECL_NONE);
					if(iter[1])
						fputs(", ", cc1_out);
				}

				if(fargs->variadic)
					fputs("variadic", cc1_out);

			}else{
				fprintf(cc1_out, "taking %s arguments", fargs->args_void ? "no" : "unspecified");
			}
			fputc(')', cc1_out);
#endif
			fputs(" returning ", cc1_out);

			break;
		}

		case type_array:
			fputs("array[", cc1_out);
			if(ref->bits.array.size)
				print_expr_val(ref->bits.array.size);
			fputs("] of ", cc1_out);
			break;

		case type_btype:
			fprintf(cc1_out, "%s", btype_to_str(ref->bits.type));
			break;

		case type_tdef:
		case type_attr:
			ICE("TODO");
		case type_where:
			break;
	}
}
示例#28
0
文件: resolve.cpp 项目: zeux/aike
static bool resolveNamesNode(ResolveNames& rs, Ast* root)
{
	// TODO: refactor
	if (root->kind != Ast::KindFnDecl && root->kind != Ast::KindTyDecl)
		visitAstTypes(root, resolveType, rs);

	if (UNION_CASE(Ident, n, root))
	{
		n->targets = resolveBindings(rs.variables.findAll(n->name));

		if (n->targets.size == 0)
			rs.output->error(n->location, "Unresolved identifier %s", n->name.str().c_str());
	}
	else if (UNION_CASE(Block, n, root))
	{
		auto scope = rs.top();

		// Bind all declarations from this scope to allow recursive references
		for (auto& c: n->body)
			resolveDecl(rs, c);

		visitAstInner(root, resolveNamesNode, rs);

		rs.pop(scope);
	}
	else if (UNION_CASE(Module, n, root))
	{
		assert(!rs.module);
		rs.module = n;

		for (auto& i: n->autoimports)
			resolveImport(rs, i);

		visitAstInner(root, resolveNamesNode, rs);
	}
	else if (UNION_CASE(For, n, root))
	{
		auto scope = rs.top();

		visitAst(n->expr, resolveNamesNode, rs);

		rs.variables.push(n->var->name, n->var);

		if (n->index)
			rs.variables.push(n->index->name, n->index);

		visitAst(n->body, resolveNamesNode, rs);

		rs.pop(scope);
	}
	else if (UNION_CASE(FnDecl, n, root))
	{
		// establish lexical parent-child relationship
		n->parent = rs.functions.empty() ? nullptr : rs.functions.back();
		n->module = rs.module;

		auto scope = rs.top();

		for (auto& a: n->tyargs)
		{
			UNION_CASE(Generic, g, a);
			assert(g);

			rs.generics.push(g->name, a);
		}

		visitAstTypes(root, resolveType, rs);

		if (n->body)
		{
			for (auto& a: n->args)
				rs.variables.push(a->name, a);

			rs.functions.push_back(n);

			visitAstInner(root, resolveNamesNode, rs);

			rs.functions.pop_back();
		}

		rs.pop(scope);
	}
	else if (UNION_CASE(TyDecl, n, root))
	{
		auto scope = rs.top();

		if (UNION_CASE(Struct, d, n->def))
		{
			for (auto& a: d->tyargs)
			{
				UNION_CASE(Generic, g, a);
				assert(g);

				rs.generics.push(g->name, a);
			}
		}
		else
			ICE("Unknown TyDef kind %d", n->def->kind);

		visitAstTypes(root, resolveType, rs);
		visitAstInner(root, resolveNamesNode, rs);

		rs.pop(scope);
	}
	else if (UNION_CASE(VarDecl, n, root))
	{
		visitAstInner(root, resolveNamesNode, rs);

		rs.variables.push(n->var->name, n->var);
	}
	else if (UNION_CASE(Import, n, root))
	{
		resolveImport(rs, n->name);
	}
	else
		return false;

	return true;
}
示例#29
0
文件: type.c 项目: 8l/ucc-c-compiler
static void type_add_str(
		type *r, const char *spel,
		int *need_spc,
		char **bufp, int *sz,
		type *stop_at)
{
	int need_paren;
	type *array_qual = NULL, *next_ty;

	if(!r){
		/* reached the bottom/end - spel */
		if(spel){
			ADD_SPC();
			BUF_ADD("%s", spel);
			*need_spc = 0;
		}
		return;
	}

	if(stop_at && r->tmp == stop_at){
		type_add_str(r->tmp, spel, need_spc, bufp, sz, stop_at);
		return;
	}

	type_add_str_pre(r, &need_paren, need_spc, bufp, sz);

	next_ty = r->tmp;
	if(r->type == type_array && r->tmp && r->tmp->type == type_cast){
		array_qual = r->tmp;
		next_ty = array_qual->tmp;
	}

	type_add_str(next_ty, spel, need_spc, bufp, sz, stop_at);

	switch(r->type){
		case type_auto:
			ICE("__auto_type");

		case type_tdef:
			/* tdef "aka: %s" handled elsewhere */
		case type_attr:
			/* attribute not handled here */
		case type_btype:
		case type_cast:
		case type_where:
			/**/
		case type_block:
			break;

		case type_func:
			type_add_funcargs(r->bits.func.args, need_spc, bufp, sz);
			break;

		case type_ptr:
#ifdef SHOW_DECAYED_ARRAYS
			if(!r->bits.ptr.size)
#endif
				break;
			/* fall */
		case type_array:
		{
			const char *sz_space = "";

			BUF_ADD("[");
			if(r->bits.array.is_vla == 0 && r->bits.array.is_static){
				BUF_ADD("static");
				sz_space = " ";
			}

			if(array_qual){
				BUF_ADD("%s%s", sz_space,
						type_qual_to_str(array_qual->bits.cast.qual, 0));
				sz_space = " ";
			}

			switch(r->bits.array.is_vla){
				case 0:
					if(r->bits.array.size){
						BUF_ADD(
								"%s%" NUMERIC_FMT_D,
								sz_space,
								const_fold_val_i(r->bits.array.size));
					}
					break;
				case VLA:
					BUF_ADD("vla");
					break;
				case VLA_STAR:
					BUF_ADD("*");
					break;
			}
			BUF_ADD("]");
			break;
		}
	}

	if(need_paren)
		BUF_ADD(")");
#undef IS_PTR
}
示例#30
0
文件: type.c 项目: 8l/ucc-c-compiler
static enum type_cmp type_cmp_r(
		type *const orig_a,
		type *const orig_b,
		enum type_cmp_opts opts)
{
	enum type_cmp ret;
	type *a, *b;
	int subchk = 1;

	if(!orig_a || !orig_b)
		return orig_a == orig_b ? TYPE_EQUAL : TYPE_NOT_EQUAL;

	a = type_skip_all(orig_a);
	b = type_skip_all(orig_b);

	/* array/func decay takes care of any array->ptr checks */
	if(a->type != b->type){
		/* allow _Bool <- pointer */
		if(type_is_primitive(a, type__Bool) && type_is_ptr(b))
			return TYPE_CONVERTIBLE_IMPLICIT;

		/* allow int <-> ptr (or block) */
		if((type_is_ptr_or_block(a) && type_is_integral(b))
		|| (type_is_ptr_or_block(b) && type_is_integral(a)))
		{
			return TYPE_CONVERTIBLE_EXPLICIT;
		}

		/* allow void <- anything */
		if(type_is_void(a))
			return TYPE_CONVERTIBLE_IMPLICIT;

		/* allow block <-> fnptr */
		if((type_is_fptr(a) && type_is(b, type_block))
		|| (type_is_fptr(b) && type_is(a, type_block)))
		{
			return TYPE_CONVERTIBLE_EXPLICIT;
		}

		return TYPE_NOT_EQUAL;
	}

	switch(a->type){
		case type_auto:
			ICE("__auto_type");

		case type_btype:
			subchk = 0;
			ret = btype_cmp(a->bits.type, b->bits.type);
			break;

		case type_array:
			if(a->bits.array.is_vla || b->bits.array.is_vla){
				/* fine, pretend they're equal even if different expressions */
				ret = TYPE_EQUAL_TYPEDEF;

			}else{
				const int a_has_sz = !!a->bits.array.size;
				const int b_has_sz = !!b->bits.array.size;

				if(a_has_sz && b_has_sz){
					integral_t av = const_fold_val_i(a->bits.array.size);
					integral_t bv = const_fold_val_i(b->bits.array.size);

					if(av != bv)
						return TYPE_NOT_EQUAL;
				}else if(a_has_sz != b_has_sz){
					if((opts & TYPE_CMP_ALLOW_TENATIVE_ARRAY) == 0)
						return TYPE_NOT_EQUAL;
				}
			}

			/* next */
			break;

		case type_block:
		case type_ptr:
			break;

		case type_cast:
		case type_tdef:
		case type_attr:
		case type_where:
			ICE("should've been skipped");

		case type_func:
			switch(funcargs_cmp(a->bits.func.args, b->bits.func.args)){
				case FUNCARGS_EXACT_EQUAL:
				case FUNCARGS_IMPLICIT_CONV:
					break;
				default:
					/* "void (int)" and "void (int, int)" aren't equal,
					 * but a cast can soon fix it */
					return TYPE_CONVERTIBLE_EXPLICIT;
			}
			break;
	}

	if(subchk)
		ret = type_cmp_r(a->ref, b->ref, opts);

	if(ret == TYPE_NOT_EQUAL
	&& a->type == type_func)
	{
		/* "int (int)" and "void (int)" aren't equal - but castable */
		ret = TYPE_CONVERTIBLE_EXPLICIT;
	}

	if(ret == TYPE_NOT_EQUAL
	&& a->type == type_ptr
	&& fopt_mode & FOPT_PLAN9_EXTENSIONS)
	{
		/* allow b to be an anonymous member of a, if pointers */
		struct_union_enum_st *a_sue = type_is_s_or_u(a),
		                     *b_sue = type_is_s_or_u(b);

		if(a_sue && b_sue /* already know they aren't equal */){
			/* b_sue has an a_sue,
			 * the implicit cast adjusts to return said a_sue */
			if(struct_union_member_find_sue(b_sue, a_sue))
				return TYPE_CONVERTIBLE_IMPLICIT;
		}
	}

	/* allow ptr <-> ptr */
	if(ret == TYPE_NOT_EQUAL && type_is_ptr(a) && type_is_ptr(b))
		ret = TYPE_CONVERTIBLE_EXPLICIT;

	/* char * and int * are explicitly conv.,
	 * even though char and int are implicit */
	if(ret == TYPE_CONVERTIBLE_IMPLICIT && a->type == type_ptr)
		ret = TYPE_CONVERTIBLE_EXPLICIT;

	if(a->type == type_ptr || a->type == type_block){
		switch(ret){
#define MAP(a, b) case a: ret = b; break
			MAP(TYPE_QUAL_ADD, TYPE_QUAL_POINTED_ADD);
			MAP(TYPE_QUAL_SUB, TYPE_QUAL_POINTED_SUB);
			MAP(TYPE_QUAL_POINTED_ADD, TYPE_QUAL_NESTED_CHANGE);
			MAP(TYPE_QUAL_POINTED_SUB, TYPE_QUAL_NESTED_CHANGE);
#undef MAP
			default:
				break;
		}
	}

	if(ret & TYPE_EQUAL_ANY){
		enum type_qualifier a_qual = type_qual(orig_a);
		enum type_qualifier b_qual = type_qual(orig_b);

		if(a_qual && b_qual){
			switch(type_qual_cmp(a_qual, b_qual)){
				case -1:
					/* a has more */
					ret = TYPE_QUAL_ADD;
					break;
				case 1:
					/* b has more */
					ret = TYPE_QUAL_SUB;
					break;
			}
		}else if(a_qual){
			ret = TYPE_QUAL_ADD;
		}else if(b_qual){
			ret = TYPE_QUAL_SUB;
		} /* else neither are casts */
	}

	if(ret == TYPE_EQUAL){
		int at = orig_a->type == type_tdef;
		int bt = orig_b->type == type_tdef;

		if(at != bt){
			/* one is a typedef */
			ret = TYPE_EQUAL_TYPEDEF;
		}else if(at){
			/* both typedefs */
			if(orig_a->bits.tdef.decl != orig_b->bits.tdef.decl){
				ret = TYPE_EQUAL_TYPEDEF;
			}
		}
		/* else no typedefs */
	}

	return ret;
}