예제 #1
0
파일: struct.c 프로젝트: ksandstr/muidl
void decode_packed_struct_inline(
	struct llvm_ctx *ctx,
	LLVMValueRef dst,
	IDL_tree ctyp,
	LLVMValueRef first_mr,
	LLVMValueRef bit_offset)
{
	const struct packed_format *fmt = packed_format_of(ctyp);
	assert(fmt != NULL);
	char **names = NULL;
	T s_type = llvm_struct_type(ctx, &names, ctyp);
	int names_len = 0;
	while(names[names_len] != NULL) names_len++;
	assert(names_len == fmt->num_items);
	assert(LLVMCountStructElementTypes(s_type) == names_len);
	T types[MAX(names_len, 1)];
	LLVMGetStructElementTypes(s_type, types);
	int cur_word = 0;
	V wordval = NULL;
	for(int i=0; i<fmt->num_items; i++) {
		const struct packed_item *pi = fmt->items[i];
		int field_ix = strv_lookup(names, pi->name);
		if(field_ix < 0) {
			fprintf(stderr, "%s: not the way to go.\n", __func__);
			abort();
		}

		V start_mr = LLVMBuildAdd(ctx->builder, first_mr,
			CONST_INT(pi->word), tmp_f(ctx->pr, "%s.start.mr", pi->name));
		V dstptr = LLVMBuildStructGEP(ctx->builder, dst, field_ix,
			tmp_f(ctx->pr, "%s.start.ptr", pi->name));
		if(pi->dim > 1) {
			/* array types. TODO */
			fprintf(stderr, "%s: struct-member arrays not implemented\n",
				__func__);
			abort();
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_STRUCT) {
			decode_packed_struct(ctx, &dstptr, pi->type, start_mr,
				CONST_INT(pi->bit));
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_UNION) {
			fprintf(stderr, "%s: union-member types not implemented\n",
				__func__);
			abort();
		} else if(IS_LONGLONG_TYPE(pi->type)) {
			/* long long on a 32-bit architecture. can be #ifdef'd out for
			 * 64-bit targets, where it'd be just a value type.
			 */
			V dtmp = NULL;
			build_read_ipc_parameter(ctx, &dtmp, pi->type,
				start_mr);
			LLVMBuildStore(ctx->builder, dtmp, dstptr);
		} else if(is_value_type(pi->type)) {
			/* word-size and smaller items. */
			if(cur_word != pi->word || wordval == NULL) {
				cur_word = pi->word;
				V old_wv = wordval;
				wordval = build_ipc_input_val_ix(ctx, start_mr,
					tmp_f(ctx->pr, "st.word%d", pi->word));
				if(old_wv == NULL) {
					/* shift it down, since we start at an offset. */
					wordval = LLVMBuildLShr(ctx->builder, wordval,
						bit_offset, "st.bitoffs.shifted");
				}
			}
			V subval = LLVMBuildLShr(ctx->builder, wordval,
				CONST_INT(pi->bit),
				tmp_f(ctx->pr, "st.word%d.shr%d", pi->word, pi->bit));
			if(pi->len < BITS_PER_WORD) {
				subval = LLVMBuildAnd(ctx->builder, subval,
					CONST_WORD((1 << pi->len) - 1),
					tmp_f(ctx->pr, "st.word%d.s%d.m%d", pi->word, pi->bit,
						pi->len));
			}
			subval = LLVMBuildTruncOrBitCast(ctx->builder, subval,
				types[field_ix], "st.val.cast");
			LLVMBuildStore(ctx->builder, subval, dstptr);
		} else if(IS_MAPGRANT_TYPE(pi->type)) {
			/* two words, like peas in a pod */
			assert(pi->bit == 0);
			build_read_ipc_parameter(ctx, &dstptr, pi->type, start_mr);
		} else {
			NOTDEFINED(pi->type);
		}
	}
	g_strfreev(names);
}
예제 #2
0
파일: struct.c 프로젝트: ksandstr/muidl
LLVMValueRef encode_packed_struct_inline(
	struct llvm_ctx *ctx,
	LLVMValueRef first_mr_word,
	LLVMValueRef bit_offset,
	IDL_tree ctyp,
	LLVMValueRef src_base)
{
	const struct packed_format *fmt = packed_format_of(ctyp);
	assert(fmt != NULL);

	/* for sub-word items, bit_offset is required. for word and larger ones it
	 * is forbidden.
	 */
	assert(bit_offset == NULL || (fmt->num_bits < BITS_PER_WORD
		&& fmt->num_words == 1));
	assert(bit_offset != NULL || fmt->num_bits >= BITS_PER_WORD);

	char **names = NULL;
	T s_type = llvm_struct_type(ctx, &names, ctyp);
	int names_len = 0;
	while(names[names_len] != NULL) names_len++;
	assert(names_len == fmt->num_items);
	assert(LLVMCountStructElementTypes(s_type) == names_len);
	T types[MAX(names_len, 1)];
	LLVMGetStructElementTypes(s_type, types);
	V wordval = CONST_WORD(0);
	int cur_word = 0, wordval_fill = 0;
	for(int i=0; i<fmt->num_items; i++) {
		assert(wordval_fill <= BITS_PER_WORD);

		const struct packed_item *pi = fmt->items[i];
		assert(bit_offset == NULL || pi->word == 0);
		int field_ix = strv_lookup(names, pi->name);
		if(field_ix < 0) {
			fprintf(stderr, "%s: not the way to go.\n", __func__);
			abort();
		}

		V start_mr = NULL;
		if(bit_offset == NULL) {
			start_mr = LLVMBuildAdd(ctx->builder, first_mr_word,
				CONST_INT(pi->word), "word.ix");
		}

		/* flush previous word? */
		if(wordval_fill > 0 && cur_word != pi->word) {
			assert(bit_offset == NULL);
			V mr_ix = LLVMBuildAdd(ctx->builder, first_mr_word,
				CONST_INT(cur_word), tmp_f(ctx->pr, "flush.w%d.ix", cur_word));
			LLVMBuildStore(ctx->builder, wordval, UTCB_ADDR_VAL(ctx, mr_ix,
				tmp_f(ctx->pr, "flush.w%d.addr", cur_word)));
			wordval = CONST_WORD(0);
			wordval_fill = 0;
			cur_word = pi->word;
		}

		V valptr = LLVMBuildStructGEP(ctx->builder, src_base, field_ix,
			tmp_f(ctx->pr, "%s.start.ptr", pi->name));
		if(pi->dim > 1) {
			/* array types. TODO */
			fprintf(stderr, "%s: struct-member arrays not implemented\n",
				__func__);
			abort();
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_STRUCT) {
			if(pi->len < BITS_PER_WORD) {
				wordval = encode_packed_struct(ctx, wordval,
					CONST_INT(pi->bit), pi->type, valptr);
				wordval_fill = (wordval_fill + pi->len) % BITS_PER_WORD;
			} else {
				encode_packed_struct(ctx, start_mr, NULL, pi->type, valptr);
			}
		} else if(IDL_NODE_TYPE(pi->type) == IDLN_TYPE_UNION) {
			fprintf(stderr, "%s: union-member types not implemented\n",
				__func__);
			abort();
		} else if(IS_LONGLONG_TYPE(pi->type)) {
			assert(bit_offset == NULL);
			assert(pi->bit == 0 && wordval_fill == 0);
			V val = LLVMBuildLoad(ctx->builder, valptr, "longlong.fld");
			build_write_ipc_parameter(ctx, start_mr, pi->type, &val);
		} else if(is_value_type(pi->type)) {
			/* word-size and smaller items. */
			V val = LLVMBuildLoad(ctx->builder, valptr,
				tmp_f(ctx->pr, "fld.%s.val", pi->name));
			val = LLVMBuildZExtOrBitCast(ctx->builder, val, ctx->wordt,
				tmp_f(ctx->pr, "fld.%s.word", pi->name));
			V bitoffs = CONST_INT(pi->bit);
			V shifted = LLVMBuildShl(ctx->builder, val, bitoffs,
				tmp_f(ctx->pr, "fld.%s.shifted", pi->name));
			wordval = LLVMBuildOr(ctx->builder, shifted, wordval,
				tmp_f(ctx->pr, "word%d.%s.merged", cur_word, pi->name));
			wordval_fill += pi->len;
		} else if(IS_MAPGRANT_TYPE(pi->type)) {
			assert(bit_offset == NULL);
			assert(pi->bit == 0 && wordval_fill == 0);
			build_write_ipc_parameter(ctx, start_mr, pi->type, &valptr);
		} else {
			NOTDEFINED(pi->type);
		}
	}

	if(bit_offset == NULL && wordval_fill > 0) {
		/* flush final partial word if the last item was sub-word */
		V mr_ix = LLVMBuildAdd(ctx->builder, first_mr_word,
			CONST_INT(cur_word), tmp_f(ctx->pr, "flush.w%d.ix", cur_word));
		LLVMBuildStore(ctx->builder, wordval, UTCB_ADDR_VAL(ctx, mr_ix,
			tmp_f(ctx->pr, "flush.w%d.addr", cur_word)));
		wordval = NULL;
	} else if(bit_offset != NULL) {
		/* shift and merge */
		wordval = LLVMBuildOr(ctx->builder, first_mr_word,
			LLVMBuildShl(ctx->builder, wordval, bit_offset, "short.shifted"),
			"rv.merged");
	}

	g_strfreev(names);

	return wordval;
}
예제 #3
0
파일: ast.cpp 프로젝트: NoraAl/banjo
 bool operator()(Qualified_type const& t) { return is_value_type(t.type()); }