summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs
blob: c04c3c843410e2a9681f39b00439cfa010908d7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace System.Reflection.Emit
{
    public sealed class LocalBuilder : LocalVariableInfo
    {
        #region Private Data Members
        private int m_localIndex;
        private Type m_localType;
        private MethodInfo m_methodBuilder;
        private bool m_isPinned;
        #endregion

        #region Constructor
        private LocalBuilder() { }
        internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder)
            : this(localIndex, localType, methodBuilder, false) { }
        internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder, bool isPinned)
        {
            m_isPinned = isPinned;
            m_localIndex = localIndex;
            m_localType = localType;
            m_methodBuilder = methodBuilder;
        }
        #endregion

        #region Internal Members
        internal int GetLocalIndex()
        {
            return m_localIndex;
        }
        internal MethodInfo GetMethodBuilder()
        {
            return m_methodBuilder;
        }
        #endregion

        #region LocalVariableInfo Override
        public override bool IsPinned { get { return m_isPinned; } }
        public override Type LocalType
        {
            get
            {
                return m_localType;
            }
        }
        public override int LocalIndex { get { return m_localIndex; } }
        #endregion

        #region Public Members
        public void SetLocalSymInfo(String name)
        {
            SetLocalSymInfo(name, 0, 0);
        }

        public void SetLocalSymInfo(String name, int startOffset, int endOffset)
        {
            ModuleBuilder dynMod;
            SignatureHelper sigHelp;
            int sigLength;
            byte[] signature;
            byte[] mungedSig;
            int index;

            MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
            if (methodBuilder == null)
                // it's a light code gen entity
                throw new NotSupportedException();
            dynMod = (ModuleBuilder)methodBuilder.Module;
            if (methodBuilder.IsTypeCreated())
            {
                // cannot change method after its containing type has been created
                throw new InvalidOperationException(SR.InvalidOperation_TypeHasBeenCreated);
            }

            // set the name and range of offset for the local
            if (dynMod.GetSymWriter() == null)
            {
                // cannot set local name if not debug module
                throw new InvalidOperationException(SR.InvalidOperation_NotADebugModule);
            }

            sigHelp = SignatureHelper.GetFieldSigHelper(dynMod);
            sigHelp.AddArgument(m_localType);
            signature = sigHelp.InternalGetSignature(out sigLength);

            // The symbol store doesn't want the calling convention on the
            // front of the signature, but InternalGetSignature returns
            // the callinging convention. So we strip it off. This is a
            // bit unfortunate, since it means that we need to allocate
            // yet another array of bytes...  
            mungedSig = new byte[sigLength - 1];
            Buffer.BlockCopy(signature, 1, mungedSig, 0, sigLength - 1);

            index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex();
            if (index == -1)
            {
                // top level scope information is kept with methodBuilder
                methodBuilder.m_localSymInfo.AddLocalSymInfo(
                     name,
                     mungedSig,
                     m_localIndex,
                     startOffset,
                     endOffset);
            }
            else
            {
                methodBuilder.GetILGenerator().m_ScopeTree.AddLocalSymInfoToCurrentScope(
                     name,
                     mungedSig,
                     m_localIndex,
                     startOffset,
                     endOffset);
            }
        }
        #endregion
    }
}