예제 #1
0
        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;
        }
예제 #2
0
        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, "};");
                }
            }
        }
예제 #3
0
        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;
        }
예제 #4
0
        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();
            }
        }