unsigned get_type_alignment(type_t const *const type) { switch (type->kind) { case TYPE_ERROR: return 0; case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: case TYPE_ENUM: return get_atomic_type_alignment(type->atomic.akind); case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: return type->compound.compound->alignment; case TYPE_FUNCTION: case TYPE_VOID: return 1; /* GCC extension. */ case TYPE_REFERENCE: case TYPE_POINTER: return pointer_properties.alignment; case TYPE_ARRAY: return get_type_alignment(type->array.element_type); case TYPE_TYPEDEF: { il_alignment_t const alignment = get_type_alignment(type->typedeft.typedefe->type); return MAX(alignment, type->typedeft.typedefe->alignment); } case TYPE_TYPEOF: return get_type_alignment(type->typeoft.typeof_type); case TYPE_BUILTIN_TEMPLATE: break; } panic("invalid type"); }
/** * get alignment of a type when used inside a compound. * Some ABIs are broken and alignment inside a compound is different from * recommended alignment of a type */ static unsigned get_type_alignment_compound(type_t *const type) { assert(!is_typeref(type)); if (type->kind == TYPE_ATOMIC) return atomic_type_properties[type->atomic.akind].struct_alignment; return get_type_alignment(type); }
static ir_tarval *alignof_to_tarval(const typeprop_expression_t *expression) { unsigned const alignment = expression->tp_expression ? get_object_alignment(expression->tp_expression) : get_type_alignment(expression->type); ir_mode *const mode = get_ir_mode_storage(expression->base.type); return new_tarval_from_long(alignment, mode); }
static unsigned get_address_alignment(expression_t const *const expr) { if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { return get_object_alignment(expr->unary.value); } else { type_t *const type = skip_typeref(expr->base.type); assert(is_type_pointer(type)); return get_type_alignment(type->pointer.points_to); } }
static unsigned get_object_alignment(expression_t const *const expr) { entity_t *ent; switch (expr->kind) { case EXPR_ARRAY_ACCESS: return get_address_alignment(expr->array_access.array_ref); case EXPR_UNARY_DEREFERENCE: return get_address_alignment(expr->unary.value); case EXPR_REFERENCE: ent = expr->reference.entity; break; case EXPR_SELECT: ent = expr->select.compound_entry; break; default: return get_type_alignment(expr->base.type); } assert(is_declaration(ent)); return get_declaration_alignment(&ent->declaration); }
void gcji_create_array_type(void) { ident *id = new_id_from_str("array"); type_jarray = new_type_class(id); assert(type_java_lang_object != NULL); add_class_supertype(type_jarray, type_java_lang_object); add_compound_member(type_jarray, superobject_ident, type_java_lang_object); ident *length_id = new_id_from_str("length"); gcj_array_length = add_compound_member(type_jarray, length_id, type_int); default_layout_compound_type(type_jarray); array_header_size = get_type_size(type_jarray); array_header_end_align = get_type_alignment(type_int); }
unsigned get_type_alignment(type_t *type) { switch (type->kind) { case TYPE_ERROR: return 0; case TYPE_ATOMIC: case TYPE_IMAGINARY: case TYPE_COMPLEX: case TYPE_ENUM: return get_atomic_type_alignment(type->atomic.akind); case TYPE_COMPOUND_UNION: layout_union_type(&type->compound); return type->compound.compound->alignment; case TYPE_COMPOUND_STRUCT: layout_struct_type(&type->compound); return type->compound.compound->alignment; case TYPE_FUNCTION: /* gcc says 1 here... */ return 1; case TYPE_REFERENCE: case TYPE_POINTER: return pointer_properties.alignment; case TYPE_ARRAY: return get_type_alignment(type->array.element_type); case TYPE_TYPEDEF: { il_alignment_t alignment = get_type_alignment(type->typedeft.typedefe->type); if (type->typedeft.typedefe->alignment > alignment) alignment = type->typedeft.typedefe->alignment; return alignment; } case TYPE_TYPEOF: return get_type_alignment(type->typeoft.typeof_type); } panic("invalid type in get_type_alignment"); }
/** * Turn a small CopyB node into a series of Load/Store nodes. */ static void lower_small_copyb_node(ir_node *irn) { ir_graph *irg = get_irn_irg(irn); dbg_info *dbgi = get_irn_dbg_info(irn); ir_node *block = get_nodes_block(irn); ir_type *tp = get_CopyB_type(irn); ir_node *addr_src = get_CopyB_src(irn); ir_node *addr_dst = get_CopyB_dst(irn); ir_node *mem = get_CopyB_mem(irn); ir_mode *mode_ref = get_irn_mode(addr_src); unsigned mode_bytes = allow_misalignments ? native_mode_bytes : get_type_alignment(tp); unsigned size = get_type_size(tp); unsigned offset = 0; bool is_volatile = get_CopyB_volatility(irn) == volatility_is_volatile; ir_cons_flags flags = is_volatile ? cons_volatile : cons_none; while (offset < size) { ir_mode *mode = get_ir_mode(mode_bytes); for (; offset + mode_bytes <= size; offset += mode_bytes) { ir_mode *mode_ref_int = get_reference_offset_mode(mode_ref); /* construct offset */ ir_node *addr_const = new_r_Const_long(irg, mode_ref_int, offset); ir_node *add = new_r_Add(block, addr_src, addr_const); ir_node *load = new_rd_Load(dbgi, block, mem, add, mode, tp, flags); ir_node *load_res = new_r_Proj(load, mode, pn_Load_res); ir_node *load_mem = new_r_Proj(load, mode_M, pn_Load_M); ir_node *addr_const2 = new_r_Const_long(irg, mode_ref_int, offset); ir_node *add2 = new_r_Add(block, addr_dst, addr_const2); ir_node *store = new_rd_Store(dbgi, block, load_mem, add2, load_res, tp, flags); ir_node *store_mem = new_r_Proj(store, mode_M, pn_Store_M); mem = store_mem; } mode_bytes /= 2; } exchange(irn, mem); }
unsigned get_type_alignment_compound(type_t const *const type) { switch (type->kind) { case TYPE_ATOMIC: case TYPE_COMPLEX: case TYPE_IMAGINARY: case TYPE_ENUM: return atomic_type_properties[type->atomic.akind].struct_alignment; case TYPE_TYPEDEF: { il_alignment_t const alignment = get_type_alignment_compound(type->typedeft.typedefe->type); return MAX(type->typedeft.typedefe->alignment, alignment); } case TYPE_TYPEOF: return get_type_alignment_compound(type->typeoft.typeof_type); default: return get_type_alignment(type); } }
unsigned long WINAPI VARIANT_UserSize(unsigned long *pFlags, unsigned long Start, VARIANT *pvar) { int align; TRACE("(%lx,%ld,%p)\n", *pFlags, Start, pvar); TRACE("vt=%04x\n", V_VT(pvar)); ALIGN_LENGTH(Start, 7); Start += sizeof(variant_wire_t); if(V_VT(pvar) & VT_BYREF) Start += 4; align = get_type_alignment(pFlags, pvar); ALIGN_LENGTH(Start, align); if(V_VT(pvar) == (VT_VARIANT | VT_BYREF)) Start += 4; else Start += get_type_size(pFlags, pvar); Start = wire_extra_user_size(pFlags, Start, pvar); TRACE("returning %ld\n", Start); return Start; }
unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); ALIGN_POINTER(Buffer, 7); VariantInit(pvar); header = (variant_wire_t *)Buffer; pvar->n1.n2.vt = header->vt; pvar->n1.n2.wReserved1 = header->wReserved1; pvar->n1.n2.wReserved2 = header->wReserved2; pvar->n1.n2.wReserved3 = header->wReserved3; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { Pos += 4; pvar->n1.n2.n3.byref = CoTaskMemAlloc(type_size); memcpy(pvar->n1.n2.n3.byref, Pos, type_size); if((header->vt & VT_TYPEMASK) != VT_VARIANT) Pos += type_size; else Pos += 4; } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(pvar, Pos, type_size); else memcpy(&pvar->n1.n2.n3, Pos, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: V_BSTR(pvar) = NULL; Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: *V_BSTRREF(pvar) = NULL; Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } return Pos; }
unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); TRACE("vt=%04x\n", V_VT(pvar)); ALIGN_POINTER(Buffer, 7); header = (variant_wire_t *)Buffer; header->clSize = 0; /* fixed up at the end */ header->rpcReserverd = 0; header->vt = pvar->n1.n2.vt; header->wReserved1 = pvar->n1.n2.wReserved1; header->wReserved2 = pvar->n1.n2.wReserved2; header->wReserved3 = pvar->n1.n2.wReserved3; header->switch_is = pvar->n1.n2.vt; if(header->switch_is & VT_ARRAY) header->switch_is &= ~VT_TYPEMASK; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { *(DWORD *)Pos = max(type_size, 4); Pos += 4; if((header->vt & VT_TYPEMASK) != VT_VARIANT) { memcpy(Pos, pvar->n1.n2.n3.byref, type_size); Pos += type_size; } else { *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24; Pos += 4; } } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(Pos, pvar, type_size); else memcpy(Pos, &pvar->n1.n2.n3, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } header->clSize = ((Pos - Buffer) + 7) >> 3; TRACE("marshalled size=%ld\n", header->clSize); return Pos; }