Exemple #1
0
        public int GetStringAddress(string s, target.Target t)
        {
            if (str_addrs.ContainsKey(s))
            {
                return(str_addrs[s]);
            }
            else
            {
                var ptr_size = t.GetCTSize(ir.Opcode.ct_object);
                while (str_tab.Count % ptr_size != 0)
                {
                    str_tab.Add(0);
                }

                int ret = str_tab.Count;
                str_addrs.Add(s, ret);

                //int string_obj_len = layout.Layout.GetTypeSize(StringObject,
                //    t, false);
                //int string_type_offset =

                int i = 0;
                for (; i < length_offset; i++)
                {
                    str_tab.Add(0);
                }
                int len = s.Length;
                str_tab.Add((byte)(len & 0xff));
                str_tab.Add((byte)((len >> 8) & 0xff));
                str_tab.Add((byte)((len >> 16) & 0xff));
                str_tab.Add((byte)((len >> 24) & 0xff));
                i += 4;
                for (; i < string_obj_len; i++)
                {
                    str_tab.Add(0);
                }

                foreach (char c in s)
                {
                    str_tab.Add((byte)(c & 0xff));
                    str_tab.Add((byte)((c >> 8) & 0xff));
                }

                // null-terminate and align up to ensure coreclr String.EqualsHelper works
                str_tab.Add(0);
                str_tab.Add(0);
                while ((str_tab.Count % t.GetPointerSize()) != 0)
                {
                    str_tab.Add(0);
                }
                return(ret);
            }
        }
Exemple #2
0
        public void WriteToOutput(binary_library.IBinaryFile of,
                                  metadata.MetadataStream ms, target.Target t,
                                  binary_library.ISection rd = null)
        {
            if (str_tab.Count == 0)
            {
                return;
            }

            if (rd == null)
            {
                rd = of.GetRDataSection();
            }
            rd.Align(t.GetCTSize(ir.Opcode.ct_object));

            var stab_lab = of.CreateSymbol();

            stab_lab.Name       = Label;
            stab_lab.ObjectType = binary_library.SymbolObjectType.Object;
            stab_lab.Offset     = (ulong)rd.Data.Count;
            stab_lab.Type       = binary_library.SymbolType.Weak;
            rd.AddSymbol(stab_lab);

            int stab_base = rd.Data.Count;

            foreach (byte b in str_tab)
            {
                rd.Data.Add(b);
            }

            foreach (var kvp in sig_metadata_addrs)
            {
                var reloc = of.CreateRelocation();
                reloc.DefinedIn = rd;
                reloc.Type      = t.GetDataToDataReloc();
                reloc.Addend    = 0;

                if (sig_metadata_addends.ContainsKey(kvp.Key))
                {
                    reloc.Addend = sig_metadata_addends[kvp.Key];
                }

                var md_lab = of.CreateSymbol();
                md_lab.Name       = kvp.Value;
                md_lab.ObjectType = binary_library.SymbolObjectType.Object;

                reloc.References = md_lab;
                reloc.Offset     = (ulong)(kvp.Key + stab_base);
                of.AddRelocation(reloc);
            }

            stab_lab.Size = rd.Data.Count - (int)stab_lab.Offset;
        }
