opcodes.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 646 行 · 第 1/2 页
SCALA
646 行
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */// $Id: Opcodes.scala 13053 2007-10-11 14:39:17Z dragos $package scala.tools.nsc.backend.icodeimport scala.tools.nsc.ast._import scala.tools.nsc.util.{Position,NoPosition}/* A pattern match case THIS(clasz) => case CONSTANT(const) => case LOAD_ARRAY_ITEM(kind) => case LOAD_LOCAL(local) => case LOAD_FIELD(field, isStatic) => case LOAD_MODULE(module) => case STORE_ARRAY_ITEM(kind) => case STORE_LOCAL(local) => case STORE_FIELD(field, isStatic) => case CALL_PRIMITIVE(primitive) => case CALL_METHOD(method, style) => case NEW(kind) => case CREATE_ARRAY(elem, dims) => case IS_INSTANCE(tpe) => case CHECK_CAST(tpe) => case SWITCH(tags, labels) => case JUMP(whereto) => case CJUMP(success, failure, cond, kind) => case CZJUMP(success, failure, cond, kind) => case RETURN(kind) => case THROW() => case DROP(kind) => case DUP(kind) => case MONITOR_ENTER() => case MONITOR_EXIT() => case SCOPE_ENTER(lv) => case SCOPE_EXIT(lv) => case LOAD_EXCEPTION() =>*//** * The ICode intermediate representation. It is a stack-based * representation, very close to the JVM and .NET. It uses the * erased types of Scala and references Symbols to refer named entities * in the source files. */trait Opcodes { self: ICodes => import global.{Symbol, NoSymbol, Type, Name, Constant}; /** This class represents an instruction of the intermediate code. * Each case subclass will represent a specific operation. */ abstract class Instruction { /** This abstract method returns the number of used elements on the stack */ def consumed : Int = 0 /** This abstract method returns the number of produced elements on the stack */ def produced : Int = 0 /** This instruction consumes these types from the top of the stack, the first * element in the list is the deepest element on the stack. */ def consumedTypes: List[TypeKind] = Nil /** This instruction produces these types on top of the stack. */ def producedTypes: List[TypeKind] = Nil /** This method returns the difference of size of the stack when the instruction is used */ def difference = produced-consumed /** The corresponding position in the source file */ var pos: Position = NoPosition /** Used by dead code elimination. */ var useful: Boolean = false def setPos(p: Position): this.type = { pos = p this } } object opcodes { /** Loads "this" on top of the stack. * Stack: ... * ->: ...:ref */ case class THIS(clasz: Symbol) extends Instruction { /** Returns a string representation of this constant */ override def toString(): String = "THIS" override def consumed = 0 override def produced = 1 override def producedTypes = List(REFERENCE(clasz)) } /** Loads a constant on the stack. * Stack: ... * ->: ...:constant */ case class CONSTANT(constant: Constant) extends Instruction { /** Returns a string representation of this constant */ override def toString(): String = "CONSTANT ("+constant.toString()+")" override def consumed = 0 override def produced = 1 override def producedTypes = List(toTypeKind(constant.tpe)) } /** Loads an element of an array. The array and the index should * be on top of the stack. * Stack: ...:array[a](Ref):index(Int) * ->: ...:element(a) */ case class LOAD_ARRAY_ITEM(kind: TypeKind) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "LOAD_ARRAY_ITEM (" + kind + ")" override def consumed = 2 override def produced = 1 override def consumedTypes = List(ARRAY(kind), INT) override def producedTypes = List(kind) } /** Load a local variable on the stack. It can be a method argument. * Stack: ... * ->: ...:value */ case class LOAD_LOCAL(local: Local) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "LOAD_LOCAL "+local.toString() //+isArgument?" (argument)":""; override def consumed = 0 override def produced = 1 override def producedTypes = List(local.kind) } /** Load a field on the stack. The object to which it refers should be * on the stack. * Stack: ...:ref (assuming isStatic = false) * ->: ...:value */ case class LOAD_FIELD(field: Symbol, isStatic: Boolean) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "LOAD_FIELD " + (if (isStatic) field.fullNameString else field.toString()); override def consumed = if (isStatic) 0 else 1 override def produced = 1 override def consumedTypes = if (isStatic) Nil else List(REFERENCE(field.owner)); override def producedTypes = List(toTypeKind(field.tpe)); } case class LOAD_MODULE(module: Symbol) extends Instruction { assert(module != NoSymbol, "Invalid module symbol"); /** Returns a string representation of this instruction */ override def toString(): String = "LOAD_MODULE " + module.toString() override def consumed = 0 override def produced = 1 override def producedTypes = List(REFERENCE(module)) } /** Store a value into an array at a specified index. * Stack: ...:array[a](Ref):index(Int):value(a) * ->: ... */ case class STORE_ARRAY_ITEM(kind: TypeKind) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "STORE_ARRAY_ITEM (" + kind + ")" override def consumed = 3 override def produced = 0 override def consumedTypes = List(ARRAY(kind), INT, kind) } /** Store a value into a local variable. It can be an argument. * Stack: ...:value * ->: ... */ case class STORE_LOCAL(local: Local) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "STORE_LOCAL "+local.toString(); //+isArgument?" (argument)":""; override def consumed = 1 override def produced = 0 override def consumedTypes = List(local.kind) } /** Store a value into a field. * Stack: ...:ref:value (assuming isStatic=false) * ->: ... */ case class STORE_FIELD(field: Symbol, isStatic: Boolean) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "STORE_FIELD "+field.toString() + (if (isStatic) " (static)" else " (dynamic)"); override def consumed = if(isStatic) 1 else 2; override def produced = 0; override def consumedTypes = if (isStatic) List(toTypeKind(field.tpe)) else List(REFERENCE(field.owner), toTypeKind(field.tpe)); } /** Store a value into the 'this' pointer. * Stack: ...:ref * ->: ... */ case class STORE_THIS(kind: TypeKind) extends Instruction { override def toString() = "STORE_THIS(" + kind + ")" override def consumed = 1 override def produced = 0 override def consumedTypes = List(kind) } /** Call a primitive function. * Stack: ...:arg1:arg2:...:argn * ->: ...:result */ case class CALL_PRIMITIVE(primitive: Primitive) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String ="CALL_PRIMITIVE "+primitive.toString() override def consumed = primitive match { case Negation(_) => 1 case Test(_,_, true) => 1 case Test(_,_, false) => 2 case Comparison(_,_) => 2 case Arithmetic(NOT,_) => 1 case Arithmetic(_,_) => 2 case Logical(_,_) => 2 case Shift(_,_) => 2 case Conversion(_,_) => 1 case ArrayLength(_) => 1 case StringConcat(_) => 2 case StartConcat => 0 case EndConcat => 1 } override def produced = 1 override def consumedTypes = primitive match { case Negation(kind) => List(kind) case Test(_, kind, true) => List(kind) case Test(_, kind, false) => List(kind, kind) case Comparison(_, kind) => List(kind, kind) case Arithmetic(NOT, kind) => List(kind) case Arithmetic(_, kind) => List(kind, kind) case Logical(_, kind) => List(kind, kind) case Shift(_, kind) => List(kind, INT) case Conversion(from, _) => List(from) case ArrayLength(kind) => List(ARRAY(kind)) case StringConcat(kind) => List(ConcatClass, kind) case StartConcat => Nil case EndConcat => List(ConcatClass) } override def producedTypes = primitive match { case Negation(kind) => List(kind) case Test(_, _, true) => List(BOOL) case Test(_, _, false) => List(BOOL) case Comparison(_, _) => List(INT) case Arithmetic(_, kind) => List(kind) case Logical(_, kind) => List(kind) case Shift(_, kind) => List(kind) case Conversion(_, to) => List(to) case ArrayLength(_) => List(INT) case StringConcat(_) => List(ConcatClass) case StartConcat => List(ConcatClass) case EndConcat => List(REFERENCE(global.definitions.StringClass)) } } /** This class represents a CALL_METHOD instruction * STYLE: dynamic / static(StaticInstance) * Stack: ...:ref:arg1:arg2:...:argn * ->: ...:result * * STYLE: static(StaticClass) * Stack: ...:arg1:arg2:...:argn * ->: ...:result * */ case class CALL_METHOD(method: Symbol, style: InvokeStyle) extends Instruction { /** Returns a string representation of this instruction */ override def toString(): String = "CALL_METHOD " + hostClass.fullNameString + method.fullNameString +" ("+style.toString()+")"; var hostClass: Symbol = method.owner; def setHostClass(cls: Symbol): this.type = { hostClass = cls; this } override def consumed = { var result = method.tpe.paramTypes.length; result = result + (style match { case Dynamic => 1 case Static(true) => 1 case Static(false) => 0 case SuperCall(_) => 1 }); result;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?