private void PrintSequentiallyLaidOutField(PrintContext context, int index, ref int currentOffset) { Debug.Assert(!isExplicitLayout); // sequential layout - no unions should be needed; however if the size // is "odd", we are in pragma pack (1) and the packing will be simulated // by our artificial padding fields if (!unalignedSizeOrOffsets) { context.SetPack(this.pack); } NativeField nf = fields[index]; int previous_offset = currentOffset; AlignField(nf, ref currentOffset, true); if (unalignedSizeOrOffsets) { // inject artificial padding context.PrintPadding(currentOffset - previous_offset); } context.Printer.PrintLn(); nf.PrintTo(context.Printer, context.LogPrinter, context.Flags); currentOffset += nf.Type.TypeSize; }
private void PrintUnionField(PrintContext context, int fieldIndex, int unionOffset) { NativeField nf = fields[fieldIndex]; if (nf.Offset.Value == unionOffset) { // no padding necessary - print the field context.Printer.PrintLn(); nf.PrintTo(context.Printer, context.LogPrinter, context.Flags); } else { // this field will be wrapped in a struct with a padding before it if (IsPragmaPack1Needed(nf.Offset.Value, unionOffset)) { context.SetPack(1); } context.Printer.PrintLn(); context.Printer.PrintLn(OutputType.Keyword, "struct"); context.Printer.Print(OutputType.Operator, "{"); context.Printer.Indent(); try { // add padding context.PrintPadding(nf.Offset.Value - unionOffset); context.Printer.PrintLn(); // add the field itself nf.PrintTo(context.Printer, context.LogPrinter, context.Flags); } finally { context.Printer.Unindent(); context.Printer.PrintLn(); context.Printer.Print(OutputType.Operator, "};"); } } }
private void PrintExplicitlyLaidOutField(PrintContext context, ref int index, ref int currentOffset) { Debug.Assert(isExplicitLayout); NativeField nf = fields[index]; int start = (nf.Offset ?? currentOffset); Debug.Assert(start >= currentOffset); // otherwise we would have printed it before bool pack1 = false; if (start > currentOffset) { if (IsPragmaPack1Needed(start)) { context.SetPack(1); pack1 = true; } // there is a gap between the end of last field and start of this field context.PrintPadding(start - currentOffset); currentOffset = start; } if (!pack1 && !unalignedSizeOrOffsets) { context.SetPack(DefaultPack); } // determine the fields that will have to be grouped in a union int union_end; int last_united_index = ComputeLastUnitedField(index, out union_end); if (last_united_index > index) { context.Printer.PrintLn(); context.Printer.Print(OutputType.Keyword, "union"); if (isUnion) { PrintIdentifierAndSize(context); } else { context.Printer.PrintLn(); } context.Printer.Print(OutputType.Operator, "{"); context.Printer.Indent(); try { for (int j = index; j <= last_united_index; j++) { // the union field will be the field itself or an anonymous // structure if a padding is needed to reach the field offset PrintUnionField(context, j, currentOffset); } } finally { context.Printer.Unindent(); context.Printer.PrintLn(); context.Printer.Print(OutputType.Operator, "};"); } } else { // no union is needed context.Printer.PrintLn(); nf.PrintTo(context.Printer, context.LogPrinter, context.Flags); } currentOffset = union_end; index = last_united_index; }
public override void PrintTo(ICodePrinter printer, ILogPrinter logPrinter, PrintFlags flags) { Debug.Assert(printer != null && logPrinter != null); base.PrintTo(printer, logPrinter, flags); PrintContext context = new PrintContext(printer, logPrinter, flags); if (unalignedSizeOrOffsets) { // the size of the structure or field offsets is "odd" -> need to pragma pack (1) it context.SetPack(1, true); } else { context.SetPack(DefaultPack, true); } if (!isUnion) { printer.PrintLn(); printer.Print(OutputType.Keyword, "struct"); PrintIdentifierAndSize(context); printer.Print(OutputType.Operator, "{"); printer.Indent(); } try { if (!isInvalid) { int current_offset = 0; for (int i = 0; i < fields.Length; i++) { if (isExplicitLayout) { // this may in fact print more fields in a union, so i is passed byref PrintExplicitlyLaidOutField(context, ref i, ref current_offset); } else { PrintSequentiallyLaidOutField(context, i, ref current_offset); } } int tmp_offset = current_offset; if (!context.UsedNonDefaultPack) { // if we never used a pack different from the default (8), we are sure // about the implicit padding at the end of the structure AlignSelf(ref tmp_offset); } if (size != tmp_offset) { // add final padding to the end of the structure to make its size exactly as requested context.PrintPadding(size - current_offset, context.UsedNonDefaultPack); } } } finally { if (!isUnion) { printer.Unindent(); printer.PrintLn(); printer.Print(OutputType.Operator, "};"); } context.SetDefaultPack(); } }