Exemple #3
0
        private void AddFieldSpecFields(MethodSpec fs, List <byte> str_tab, target.Target t, TysilaState s)
        {
            /* Field specs have two special fields:
             *
             * IntPtr field_size
             * IntPtr field_data
             *
             * where field_data may be null if no .data member is specified for the field
             */

            // read field signature to get the type of the field
            var sig_idx = fs.msig;

            sig_idx = fs.m.GetFieldSigTypeIndex(sig_idx);
            var ts    = fs.m.GetTypeSpec(ref sig_idx, fs.gtparams, null);
            var fsize = t.GetSize(ts);

            str_tab.AddRange(t.IntPtrArray(BitConverter.GetBytes(fsize)));

            // now determine if the field has an rva associated with it
            int rva_id = 0;

            for (int i = 1; i <= fs.m.table_rows[MetadataStream.tid_FieldRVA]; i++)
            {
                var field_idx = fs.m.GetIntEntry(MetadataStream.tid_FieldRVA, i, 1);
                if (field_idx == fs.mdrow)
                {
                    rva_id = i;
                    break;
                }
            }

            // rva id
            if (rva_id != 0)
            {
                // TODO checks in CIL II 22.18
                var rva    = fs.m.GetIntEntry(MetadataStream.tid_FieldRVA, rva_id, 0);
                var offset = fs.m.ResolveRVA(rva);
                sig_metadata_addrs[str_tab.Count]   = fs.m.AssemblyName;
                sig_metadata_addends[str_tab.Count] = offset;
            }
            for (int i = 0; i < t.psize; i++)
            {
                str_tab.Add(0);
            }
        }
Exemple #4
0
        public StringTable(string mod_name, metadata.AssemblyLoader al,
                           target.Target t)
        {
            Label = mod_name + "_StringTable";

            var corlib = al.GetAssembly("mscorlib");

            StringObject = corlib.GetTypeSpec("System", "String");
            var fs_len = corlib.GetFieldDefRow("m_stringLength", StringObject);

            length_offset = layout.Layout.GetFieldOffset(StringObject, fs_len,
                                                         t, out var is_tls);
            var fs_start = corlib.GetFieldDefRow("m_firstChar", StringObject);

            string_obj_len = layout.Layout.GetFieldOffset(StringObject, fs_start,
                                                          t, out is_tls);
        }
Exemple #5
0
        public int GetSignatureAddress(metadata.TypeSpec.FullySpecSignature sig, target.Target t, TysilaState s)
        {
            var ptr_size = t.GetCTSize(ir.Opcode.ct_object);

            while (str_tab.Count % ptr_size != 0)
            {
                str_tab.Add(0);
            }

            int ret = str_tab.Count;

            // first is type of signature
            str_tab.AddRange(t.IntPtrArray(BitConverter.GetBytes((int)sig.Type)));

            // then any extra data if necessary
            switch (sig.Type)
            {
            case metadata.Spec.FullySpecSignature.FSSType.Field:
                // For fields with static data we insert it here
                AddFieldSpecFields(sig.OriginalSpec as MethodSpec, str_tab, t, s);
                break;

            case Spec.FullySpecSignature.FSSType.Type:
                AddTypeSpecFields(sig.OriginalSpec as TypeSpec, str_tab, t, s);
                break;
            }

            // then is length of module references
            str_tab.AddRange(t.IntPtrArray(BitConverter.GetBytes(sig.Modules.Count)));

            // then module references
            foreach (var mod in sig.Modules)
            {
                sig_metadata_addrs[str_tab.Count] = mod.AssemblyName;
                for (int i = 0; i < ptr_size; i++)
                {
                    str_tab.Add(0);
                }
            }

            // then signature
            str_tab.AddRange(sig.Signature);

            return(ret);
        }
Exemple #6
0
        public int GetSignatureAddress(IEnumerable <byte> sig, target.Target t, TysilaState s)
        {
            var ptr_size = t.GetCTSize(ir.Opcode.ct_object);

            while (str_tab.Count % ptr_size != 0)
            {
                str_tab.Add(0);
            }

            int ret = str_tab.Count;

            foreach (byte b in sig)
            {
                str_tab.Add(b);
            }

            return(ret);
        }
