summaryrefslogtreecommitdiff
path: root/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala
blob: a80ea723230697f6a813eed713bc6555ca4e6c5f (plain) (blame)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
 */


package ch.epfl.lamp.compiler.msil.emit

import ch.epfl.lamp.compiler.msil.Type

/**
 * Represents a label in the instruction stream. Label is used in conjunction
 * with the ILGenerator class.
 *
 * @author Nikolay Mihaylov
 * @version 1.0
 */
abstract class Label protected {
    import Label._
    def isInitialized(): Boolean
    def getKind(): Kind
    def getAddress(): Int
    def getStacksize(): Int
    def setStacksize(stacksize: Int): Unit
    def incStacksize(): Unit
    def mergeWith(that: Label): Unit
}

object Label {
    final val DUMMY: Int = -((1<<31)-1)

    //##########################################################################

    final class NormalLabel(_address: Int, _stacksize: Int) extends Label {

        //##########################################################################
        // protected constructors

        //the position of the label
        private var address: Int = _address

        //the stacksize at the label
        private var stacksize: Int = _stacksize

	def this() {
          this(-1, DUMMY)
        }

        def this(that: NormalLabel) {
          this(that.getAddress(), that.getStacksize())
        }

        //##########################################################################
        // instrumental methods only used by ILGenerator

        def isInitialized() = (getAddress() != -1) || (stacksize != DUMMY)

        def getAddress() = address

        def getStacksize() = stacksize

        def setStacksize(stacksize: Int) {
            assert(stacksize >= 0)
            this.stacksize = stacksize
        }

        def incStacksize() {
            stacksize = stacksize + 1
        }

        def getKind(): Kind = Kind.Normal

        def mergeWith(that: Label) {
            //assert address < 0 : "this.address = " + address + " that.address = " + that.address
            address = that.getAddress()

            // 	assert stacksize == that.stacksize
            // 	    : "this.stacksize = " + stacksize + " that.stacksize = "
            // 	    + that.stacksize
            // 	stacksize = that.stacksize
            val ss: Int = math.max(stacksize, that.getStacksize())
            stacksize = ss
            that.setStacksize(ss)
        }

        //##########################################################################
        //

        /**
         * the toString Method return the label name
         * it's "IL" + address
         */
        override def toString(): String = {
            var pad: String = ""
            if (address < 16) pad = "000"
            else if (address < 256) pad = "00"
            else if (address < 4096) pad = "0"
            return "IL_"  + pad + Integer.toHexString(address)
        }

        def getString(): String = {
            val name = super.toString()
            val i: Int = name.lastIndexOf('.')
            return name.substring(i+1, name.length())
        }
    }

    //########################################################################
    // Special Labels

    final class SpecialLabel(kind: Label.Kind) extends Label {
        def isInitialized() = true
        def getAddress(): Int = { throw new RuntimeException("" + kind) }
        def getStacksize(): Int = { throw new RuntimeException("" + kind) }
        def setStacksize(stacksize: Int) { throw new RuntimeException("" + kind) }
        def incStacksize() { throw new RuntimeException("" + kind) }
        def getKind(): Kind = kind
        def mergeWith(that: Label) { throw new RuntimeException("" + kind) }
        override def toString() = s"Label($kind)"
    }

    final val NewScope: Label = new SpecialLabel(Kind.NewScope)
    final val EndScope: Label = new SpecialLabel(Kind.EndScope)
    final val Try: Label = new SpecialLabel(Kind.Try)
    final val Catch: Label = new SpecialLabel(Kind.Catch)
    final val Filter: Label = new SpecialLabel(Kind.Filter)
    final val EndFilter: Label = new SpecialLabel(Kind.EndFilter)
    final val Finally: Label = new SpecialLabel(Kind.Finally)
    final val EndTry: Label = new SpecialLabel(Kind.EndTry)

    final class Kind() {}

    final object Kind {
        final val Normal: Kind = new Kind()

	final val NewScope: Kind = new Kind()
	final val EndScope: Kind = new Kind()

        final val Try: Kind = new Kind()
        final val Catch: Kind = new Kind()
        final val Filter: Kind = new Kind()
        final val EndFilter: Kind = new Kind()
        final val Finally: Kind = new Kind()
        final val EndTry: Kind = new Kind()
    }

    //##########################################################################
}