예제 #1
0
static void
read_unicode_data_txt (
  FILE *f
)
{
  unsigned long c, l;

  l = 0;
  while (fgets (buf, sizeof buf, f))
    {
      int i;
      const char *s = buf;

      l++;

      while (*s == ' ')
	s++;

      if (*s == '#' || *s == '\0' || *s == '\n')
	continue;

      i = sscanf (s, "%lx;%*[^;];%[^; ];%*[^;];%[^; ]", &c, tp_gen, tp_bidi);
      if (i != 3 || c >= FRIBIDI_UNICODE_CHARS)
	die3l ("UnicodeData.txt: invalid input at line %ld: %s", l, s);

      if (type_is (tp_bidi, ignored_bidi_types))
	table[c] = G;
      if (type_is (tp_gen, transparent_general_categories))
	table[c] = T;
    }
}
예제 #2
0
type *type_dereference_decay(type *const ty_ptr)
{
	type *const pointee = type_is_ptr(ty_ptr);
	assert(pointee);

	/* *(void (*)()) does nothing */
	if(type_is(pointee, type_func))
		return ty_ptr;

	/* decay never returns an array type - decay to pointer */
	if(type_is(pointee, type_array))
		return type_decay(pointee);

	return pointee;
}
예제 #3
0
int expr_is_addressable(expr *e)
{
	if(type_is(e->tree_type, type_func))
		return 1;

	return expr_is_lval(e) == LVALUE_USER_ASSIGNABLE;
}
예제 #4
0
const char *decl_asm_spel(decl *d)
{
	if(!d->spel_asm)
		d->spel_asm = func_mangle(d->spel, type_is(d->ref, type_func));

	return d->spel_asm;
}
예제 #5
0
int decl_is_bitfield(decl *d)
{
	if(type_is(d->ref, type_func))
		return 0;

	return !!d->bits.var.field_width;
}
예제 #6
0
static unsigned decl_align1(decl *d)
{
	unsigned al = 0;

	if(!type_is(d->ref, type_func) && d->bits.var.align.resolved)
		al = d->bits.var.align.resolved;

	return al ? al : type_align(d->ref, &d->where);
}
예제 #7
0
unsigned decl_size(decl *d)
{
	if(type_is_void(d->ref))
		die_at(&d->where, "%s is void", d->spel);

	if(!type_is(d->ref, type_func) && d->bits.var.field_width)
		die_at(&d->where, "can't take size of a bitfield");

	return type_size(d->ref, &d->where);
}
예제 #8
0
int decl_should_emit_code(decl *d)
{
	assert(type_is(d->ref, type_func));
	if(!d->bits.func.code)
		return 0;
	if(decl_is_pure_inline(d))
		return 0;
	if(decl_unused_and_internal(d) && !attribute_present(d, attr_used))
		return 0;
	return 1;
}
예제 #9
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;
}
예제 #10
0
파일: type.c 프로젝트: 8l/ucc-c-compiler
unsigned type_align(type *r, const where *from)
{
	struct_union_enum_st *sue;
	type *test;
	attribute *align;

	align = type_attr_present(r, attr_aligned);

	if(align){
		if(align->bits.align){
			consty k;

			const_fold(align->bits.align, &k);

			assert(k.type == CONST_NUM && K_INTEGRAL(k.bits.num));

			return k.bits.num.val.i;
		}

		return platform_align_max();
	}

	if((sue = type_is_s_or_u(r)))
		/* safe - can't have an instance without a ->sue */
		return sue->align;

	if(type_is(r, type_ptr)
	|| type_is(r, type_block))
	{
		return platform_word_size();
	}

	if((test = type_is(r, type_btype)))
		return btype_align(test->bits.type, from);

	if((test = type_is(r, type_array)))
		return type_align(test->ref, from);

	return 1;
}
예제 #11
0
decl *decl_with_init(decl *const d, enum decl_impl_flags flags)
{
	decl *i;

	assert(!type_is(d->ref, type_func));

	for(i = d; i; i = i->proto)
		if(i->bits.var.init.dinit)
			return i;

	for(i = d; i; i = i->impl)
		if(i->bits.var.init.dinit)
			return i;

	if(flags & DECL_INCLUDE_ALIAS){
		decl *alias = decl_alias(d, d);

		if(!type_is(alias->ref, type_func) && alias->bits.var.init.dinit)
			return alias;
	}

	return d;
}
예제 #12
0
type *decl_type_for_bitfield(decl *d)
{
	assert(!type_is(d->ref, type_func));

	if(d->bits.var.field_width){
		const unsigned bits = const_fold_val_i(d->bits.var.field_width);
		const int is_signed = type_is_signed(d->ref);
		unsigned bytes = bits / CHAR_BIT;

		/* need to add on a byte for any leftovers */
		if(bits % CHAR_BIT)
			bytes++;

		return type_nav_MAX_FOR(cc1_type_nav, bytes, is_signed);
	}else{
		return d->ref;
	}
}
예제 #13
0
int decl_defined(decl *d, enum decl_impl_flags flags)
{
	if(type_is(d->ref, type_func)){
		return !!decl_impl(d, flags)->bits.func.code;

	}else{
		/* variable - defined if initialised or non-extern
		 * (check initialisation first, as "extern int x = 3;" is actually "int x = 3;" */
		int explicitly_initialised;

		d = decl_with_init(d, flags);
		explicitly_initialised = d->bits.var.init.dinit && !d->bits.var.init.compiler_generated;

		if(explicitly_initialised)
			return 1;

		if((d->store & STORE_MASK_STORE) == store_extern)
			return 0;
		return 1;
	}
}
예제 #14
0
static void print_struct(struct_union_enum_st *sue)
{
	sue_member **iter;

	if(!sue_complete(sue)){
		idt_printf("incomplete %s %s\n", sue_str(sue), sue->spel);
		return;
	}

	idt_printf("%s %s (size %d):\n", sue_str(sue), sue->spel, sue_size(sue, &sue->where));

	gen_str_indent++;
	for(iter = sue->members; iter && *iter; iter++){
		decl *d = (*iter)->struct_member;

		idt_printf("decl %s:\n", d->spel ? d->spel : "<anon>");
		gen_str_indent++;
		print_decl(d, PDECL_INDENT | PDECL_NEWLINE | PDECL_ATTR);

		if(!type_is(d->ref, type_func)){
#define SHOW_FIELD(nam) idt_printf("." #nam " = %u\n", d->bits.var.nam)
			SHOW_FIELD(struct_offset);

			if(d->bits.var.field_width){
				integral_t v = const_fold_val_i(d->bits.var.field_width);

				gen_str_indent++;

				idt_printf(".field_width = %" NUMERIC_FMT_D "\n", v);

				SHOW_FIELD(struct_offset_bitfield);

				gen_str_indent--;
			}
		}

		gen_str_indent--;
	}
	gen_str_indent--;
}
예제 #15
0
void sanitize_boundscheck(
    expr *elhs, expr *erhs,
    out_ctx *octx,
    const out_val *lhs, const out_val *rhs)
{
    decl *array_decl = NULL;
    type *array_ty;
    expr *expr_sz;
    consty sz;
    const out_val *val;

    if(!(cc1_sanitize & CC1_UBSAN))
        return;

    if(type_is_ptr(elhs->tree_type))
        array_decl = expr_to_declref(elhs, NULL), val = rhs;
    else if(type_is_ptr(erhs->tree_type))
        array_decl = expr_to_declref(erhs, NULL), val = lhs;

    if(!array_decl)
        return;

    if(!(array_ty = type_is(array_decl->ref, type_array)))
        return;

    expr_sz = array_ty->bits.array.size;
    if(!expr_sz)
        return;
    const_fold(expr_sz, &sz);

    if(sz.type != CONST_NUM)
        return;

    if(!K_INTEGRAL(sz.bits.num))
        return;

    /* force unsigned compare, which catches negative indexes */
    sanitize_assert_order(val, op_le, sz.bits.num.val.i, uintptr_ty(), octx, "bounds");
}
예제 #16
0
static type *type_qualify3(
		type *unqualified,
		enum type_qualifier qual,
		int transform_array_qual)
{
	type *ar_ty;
	enum type_qualifier existing;

	if(!qual)
		return unqualified;

	/* if nothing new, no-op */
	existing = type_qual(unqualified);

	if(existing && (qual | existing) == existing){
		return unqualified;
	}

	/* don't double up on qualifiers */
	qual &= ~existing;

	if(transform_array_qual && (ar_ty = type_is(unqualified, type_array))){
		/* const -> array -> int
		 * becomes
		 * array -> const -> int
		 *
		 * C11 6.7.3.9 */

		return type_array_of(
				type_qualify(ar_ty->ref, qual),
				ar_ty->bits.array.size);
	}

	return type_uptree_find_or_new(
			unqualified, type_cast,
			eq_qual, init_qual,
			&qual);
}
예제 #17
0
void dump_decl(decl *d, dump *ctx, const char *desc)
{
	const int is_func = !!type_is(d->ref, type_func);
	type *ty;

	if(!desc){
		if(d->spel){
			desc = is_func ? "function" : "variable";
		}else{
			desc = "type";
		}
	}

	dump_desc_colour_newline(ctx, desc, d, &d->where,
			maybe_colour(ctx->fout, col_desc_decl), 0);

	if(d->proto)
		dump_printf_indent(ctx, 0, " prev %p", (void *)d->proto);

	if(d->spel)
		dump_printf_indent(ctx, 0, " %s", d->spel);

	dump_type(ctx, d->ref);

	if(d->store)
		dump_printf_indent(ctx, 0, " %s", decl_store_to_str(d->store));

	dump_printf_indent(ctx, 0, "\n");

	if(!is_func){
		type *tof = type_skip_non_tdefs(d->ref);
		if(tof->type == type_tdef && !tof->bits.tdef.decl){
			/* show typeof expr */
			dump_inc(ctx);
			dump_expr(tof->bits.tdef.type_of, ctx);
			dump_dec(ctx);
		}

		if(d->bits.var.field_width){
			dump_inc(ctx);
			dump_expr(d->bits.var.field_width, ctx);
			dump_dec(ctx);
		}

		if(!d->spel){
			dump_sue(ctx, d->ref);
		}else if(d->bits.var.init.dinit){
			dump_inc(ctx);
			dump_init(ctx, d->bits.var.init.dinit);
			dump_dec(ctx);
		}
	}

	dump_inc(ctx);
	dump_attributes(d->attr, ctx);
	ty = type_skip_non_attr(d->ref);
	if(ty && ty->type == type_attr)
		dump_attributes(ty->bits.attr, ctx);
	dump_dec(ctx);

	if(is_func && d->bits.func.code){
		funcargs *fa = type_funcargs(d->ref);

		dump_inc(ctx);
		dump_args(fa, ctx);
		dump_stmt(d->bits.func.code, ctx);
		dump_dec(ctx);
	}
}
예제 #18
0
void print_decl(decl *d, enum pdeclargs mode)
{
	if(mode & PDECL_INDENT)
		idt_print();

	if(d->store)
		fprintf(cc1_out, "%s ", decl_store_to_str(d->store));

	if(fopt_mode & FOPT_ENGLISH){
		print_decl_eng(d);
	}else{
		print_type(d->ref, d);
	}

	if(mode & PDECL_SYM_OFFSET){
		if(d->sym){
			const int off = d->sym->type == sym_arg
				? d->sym->loc.arg_offset
				: (int)d->sym->loc.stack_pos;

			fprintf(cc1_out, " (sym %s, pos = %d)",
					sym_to_str(d->sym->type), off);
		}else{
			fprintf(cc1_out, " (no sym)");
		}
	}

	if(mode & PDECL_SIZE && !type_is(d->ref, type_func)){
		if(type_is_complete(d->ref)){
			const unsigned sz = decl_size(d);
			const unsigned align = decl_align(d);

			fprintf(cc1_out, " size %u, align %u", sz, align);
		}else{
			fprintf(cc1_out, " incomplete decl");
		}
	}

	if(mode & PDECL_NEWLINE)
		fputc('\n', cc1_out);

	if(!type_is(d->ref, type_func)
	&& d->bits.var.init.dinit
	&& mode & PDECL_PINIT)
	{
		gen_str_indent++;
		print_decl_init(d->bits.var.init.dinit);
		gen_str_indent--;
	}

	if(mode & PDECL_ATTR){
		gen_str_indent++;
		if(!type_is(d->ref, type_func) && d->bits.var.align)
			idt_printf("[align={as_int=%d, resolved=%d}]\n",
					d->bits.var.align->as_int, d->bits.var.align->resolved);
		print_attribute(d->attr);
		print_type_attr(d->ref);
		gen_str_indent--;
	}

	if((mode & PDECL_FUNC_DESCEND) && DECL_HAS_FUNC_CODE(d)){
		decl **iter;

		gen_str_indent++;

		for(iter = d->bits.func.code->symtab->decls; iter && *iter; iter++){
			sym *s = (*iter)->sym;
			if(s)
				idt_printf("offset of %s = %d\n", (*iter)->spel, s->loc.stack_pos);
		}

		idt_printf("function stack space %d\n",
				d->bits.func.code->symtab->auto_total_size);

		print_stmt(d->bits.func.code);

		gen_str_indent--;
	}
}
예제 #19
0
파일: op.c 프로젝트: 8l/ucc-c-compiler
static void apply_ptr_step(
		out_ctx *octx,
		const out_val **lhs, const out_val **rhs,
		const out_val **div_out)
{
	int l_ptr = !!type_is((*lhs)->t, type_ptr);
	int r_ptr = !!type_is((*rhs)->t, type_ptr);
	int ptr_step;

	if(!l_ptr && !r_ptr)
		return;

	ptr_step = calc_ptr_step((l_ptr ? *lhs : *rhs)->t);

	if(l_ptr ^ r_ptr){
		/* ptr +/- int, adjust the non-ptr by sizeof *ptr */
		const out_val **incdec = (l_ptr ? rhs : lhs);
		out_val *mut_incdec;

		*incdec = mut_incdec = v_dup_or_reuse(octx, *incdec, (*incdec)->t);

		switch(mut_incdec->type){
			case V_CONST_I:
				if(ptr_step == -1){
					*incdec = out_op(octx, op_multiply,
							*incdec,
							vla_size(
								type_next((l_ptr ? *lhs : *rhs)->t),
								octx));

					mut_incdec = NULL; /* safety */
				}else{
					mut_incdec->bits.val_i *= ptr_step;
				}
				break;

			case V_CONST_F:
				assert(0 && "float pointer inc?");

			case V_LBL:
			case V_FLAG:
			case V_REG_SPILT:
				assert(mut_incdec->retains == 1);
				*incdec = (out_val *)v_to_reg(octx, *incdec);

			case V_REG:
			{
				const out_val *n;
				if(ptr_step == -1){
					n = vla_size(
							type_next((l_ptr ? *lhs : *rhs)->t),
							octx);
				}else{
					n = out_new_l(
						octx,
						type_nav_btype(cc1_type_nav, type_intptr_t),
						ptr_step);
				}

				*incdec = (out_val *)out_op(octx, op_multiply, *incdec, n);
				break;
			}
		}

	}else if(l_ptr && r_ptr){
		/* difference - divide afterwards */
		if(ptr_step == -1){
			*div_out = vla_size(type_next((*lhs)->t), octx);
		}else{
			*div_out = out_new_l(octx,
					type_ptr_to(type_nav_btype(cc1_type_nav, type_void)),
					ptr_step);
		}
	}
}
예제 #20
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;
}
예제 #21
0
파일: asm.c 프로젝트: 8l/ucc-c-compiler
static void asm_declare_init(enum section_type sec, decl_init *init, type *tfor)
{
	type *r;

	if(init == DYNARRAY_NULL)
		init = NULL;

	if(!init){
		/* don't initialise flex-arrays */
		if(!type_is_incomplete_array(tfor)){
			asm_declare_pad(sec, type_size(tfor, NULL),
					"null init"/*, type_to_str(tfor)*/);
		}else{
			asm_out_section(sec, ASM_COMMENT " flex array init skipped\n");
		}

	}else if((r = type_is_primitive(tfor, type_struct))){
		/* array of stmts for each member
		 * assumes the ->bits.inits order is member order
		 */
		struct_union_enum_st *const sue = r->bits.type->sue;
		sue_member **mem;
		decl_init **i;
		unsigned end_of_last = 0;
		struct bitfield_val *bitfields = NULL;
		unsigned nbitfields = 0;
		decl *first_bf = NULL;
		expr *copy_from_exp;

		UCC_ASSERT(init->type == decl_init_brace, "unbraced struct");

#define DEBUG(s, ...) /*fprintf(f, "\033[35m" s "\033[m\n", __VA_ARGS__)*/

		i = init->bits.ar.inits;

		/* check for compound-literal copy-init */
		if((copy_from_exp = decl_init_is_struct_copy(init, sue))){
			decl_init *copy_from_init;

			copy_from_exp = expr_skip_lval2rval(copy_from_exp);

			/* the only struct-expression that's possible
			 * in static context is a compound literal */
			assert(expr_kind(copy_from_exp, compound_lit)
					&& "unhandled expression init");

			copy_from_init = copy_from_exp->bits.complit.decl->bits.var.init.dinit;
			assert(copy_from_init->type == decl_init_brace);

			i = copy_from_init->bits.ar.inits;
		}

		/* iterate using members, not inits */
		for(mem = sue->members;
				mem && *mem;
				mem++)
		{
			decl *d_mem = (*mem)->struct_member;
			decl_init *di_to_use = NULL;

			if(i){
				int inc = 1;

				if(*i == NULL)
					inc = 0;
				else if(*i != DYNARRAY_NULL)
					di_to_use = *i;

				if(inc){
					i++;
					if(!*i)
						i = NULL; /* reached end */
				}
			}

			DEBUG("init for %ld/%s, %s",
					mem - sue->members, d_mem->spel,
					di_to_use ? di_to_use->bits.expr->f_str() : NULL);

			/* only pad if we're not on a bitfield or we're on the first bitfield */
			if(!d_mem->bits.var.field_width || !first_bf){
				DEBUG("prev padding, offset=%d, end_of_last=%d",
						d_mem->struct_offset, end_of_last);

				UCC_ASSERT(
						d_mem->bits.var.struct_offset >= end_of_last,
						"negative struct pad, sue %s, member %s "
						"offset %u, end_of_last %u",
						sue->spel, decl_to_str(d_mem),
						d_mem->bits.var.struct_offset, end_of_last);

				asm_declare_pad(sec,
						d_mem->bits.var.struct_offset - end_of_last,
						"prev struct padding");
			}

			if(d_mem->bits.var.field_width){
				if(!first_bf || d_mem->bits.var.first_bitfield){
					if(first_bf){
						DEBUG("new bitfield group (%s is new boundary), old:",
								d_mem->spel);
						/* next bitfield group - store the current */
						bitfields_out(sec, bitfields, &nbitfields, first_bf->ref);
					}
					first_bf = d_mem;
				}

				bitfields = bitfields_add(
						bitfields, &nbitfields,
						d_mem, di_to_use);

			}else{
				if(nbitfields){
					DEBUG("at non-bitfield, prev-bitfield out:", 0);
					bitfields_out(sec, bitfields, &nbitfields, first_bf->ref);
					first_bf = NULL;
				}

				DEBUG("normal init for %s:", d_mem->spel);
				asm_declare_init(sec, di_to_use, d_mem->ref);
			}

			if(type_is_incomplete_array(d_mem->ref)){
				UCC_ASSERT(!mem[1], "flex-arr not at end");
			}else if(!d_mem->bits.var.field_width || d_mem->bits.var.first_bitfield){
				unsigned last_sz = type_size(d_mem->ref, NULL);

				end_of_last = d_mem->bits.var.struct_offset + last_sz;
				DEBUG("done with member \"%s\", end_of_last = %d",
						d_mem->spel, end_of_last);
			}
		}

		if(nbitfields)
			bitfields_out(sec, bitfields, &nbitfields, first_bf->ref);
		free(bitfields);

		/* need to pad to struct size */
		asm_declare_pad(sec,
				sue_size(sue, NULL) - end_of_last,
				"struct tail");

	}else if((r = type_is(tfor, type_array))){
		size_t i, len;
		decl_init **p;
		type *next = type_next(tfor);

		UCC_ASSERT(init->type == decl_init_brace, "unbraced struct");

		if(type_is_incomplete_array(tfor)){
			len = dynarray_count(init->bits.ar.inits);
		}else{
			UCC_ASSERT(type_is_complete(tfor), "incomplete array/type init");
			len = type_array_len(tfor);
		}

		for(i = len, p = init->bits.ar.inits;
				i > 0;
				i--)
		{
			decl_init *this = NULL;
			if(*p){
				this = *p++;

				if(this != DYNARRAY_NULL && this->type == decl_init_copy){
					/*fprintf(f, "# copy from %lu\n", DECL_INIT_COPY_IDX(this, init));*/
					struct init_cpy *icpy = *this->bits.range_copy;
					/* resolve the copy */
					this = icpy->range_init;
				}
			}

			asm_declare_init(sec, this, next);
		}

	}else if((r = type_is_primitive(tfor, type_union))){
		/* union inits are decl_init_brace with spaces up to the first union init,
		 * then NULL/end of the init-array */
		struct_union_enum_st *sue = type_is_s_or_u(r);
		unsigned i, sub = 0;
		decl_init *u_init;

		UCC_ASSERT(init->type == decl_init_brace, "brace init expected");

		/* skip the empties until we get to one */
		for(i = 0; init->bits.ar.inits[i] == DYNARRAY_NULL; i++);

		if((u_init = init->bits.ar.inits[i])){
			decl *mem = sue->members[i]->struct_member;
			type *mem_r = mem->ref;

			/* union init, member at index `i' */
			if(mem->bits.var.field_width){
				/* we know it's integral */
				struct bitfield_val bfv;

				ASSERT_SCALAR(u_init);

				bitfield_val_set(&bfv, u_init->bits.expr, mem->bits.var.field_width);

				asm_declare_init_bitfields(sec, &bfv, 1, mem_r);
			}else{
				asm_declare_init(sec, u_init, mem_r);
			}

			sub = type_size(mem_r, NULL);
		} /* else null union init */

		asm_declare_pad(sec,
				type_size(r, NULL) - sub,
				"union extra");

	}else{
		/* scalar */
		expr *exp = init->bits.expr;

		UCC_ASSERT(init->type == decl_init_scalar, "scalar init expected");

		/* exp->tree_type should match tfor */
		{
			char buf[TYPE_STATIC_BUFSIZ];

			UCC_ASSERT(
					type_cmp(exp->tree_type, tfor, TYPE_CMP_ALLOW_TENATIVE_ARRAY) != TYPE_NOT_EQUAL,
					"mismatching init types: %s and %s",
					type_to_str_r(buf, exp->tree_type),
					type_to_str(tfor));
		}

		/* use tfor, since "abc" has type (char[]){(int)'a', (int)'b', ...} */
		DEBUG("  scalar init for %s:", type_to_str(tfor));
		static_val(sec, tfor, exp);
	}
}
예제 #22
0
void fold_expr_struct(expr *e, symtable *stab)
{
	/*
	 * lhs = any ptr-to-struct expr
	 * rhs = struct member ident
	 */
	const int ptr_expect = !e->expr_is_st_dot;
	struct_union_enum_st *sue;
	char *spel;

	fold_expr_no_decay(e->lhs, stab);
	/* don't fold the rhs - just a member name */

	if(e->rhs){
		UCC_ASSERT(expr_kind(e->rhs, identifier),
				"struct/union member not identifier (%s)", e->rhs->f_str());

		UCC_ASSERT(!e->bits.struct_mem.d, "already have a struct-member");

		spel = e->rhs->bits.ident.spel;
	}else{
		UCC_ASSERT(e->bits.struct_mem.d, "no member specified already?");
		spel = NULL;
	}

	/* we access a struct, of the right ptr depth */
	{
		type *r = e->lhs->tree_type;

		if(ptr_expect){
			type *rtest = type_is(r, type_ptr);

			if(!rtest && !(rtest = type_is(r, type_array)))
				goto err;

			r = rtest->ref; /* safe - rtest is an array */
		}

		if(!(sue = type_is_s_or_u(r))){
err:
			die_at(&e->lhs->where, "'%s' (%s-expr) is not a %sstruct or union (member %s)",
					type_to_str(e->lhs->tree_type),
					e->lhs->f_str(),
					ptr_expect ? "pointer to " : "",
					spel);
		}
	}

	if(!sue_complete(sue)){
		char wbuf[WHERE_BUF_SIZ];

		die_at(&e->lhs->where, "%s incomplete type (%s)\n"
				"%s: note: forward declared here",
				ptr_expect
					? "dereferencing pointer to"
					: "accessing member of",
				type_to_str(e->lhs->tree_type),
				where_str_r(wbuf, &sue->where));
	}

	if(spel){
		/* found the struct, find the member */
		decl *d_mem = struct_union_member_find(sue, spel,
				&e->bits.struct_mem.extra_off, NULL);

		if(!d_mem)
			die_at(&e->where, "%s %s has no member named \"%s\"",
					sue_str(sue), sue->spel, spel);

		e->rhs->tree_type = (e->bits.struct_mem.d = d_mem)->ref;
	}/* else already have the member */

	/*
	 * if it's a.b, convert to (&a)->b for asm gen
	 * e = { lhs = "a", rhs = "b", type = dot }
	 * e = {
	 *   type = ptr,
	 *   lhs = { cast<void *>, expr = { expr = "a", type = addr } },
	 *   rhs = "b",
	 * }
	 */
	if(!ptr_expect){
		expr *cast, *addr;

		addr = expr_new_addr(e->lhs);
		cast = expr_new_cast(addr,
				type_ptr_to(type_nav_btype(cc1_type_nav, type_void)),
				1);

		e->lhs = cast;
		e->expr_is_st_dot = 0;

		FOLD_EXPR(e->lhs, stab);
	}

	/* pull qualifiers from the struct to the member */
	e->tree_type = type_qualify(
			e->bits.struct_mem.d->ref,
			type_qual(e->lhs->tree_type));
}
예제 #23
0
void fold_expr_if(expr *e, symtable *stab)
{
	consty konst;
	type *tt_l, *tt_r;

	FOLD_EXPR(e->expr, stab);
	const_fold(e->expr, &konst);

	fold_check_expr(e->expr, FOLD_CHK_NO_ST_UN, "if-expr");

	if(e->lhs){
		FOLD_EXPR(e->lhs, stab);
		fold_check_expr(e->lhs,
				FOLD_CHK_NO_ST_UN | FOLD_CHK_ALLOW_VOID,
				"if-lhs");
	}

	FOLD_EXPR(e->rhs, stab);
	fold_check_expr(e->rhs,
			FOLD_CHK_NO_ST_UN | FOLD_CHK_ALLOW_VOID,
			"if-rhs");


	/*

	Arithmetic                             Arithmetic                           Arithmetic type after usual arithmetic conversions
	// Structure or union type                Compatible structure or union type   Structure or union type with all the qualifiers on both operands
	void                                   void                                 void
	Pointer to compatible type             Pointer to compatible type           Pointer to type with all the qualifiers specified for the type
	Pointer to type                        NULL pointer (the constant 0)        Pointer to type
	Pointer to object or incomplete type   Pointer to void                      Pointer to void with all the qualifiers specified for the type

	GCC and Clang seem to relax the last rule:
		a) resolve if either is any pointer, not just (void *)
	  b) resolve to a pointer to the incomplete-type
	*/

	tt_l = (e->lhs ? e->lhs : e->expr)->tree_type;
	tt_r = e->rhs->tree_type;

	if(type_is_integral(tt_l) && type_is_integral(tt_r)){
		expr **middle_op = e->lhs ? &e->lhs : &e->expr;

		expr_check_sign("?:", *middle_op, e->rhs, &e->where);

		e->tree_type = op_promote_types(
				op_unknown,
				middle_op, &e->rhs, &e->where, stab);

	}else if(type_is_void(tt_l) || type_is_void(tt_r)){
		e->tree_type = type_nav_btype(cc1_type_nav, type_void);

	}else if(type_cmp(tt_l, tt_r, 0) & TYPE_EQUAL_ANY){
		/* pointer to 'compatible' type */
		e->tree_type = type_qualify(tt_l,
				type_qual(tt_l) | type_qual(tt_r));

	}else{
		/* brace yourself. */
		int l_ptr_null = expr_is_null_ptr(
				e->lhs ? e->lhs : e->expr, NULL_STRICT_VOID_PTR);

		int r_ptr_null = expr_is_null_ptr(e->rhs, NULL_STRICT_VOID_PTR);

		int l_complete = !l_ptr_null && type_is_complete(tt_l);
		int r_complete = !r_ptr_null && type_is_complete(tt_r);

		if((l_complete && r_ptr_null) || (r_complete && l_ptr_null)){
			e->tree_type = l_ptr_null ? tt_r : tt_l;

		}else{
			int l_ptr = l_ptr_null || type_is(tt_l, type_ptr);
			int r_ptr = r_ptr_null || type_is(tt_r, type_ptr);

			if(l_ptr || r_ptr){
				fold_type_chk_warn(
						tt_l, tt_r, &e->where, "?: pointer type mismatch");

				/* qualified void * */
				e->tree_type = type_qualify(
						type_ptr_to(type_nav_btype(cc1_type_nav, type_void)),
						type_qual(tt_l) | type_qual(tt_r));

			}else{
				char buf[TYPE_STATIC_BUFSIZ];

				warn_at(&e->where, "conditional type mismatch (%s vs %s)",
						type_to_str(tt_l), type_to_str_r(buf, tt_r));

				e->tree_type = type_nav_btype(cc1_type_nav, type_void);
			}
		}
	}

	e->freestanding = (e->lhs ? e->lhs : e->expr)->freestanding || e->rhs->freestanding;
}