Exemple #7
0
        public void WriteToOutput(binary_library.IBinaryFile of,
                                  metadata.MetadataStream ms, target.Target t)
        {
            var rd = of.GetRDataSection();

            rd.Align(t.GetCTSize(ir.Opcode.ct_object));

            var stab_lab = GetStringTableSymbol(of);

            stab_lab.Name       = Label;
            stab_lab.ObjectType = binary_library.SymbolObjectType.Object;
            stab_lab.Offset     = (ulong)rd.Data.Count;
            stab_lab.Type       = binary_library.SymbolType.Global;
            rd.AddSymbol(stab_lab);

            int stab_base = rd.Data.Count;

            foreach (byte b in str_tab)
            {
                rd.Data.Add(b);
            }

            var str_lab = of.CreateSymbol();

            str_lab.Name       = StringObject.m.MangleType(StringObject);
            str_lab.ObjectType = binary_library.SymbolObjectType.Object;

            foreach (var str_addr in str_addrs.Values)
            {
                var reloc = of.CreateRelocation();
                reloc.DefinedIn  = rd;
                reloc.Type       = t.GetDataToDataReloc();
                reloc.Addend     = 0;
                reloc.References = str_lab;
                reloc.Offset     = (ulong)(str_addr + stab_base);
                of.AddRelocation(reloc);
            }

            stab_lab.Size = rd.Data.Count - (int)stab_lab.Offset;
        }
Exemple #8
0
        public static bool AssembleBoxedMethod(metadata.MethodSpec ms,
                                               binary_library.IBinaryFile bf, target.Target t,
                                               TysilaState s,
                                               StringBuilder debug_passes = null,
                                               binary_library.ISection ts = null)
        {
            if (ts == null)
            {
                ts = bf.GetTextSection();
            }
            s.bf           = bf;
            s.text_section = ts;

            // Symbol
            List <binary_library.ISymbol> meth_syms = new List <binary_library.ISymbol>();
            var mangled_name = ms.MangleMethod();
            var meth_sym     = bf.CreateSymbol();

            meth_sym.Name       = mangled_name;
            meth_sym.ObjectType = binary_library.SymbolObjectType.Function;
            meth_sym.Offset     = (ulong)ts.Data.Count;
            meth_sym.Type       = binary_library.SymbolType.Weak;
            ts.AddSymbol(meth_sym);
            meth_syms.Add(meth_sym);

            Code c = ms.ret_type_needs_boxing ? t.AssembleBoxRetTypeMethod(ms, s) : t.AssembleBoxedMethod(ms, s);

            c.t = t;
            t.AssemblePass(c);

            foreach (var sym in meth_syms)
            {
                sym.Size = ts.Data.Count - (int)sym.Offset;
            }

            DumpDebug(debug_passes, meth_syms, c);

            return(true);
        }
