summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
blob: dd930ba52f7c97036ed0299b736eb7180450509f (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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/* NSC -- new scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Martin Odersky
 */


package scala.tools.nsc
package backend
package icode

import java.io.PrintWriter

trait Primitives { self: ICodes =>

  /** This class represents a primitive operation. */
  class Primitive {
  }


  // type : (type) => type
  // range: type <- { BOOL, Ix, Ux, Rx }
  // jvm  : {i, l, f, d}neg
  case class Negation(kind: TypeKind) extends Primitive

  // type : zero ? (type) => BOOL : (type,type) => BOOL
  // range: type <- { BOOL, Ix, Ux, Rx, REF }
  // jvm  : if{eq, ne, lt, ge, le, gt}, if{null, nonnull}
  //        if_icmp{eq, ne, lt, ge, le, gt}, if_acmp{eq,ne}
  case class Test(op: TestOp, kind: TypeKind,  zero: Boolean)  extends Primitive

  // type : (type,type) => I4
  // range: type <- { Ix, Ux, Rx }
  // jvm  : lcmp, {f, d}cmp{l, g}
  case class Comparison(op: ComparisonOp, kind: TypeKind) extends Primitive

  // type : (type,type) => type
  // range: type <- { Ix, Ux, Rx }
  // jvm  : {i, l, f, d}{add, sub, mul, div, rem}
  case class Arithmetic(op: ArithmeticOp, kind: TypeKind) extends Primitive

  // type : (type,type) => type
  // range: type <- { BOOL, Ix, Ux }
  // jvm  : {i, l}{and, or, xor}
  case class Logical(op: LogicalOp, kind: TypeKind) extends Primitive

  // type : (type,I4) => type
  // range: type <- { Ix, Ux }
  // jvm  : {i, l}{shl, ushl, shr}
  case class Shift(op: ShiftOp, kind: TypeKind) extends Primitive

  // type : (src) => dst
  // range: src,dst <- { Ix, Ux, Rx }
  // jvm  : i2{l, f, d}, l2{i, f, d}, f2{i, l, d}, d2{i, l, f}, i2{b, c, s}
  case class Conversion(src: TypeKind, dst: TypeKind) extends Primitive

  // type : (Array[REF]) => I4
  // range: type <- { BOOL, Ix, Ux, Rx, REF }
  // jvm  : arraylength
  case class ArrayLength(kind: TypeKind) extends Primitive

  // type : (buf,el) => buf
  // range: lf,rg <- { BOOL, Ix, Ux, Rx, REF, STR }
  // jvm  : It should call the appropriate 'append' method on StringBuffer
  case class StringConcat(el: TypeKind) extends Primitive

  /** Signals the beginning of a series of concatenations.
   *  On the JVM platform, it should create a new StringBuffer
   */
  case object StartConcat extends Primitive

  /**
   * type: (buf) => STR
   * jvm : It should turn the StringBuffer into a String.
   */
  case object EndConcat extends Primitive

  /** Pretty printer for primitives */
  class PrimitivePrinter(out: PrintWriter) {
    def print(s: String): PrimitivePrinter = {
      out.print(s)
      this
    }
  }

  /** This class represents a comparison operation. */
  class ComparisonOp {

    /** Returns a string representation of this operation. */
    override def toString(): String = this match {
      case CMPL => "CMPL"
      case CMP  => "CMP"
      case CMPG => "CMPG"
      case _ => throw new RuntimeException("ComparisonOp unknown case")
    }
  }

  /** A comparison operation with -1 default for NaNs */
  case object CMPL extends ComparisonOp

  /** A comparison operation with no default for NaNs */
  case object CMP extends ComparisonOp

    /** A comparison operation with +1 default for NaNs */
  case object CMPG extends ComparisonOp


  /** This class represents a test operation. */
  sealed abstract class TestOp {

    /** Returns the negation of this operation. */
    def negate(): TestOp

    /** Returns a string representation of this operation. */
    override def toString(): String

    /** used only from GenASM */
    def opcodeIF(): Int

    /** used only from GenASM */
    def opcodeIFICMP(): Int

  }

  /** An equality test */
  case object EQ extends TestOp {
    def negate() = NE
    override def toString() = "EQ"
    override def opcodeIF()     = scala.tools.asm.Opcodes.IFEQ
    override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPEQ
  }

  /** A non-equality test */
  case object NE extends TestOp {
    def negate() = EQ
    override def toString() = "NE"
    override def opcodeIF()     = scala.tools.asm.Opcodes.IFNE
    override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPNE
  }

  /** A less-than test */
  case object LT extends TestOp {
    def negate() = GE
    override def toString() = "LT"
    override def opcodeIF()     = scala.tools.asm.Opcodes.IFLT
    override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPLT
  }

  /** A greater-than-or-equal test */
  case object GE extends TestOp {
    def negate() = LT
    override def toString() = "GE"
    override def opcodeIF()     = scala.tools.asm.Opcodes.IFGE
    override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPGE
  }

  /** A less-than-or-equal test */
  case object LE extends TestOp {
    def negate() = GT
    override def toString() = "LE"
    override def opcodeIF()     = scala.tools.asm.Opcodes.IFLE
    override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPLE
  }

  /** A greater-than test */
  case object GT extends TestOp {
    def negate() = LE
    override def toString() = "GT"
    override def opcodeIF()     = scala.tools.asm.Opcodes.IFGT
    override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPGT
  }

  /** This class represents an arithmetic operation. */
  class ArithmeticOp {

    /** Returns a string representation of this operation. */
    override def toString(): String = this match {
      case ADD => "ADD"
      case SUB => "SUB"
      case MUL => "MUL"
      case DIV => "DIV"
      case REM => "REM"
      case NOT => "NOT"
      case _   => throw new RuntimeException("ArithmeticOp unknown case")
    }
  }

  /** An arithmetic addition operation */
  case object ADD extends ArithmeticOp

  /** An arithmetic subtraction operation */
  case object SUB extends ArithmeticOp

  /** An arithmetic multiplication operation */
  case object MUL extends ArithmeticOp

  /** An arithmetic division operation */
  case object DIV extends ArithmeticOp

  /** An arithmetic remainder operation */
  case object REM extends ArithmeticOp

  /** Bitwise negation. */
  case object NOT extends ArithmeticOp

  /** This class represents a shift operation. */
  class ShiftOp {

    /** Returns a string representation of this operation. */
    override def toString(): String = this match {
      case LSL =>  "LSL"
      case ASR =>  "ASR"
      case LSR =>  "LSR"
      case _  => throw new RuntimeException("ShiftOp unknown case")
    }
  }

  /** A logical shift to the left */
  case object LSL extends ShiftOp

  /** An arithmetic shift to the right */
  case object ASR extends ShiftOp

  /** A logical shift to the right */
  case object LSR extends ShiftOp

  /** This class represents a logical operation. */
  class LogicalOp {

    /** Returns a string representation of this operation. */
    override def toString(): String = this match {
      case AND => "AND"
      case OR  => "OR"
      case XOR => "XOR"
      case _  => throw new RuntimeException("LogicalOp unknown case")
    }
  }

  /** A bitwise AND operation */
  case object AND extends LogicalOp

  /** A bitwise OR operation */
  case object OR extends LogicalOp

  /** A bitwise XOR operation */
  case object XOR extends LogicalOp
}