Exemple #9
0
        public static bool AssembleMethod(metadata.MethodSpec ms,
                                          binary_library.IBinaryFile bf, target.Target t,
                                          TysilaState s,
                                          StringBuilder debug_passes        = null,
                                          MetadataStream base_m             = null,
                                          Code code_override                = null,
                                          binary_library.ISection ts        = null,
                                          binary_library.ISection data_sect = null,
                                          dwarf.DwarfCU dcu = null)
        {
            if (ms.ret_type_needs_boxing)
            {
                throw new Exception("AssembleMethod called for box rettype stub - use AssembleBoxedMethod instead");
            }
            if (ms.is_boxed)
            {
                throw new Exception("AssembleMethod called for boxed method - use AssembleBoxedMethod instead");
            }

            if (ts == null)
            {
                ts = bf.GetTextSection();
            }
            s.bf           = bf;
            s.text_section = ts;
            binary_library.SymbolType sym_st = binary_library.SymbolType.Global;

            var csite = ms.msig;
            var mdef  = ms.mdrow;
            var m     = ms.m;

            /* Don't compile if not for this architecture */
            if (!t.IsMethodValid(ms))
            {
                return(false);
            }

            // Get method RVA, don't compile if no body
            var rva = m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                    mdef, 0);

            // New signature table
            s.sigt = new SignatureTable(ms.MangleMethod());

            /* Is this an array method? */
            if (rva == 0 &&
                ms.type != null &&
                ms.type.stype == TypeSpec.SpecialType.Array &&
                code_override == null)
            {
                if (ms.name_override == "Get")
                {
                    code_override = ir.ConvertToIR.CreateArrayGet(ms, t, s);
                }
                else if (ms.name_override == ".ctor")
                {
                    // there are two constructors, choose the correct one
                    var pcount = ms.m.GetMethodDefSigParamCount(ms.msig);

                    if (pcount == ms.type.arr_rank)
                    {
                        code_override = ir.ConvertToIR.CreateArrayCtor1(ms, t, s);
                    }
                    else if (pcount == 2 * ms.type.arr_rank)
                    {
                        code_override = ir.ConvertToIR.CreateArrayCtor2(ms, t, s);
                    }
                    else
                    {
                        throw new NotSupportedException("Invalid number of parameters to " + ms.MangleMethod() + " for array of rank " + ms.type.arr_rank.ToString());
                    }
                }
                else if (ms.name_override == "Set")
                {
                    code_override = ir.ConvertToIR.CreateArraySet(ms, t, s);
                }
                else if (ms.name_override == "Address")
                {
                    code_override = ir.ConvertToIR.CreateArrayAddress(ms, t, s);
                }
                else
                {
                    throw new NotImplementedException(ms.name_override);
                }

                sym_st = binary_library.SymbolType.Weak;
            }

            /* Is this a vector method? */
            if (rva == 0 &&
                ms.type != null &&
                ms.type.stype == TypeSpec.SpecialType.SzArray &&
                code_override == null)
            {
                if (ms.Name == "IndexOf")
                {
                    code_override = ir.ConvertToIR.CreateVectorIndexOf(ms, t, s);
                }
                else if (ms.Name == "Insert")
                {
                    code_override = ir.ConvertToIR.CreateVectorInsert(ms, t, s);
                }
                else if (ms.Name == "RemoveAt")
                {
                    code_override = ir.ConvertToIR.CreateVectorRemoveAt(ms, t, s);
                }
                else if (ms.Name == "get_Item")
                {
                    code_override = ir.ConvertToIR.CreateVectorget_Item(ms, t, s);
                }
                else if (ms.Name == "set_Item")
                {
                    code_override = ir.ConvertToIR.CreateVectorset_Item(ms, t, s);
                }
                else if (ms.Name == "get_Count")
                {
                    code_override = ir.ConvertToIR.CreateVectorget_Count(ms, t, s);
                }
                else if (ms.Name == "CopyTo")
                {
                    code_override = ir.ConvertToIR.CreateVectorCopyTo(ms, t, s);
                }

                /*else if (ms.Name == "GetEnumerator")
                 *  code_override = ir.ConvertToIR.CreateVectorGetEnumerator(ms, t);*/
                else if (ms.Name == "Add" ||
                         ms.Name == "Clear" ||
                         ms.Name == "Contains" ||
                         ms.Name == "Remove" ||
                         ms.Name == "get_IsReadOnly" ||
                         ms.Name == "get_IsSynchronized" ||
                         ms.Name == "get_SyncRoot" ||
                         ms.Name == "get_IsFixedSize" ||
                         ms.Name == "Clone" ||
                         ms.Name == "CompareTo" ||
                         ms.Name == "GetHashCode" ||
                         ms.Name == "Equals")
                {
                    code_override = ir.ConvertToIR.CreateVectorUnimplemented(ms, t, s);
                }
                else
                {
                    return(false);
                }

                sym_st = binary_library.SymbolType.Weak;
            }

            if (rva == 0 && code_override == null)
            {
                return(false);
            }

            // Get mangled name for defining a symbol
            List <binary_library.ISymbol> meth_syms = new List <binary_library.ISymbol>();
            var mangled_name = m.MangleMethod(ms);
            var meth_sym     = bf.CreateSymbol();

            meth_sym.Name       = mangled_name;
            meth_sym.ObjectType = binary_library.SymbolObjectType.Function;
            meth_sym.Offset     = (ulong)ts.Data.Count;
            meth_sym.Type       = binary_library.SymbolType.Global;
            ts.AddSymbol(meth_sym);
            meth_syms.Add(meth_sym);

            foreach (var alias in ms.MethodAliases)
            {
                var alias_sym = bf.CreateSymbol();
                alias_sym.Name       = alias;
                alias_sym.ObjectType = binary_library.SymbolObjectType.Function;
                alias_sym.Offset     = (ulong)ts.Data.Count;
                alias_sym.Type       = binary_library.SymbolType.Global;
                ts.AddSymbol(alias_sym);
                meth_syms.Add(alias_sym);
            }

            if (ms.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs20WeakLinkageAttribute_7#2Ector_Rv_P1u1t"))
            {
                sym_st = binary_library.SymbolType.Weak;
            }
            if (base_m != null && ms.m != base_m)
            {
                sym_st = binary_library.SymbolType.Weak;
            }
            foreach (var sym in meth_syms)
            {
                sym.Type = sym_st;
            }

            // Get signature if not specified
            if (csite == 0)
            {
                csite = (int)m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                           mdef, 4);
            }

            Code cil;

            if (code_override == null)
            {
                var meth = m.GetRVA(rva);

                var  flags        = meth.ReadByte(0);
                int  max_stack    = 0;
                long code_size    = 0;
                long lvar_sig_tok = 0;
                int  boffset      = 0;
                List <metadata.ExceptionHeader> ehdrs = null;
                bool has_exceptions = false;

                if ((flags & 0x3) == 0x2)
                {
                    // Tiny header
                    code_size = flags >> 2;
                    max_stack = 8;
                    boffset   = 1;
                }
                else if ((flags & 0x3) == 0x3)
                {
                    // Fat header
                    uint fat_flags   = meth.ReadUShort(0) & 0xfffU;
                    int  fat_hdr_len = (meth.ReadUShort(0) >> 12) * 4;
                    max_stack    = meth.ReadUShort(2);
                    code_size    = meth.ReadUInt(4);
                    lvar_sig_tok = meth.ReadUInt(8);
                    boffset      = fat_hdr_len;

                    if ((flags & 0x8) == 0x8)
                    {
                        has_exceptions = true;

                        ehdrs = new List <metadata.ExceptionHeader>();

                        int ehdr_offset = boffset + (int)code_size;
                        ehdr_offset = util.util.align(ehdr_offset, 4);

                        while (true)
                        {
                            int kind = meth.ReadByte(ehdr_offset);

                            if ((kind & 0x1) != 0x1)
                            {
                                throw new Exception("Invalid exception header");
                            }

                            bool is_fat = false;
                            if ((kind & 0x40) == 0x40)
                            {
                                is_fat = true;
                            }

                            int data_size = meth.ReadInt(ehdr_offset);
                            data_size >>= 8;
                            if (is_fat)
                            {
                                data_size &= 0xffffff;
                            }
                            else
                            {
                                data_size &= 0xff;
                            }

                            int clause_count;
                            if (is_fat)
                            {
                                clause_count = (data_size - 4) / 24;
                            }
                            else
                            {
                                clause_count = (data_size - 4) / 12;
                            }

                            ehdr_offset += 4;
                            for (int i = 0; i < clause_count; i++)
                            {
                                var ehdr = ParseExceptionHeader(meth,
                                                                ref ehdr_offset, is_fat, ms);
                                ehdr.EhdrIdx = i;
                                ehdrs.Add(ehdr);
                            }

                            if ((kind & 0x80) != 0x80)
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    throw new Exception("Invalid method header flags");
                }

                /* Parse CIL code */
                cil = libtysila5.cil.CilParser.ParseCIL(meth,
                                                        ms, boffset, (int)code_size, lvar_sig_tok,
                                                        has_exceptions, ehdrs);
                cil.s = s;

                /* Allocate local vars and args */
                t.AllocateLocalVarsArgs(cil);

                /* Convert to IR */
                cil.t = t;
                ir.ConvertToIR.DoConversion(cil);
            }
            else
            {
                cil = code_override;
            }


            /* Allocate registers */
            ir.AllocRegs.DoAllocation(cil);


            /* Choose instructions */
            target.ChooseInstructions.DoChoosing(cil);
            t.AssemblePass(cil);
            //((target.x86.x86_Assembler)cil.t).AssemblePass(cil);

            foreach (var sym in meth_syms)
            {
                sym.Size = ts.Data.Count - (int)sym.Offset;
            }

            foreach (var extra_sym in cil.extra_labels)
            {
                var esym = bf.CreateSymbol();
                esym.Name       = extra_sym.Name;
                esym.ObjectType = binary_library.SymbolObjectType.Function;
                esym.Offset     = (ulong)extra_sym.Offset;
                esym.Type       = sym_st;
                ts.AddSymbol(esym);
            }

            /* Dump debug */
            DumpDebug(debug_passes, meth_syms, cil);

            /* Signature table */
            if (data_sect == null)
            {
                data_sect = bf.GetDataSection();
            }
            s.sigt.WriteToOutput(bf, ms.m, t, data_sect);

            /* DWARF output */
            if (dcu != null)
            {
                var ddie = dcu.GetMethodDie(ms);
                ddie.sym = meth_syms[0];
                ddie.cil = cil;

                var ddts = dcu.GetTypeDie(ms.type) as dwarf.DwarfParentDIE;
                ddts.Children.Add(ddie);

                if (ms.ReturnType != null)
                {
                    dcu.GetTypeDie(ms.ReturnType);
                    if (ms.ReturnType.stype == TypeSpec.SpecialType.None && !ms.ReturnType.IsValueType)
                    {
                        dcu.GetTypeDie(ms.ReturnType.Pointer);
                    }
                }
                foreach (var la in cil.la_types)
                {
                    dcu.GetTypeDie(la);
                    if (la.stype == TypeSpec.SpecialType.None && !la.IsValueType)
                    {
                        dcu.GetTypeDie(la.Pointer);
                    }
                }
                foreach (var lv in cil.lv_types)
                {
                    dcu.GetTypeDie(lv);
                    if (lv.stype == TypeSpec.SpecialType.None && !lv.IsValueType)
                    {
                        dcu.GetTypeDie(lv.Pointer);
                    }
                }

                if (!ms.IsStatic)
                {
                    dcu.GetTypeDie(ms.type.Pointer);
                }

                // do we have source lines?
                if (ms.m.pdb != null && ms.mdrow > 0)
                {
                    var sps = ms.m.pdb.DebugGetSeqPtForMDRow(ms.mdrow);
                    if (sps != null && cil.cil != null && cil.cil.Count > 0)
                    {
                        /* Start building a Line Number Program
                         *
                         * We follow the example in DWARF4 D.5 (p251), with a few changes
                         *
                         * header - defined per CU
                         *   - add this/these source files to it if necessary
                         *
                         * DW_LNE_set_address - psize 0s, reloc to mangled name
                         * DW_LNS_advance_pc - mc_offset of first cil instruction
                         * DW_LNS_set_prologue_end
                         * DW_LNS_set_file - source file
                         * SPECIAL(0,0) - add first opcode
                         * SPECIAL(x,y) - add rest of opcodes
                         * DW_LNE_end_sequence
                         *
                         */

                        string cur_file = null;
                        int    cur_line = 1;
                        int    cur_mc   = 0;
                        int    cur_col  = 0;

                        var lnp = dcu.lnp;

                        // DW_LNE_set_address
                        lnp.AddRange(new byte[] { 0x00, (byte)(t.psize + 1), 0x02 });
                        dcu.lnp_relocs.Add(lnp.Count, meth_syms[0]);
                        for (int i = 0; i < t.psize; i++)
                        {
                            lnp.Add(0);
                        }

                        // DW_LNS_advance_pc
                        lnp.Add(0x02);
                        dwarf.DwarfDIE.w(lnp, (uint)cil.cil[0].mc_offset);
                        cur_mc = cil.cil[0].mc_offset;

                        // DW_LNS_set_prologue_end
                        lnp.Add(0x0a);

                        foreach (var cn in cil.cil)
                        {
                            var mc_advance = cn.mc_offset - cur_mc;

                            // get current line number
                            MetadataStream.SeqPt csp = null;
                            foreach (var sp in sps)
                            {
                                if (sp.IlOffset == cn.il_offset &
                                    !sp.IsHidden)
                                {
                                    csp = sp;
                                    break;
                                }
                            }
                            if (csp != null)
                            {
                                var line_advance = csp.StartLine - cur_line;

                                if (ddie.StartLine == 0)
                                {
                                    ddie.StartLine = csp.StartLine;
                                }
                                if (ddie.StartColumn == 0)
                                {
                                    ddie.StartColumn = csp.StartCol;
                                }

                                if (csp.DocName != cur_file)
                                {
                                    // DW_LNS_set_file
                                    lnp.Add(0x04);

                                    uint file_no;
                                    if (!dcu.lnp_files.TryGetValue(csp.DocName, out file_no))
                                    {
                                        file_no = (uint)(dcu.lnp_files.Count + 1);
                                        dcu.lnp_files[csp.DocName] = file_no;
                                        dcu.lnp_fnames.Add(csp.DocName);
                                    }
                                    if (ddie.SourceFileId == 0)
                                    {
                                        ddie.SourceFileId = (int)file_no;
                                    }

                                    dwarf.DwarfDIE.w(lnp, file_no);

                                    cur_file = csp.DocName;
                                }

                                if (csp.StartCol != cur_col)
                                {
                                    // DW_LNS_set_column
                                    lnp.Add(0x05);
                                    dwarf.DwarfDIE.w(lnp, (uint)csp.StartCol);
                                    cur_col = csp.StartCol;
                                }

                                /* SPECIAL if possible
                                 *  Use example on DWARF4 p132:
                                 *      opcode_base = 13, line_base = -3, line_range = 12
                                 *
                                 *  Gives a line advance range of [-3,8] and op_advance [0,19]
                                 */

                                if ((line_advance >= dcu.line_base && line_advance < (dcu.line_base + dcu.line_range)) &&
                                    (mc_advance >= 0 && mc_advance < dcu.mc_advance_max))
                                {
                                    var spec_opcode = (line_advance - dcu.line_base) +
                                                      (dcu.line_range * mc_advance) + dcu.opcode_base;
                                    lnp.Add((byte)spec_opcode);
                                }
                                else
                                {
                                    // DW_LNS_advance_pc
                                    lnp.Add(0x02);
                                    dwarf.DwarfDIE.w(lnp, (uint)mc_advance);

                                    // DW_LNS_advance_line
                                    lnp.Add(0x03);
                                    dwarf.DwarfDIE.w(lnp, line_advance);

                                    // SPECIAL(0,0)
                                    var spec_opcode = (0 - dcu.line_base) + dcu.opcode_base;
                                    lnp.Add((byte)spec_opcode);
                                }

                                cur_line += line_advance;
                                cur_mc   += mc_advance;
                            }
                        }

                        // Advance to end
                        var to_advance = (int)meth_syms[0].Size - cur_mc;
                        lnp.Add(0x02);
                        dwarf.DwarfDIE.w(lnp, to_advance);

                        // DW_LNE_end_sequence
                        lnp.Add(0x00);
                        lnp.Add(0x01);
                        lnp.Add(0x01);
                    }
                }
            }

            return(true);
        }