diff options
author | schinz <schinz@epfl.ch> | 2003-10-23 11:34:35 +0000 |
---|---|---|
committer | schinz <schinz@epfl.ch> | 2003-10-23 11:34:35 +0000 |
commit | 39e04cd56dda8d57b54f3e785caecf4612bcda72 (patch) | |
tree | bb36fa57ea2e148d8c0c43578c13b9e9a068a889 | |
parent | 9efff672d7467da15fa9487d7cc9b4493ea25757 (diff) | |
download | scala-39e04cd56dda8d57b54f3e785caecf4612bcda72.tar.gz scala-39e04cd56dda8d57b54f3e785caecf4612bcda72.tar.bz2 scala-39e04cd56dda8d57b54f3e785caecf4612bcda72.zip |
- removed BCEL-based JVM back-end
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | Makefile.config | 5 | ||||
-rw-r--r-- | Makefile.distrib | 6 | ||||
-rw-r--r-- | config/list/compiler.lst | 2 | ||||
-rw-r--r-- | sources/bin/.scala_wrapper.tmpl | 9 | ||||
-rw-r--r-- | sources/scalac/CompilerCommand.java | 2 | ||||
-rw-r--r-- | sources/scalac/CompilerPhases.java | 6 | ||||
-rw-r--r-- | sources/scalac/Global.java | 3 | ||||
-rw-r--r-- | sources/scalac/backend/jvm/GenJVMBCEL.java | 1567 | ||||
-rw-r--r-- | sources/scalac/backend/jvm/GenJVMBCELPhase.java | 50 | ||||
-rw-r--r-- | sources/scalac/transformer/AddConstructors.java | 3 |
11 files changed, 3 insertions, 1654 deletions
@@ -79,7 +79,7 @@ COMPILER_ROOT = $(PROJECT_SOURCEDIR)/scalac COMPILER_LIST = $(call READLIST,$(PROJECT_LISTDIR)/compiler.lst) COMPILER_SOURCES += $(COMPILER_LIST:%=$(COMPILER_ROOT)/%) COMPILER_JC_FILES = $(filter %.java,$(COMPILER_SOURCES)) -COMPILER_JC_CLASSPATH = $(PROJECT_CLASSPATH):$(BCEL_JARFILE):$(MSIL_JARFILE):$(FJBG_JARFILE) +COMPILER_JC_CLASSPATH = $(PROJECT_CLASSPATH):$(MSIL_JARFILE):$(FJBG_JARFILE) COMPILER_SC_FILES = $(filter %.scala,$(COMPILER_SOURCES)) COMPILER_SC_CLASSPATH = $(COMPILER_JC_CLASSPATH) COMPILER_SCALAC = $(PROJECT_BOOTSTRAPDIR)/bin/scalac @@ -353,7 +353,6 @@ $(SCRIPTS_WRAPPER) : MACRO_VERSION ?= $(PROJECT_VERSION) $(SCRIPTS_WRAPPER) : MACRO_RUNTIME_SOURCES ?= $(PROJECT_SOURCEDIR) $(SCRIPTS_WRAPPER) : MACRO_RUNTIME_CLASSES ?= $(PROJECT_OUTPUTDIR) $(SCRIPTS_WRAPPER) : MACRO_TOOLS_CLASSES ?= $(PROJECT_OUTPUTDIR) -$(SCRIPTS_WRAPPER) : MACRO_BCEL_CLASSES ?= $(BCEL_JARFILE) $(SCRIPTS_WRAPPER) : MACRO_FJBG_CLASSES ?= $(FJBG_JARFILE) $(SCRIPTS_WRAPPER) : MACRO_MSIL_CLASSES ?= $(MSIL_JARFILE) $(SCRIPTS_WRAPPER) : MACRO_JAVA_ARGS ?= -enableassertions @@ -369,7 +368,6 @@ $(SCRIPTS_WRAPPER) : $(SCRIPTS_WRAPPER).tmpl $(call SCRIPTS_WRAPPER_MACRO,RUNTIME_SOURCES) \ $(call SCRIPTS_WRAPPER_MACRO,RUNTIME_CLASSES) \ $(call SCRIPTS_WRAPPER_MACRO,TOOLS_CLASSES) \ - $(call SCRIPTS_WRAPPER_MACRO,BCEL_CLASSES) \ $(call SCRIPTS_WRAPPER_MACRO,FJBG_CLASSES) \ $(call SCRIPTS_WRAPPER_MACRO,MSIL_CLASSES) \ $(call SCRIPTS_WRAPPER_MACRO,JAVA_ARGS) \ diff --git a/Makefile.config b/Makefile.config index c83f790815..abcff258a7 100644 --- a/Makefile.config +++ b/Makefile.config @@ -36,11 +36,6 @@ FJBG_JARFILE ?= $(FJBG_HOME)/fjbg.jar MSIL_HOME ?= $(PROJECT_LIBDIR)/msil MSIL_JARFILE ?= $(MSIL_HOME)/msil.jar -# BCEL (http://jakarta.apache.org/bcel/) -BCEL_HOME ?= $(PROJECT_LIBDIR)/bcel -BCEL_JARFILE ?= $(BCEL_HOME)/bcel.jar -BCEL_LICENSE ?= $(BCEL_HOME)/LICENSE - ############################################################################## # Standard tools diff --git a/Makefile.distrib b/Makefile.distrib index 3abb1f6dc8..aaf45edda4 100644 --- a/Makefile.distrib +++ b/Makefile.distrib @@ -50,8 +50,6 @@ INSTALL_RUNTIME_JARFILE = $(INSTALL_LIBDIR)/$(PROJECT_NAME).jar INSTALL_TOOLS_JARFILE = $(INSTALL_LIBDIR)/$(TOOLS_NAME).jar INSTALL_FJBG_JARFILE = $(INSTALL_LIBDIR)/fjbg.jar INSTALL_MSIL_JARFILE = $(INSTALL_LIBDIR)/msil.jar -INSTALL_BCEL_JARFILE = $(INSTALL_LIBDIR)/bcel.jar -INSTALL_BCEL_LICENSE = $(INSTALL_LIBDIR)/bcel.LICENSE install-clean : $(RM) -r $(INSTALL_PREFIX) @@ -74,7 +72,6 @@ install : $(TOOLS_JAR_ARCHIVE) MACRO_RUNTIME_SOURCES=$(INSTALL_SRCDIR) \ MACRO_RUNTIME_CLASSES=$(INSTALL_RUNTIME_JARFILE) \ MACRO_TOOLS_CLASSES=$(INSTALL_TOOLS_JARFILE) \ - MACRO_BCEL_CLASSES=$(INSTALL_BCEL_JARFILE) \ MACRO_FJBG_CLASSES=$(INSTALL_FJBG_JARFILE) \ MACRO_MSIL_CLASSES=$(INSTALL_MSIL_JARFILE) \ MACRO_JAVA_ARGS= \ @@ -85,8 +82,6 @@ install : $(TOOLS_JAR_ARCHIVE) $(INSTALL) -m 644 -p $(TOOLS_JAR_ARCHIVE) $(INSTALL_TOOLS_JARFILE) $(INSTALL) -m 644 -p $(FJBG_JARFILE) $(INSTALL_FJBG_JARFILE) $(INSTALL) -m 644 -p $(MSIL_JARFILE) $(INSTALL_MSIL_JARFILE) - $(INSTALL) -m 644 -p $(BCEL_JARFILE) $(INSTALL_BCEL_JARFILE) - $(INSTALL) -m 644 -p $(BCEL_LICENSE) $(INSTALL_BCEL_LICENSE) $(INSTALL) -m 755 -d $(INSTALL_SRCDIR) $(strip $(MIRROR) -m 644 -p -C $(LIBRARY_ROOT) $(LIBRARY_LIST:%='%') \ $(INSTALL_SRCDIR)/$(PROJECT_NAME)) @@ -136,7 +131,6 @@ install-windows : $(UNIX2DOS) $(INSTALL_PREFIX)/README $(UNIX2DOS) $(INSTALL_PREFIX)/LICENSE $(UNIX2DOS) $(INSTALL_PREFIX)/VERSION - $(UNIX2DOS) $(INSTALL_BCEL_LICENSE) $(TOUCH) $(INSTALL_PREFIX)/VERSION-$(INSTALL_VERSION) @root=`cd "$(INSTALL_PREFIX)"; pwd`; \ for file in "" $(SCRIPTS_WRAPPER_ALIASES); do \ diff --git a/config/list/compiler.lst b/config/list/compiler.lst index d14aa81552..4702e62f3b 100644 --- a/config/list/compiler.lst +++ b/config/list/compiler.lst @@ -42,8 +42,6 @@ backend/Primitive.java backend/Primitives.java backend/jvm/GenJVMPhase.java backend/jvm/GenJVM.java -backend/jvm/GenJVMBCELPhase.java -backend/jvm/GenJVMBCEL.java backend/msil/GenMSIL.java backend/msil/GenMSILPhase.java backend/msil/TypeCreator.java diff --git a/sources/bin/.scala_wrapper.tmpl b/sources/bin/.scala_wrapper.tmpl index c0c43f8d77..16c7745ce7 100644 --- a/sources/bin/.scala_wrapper.tmpl +++ b/sources/bin/.scala_wrapper.tmpl @@ -61,11 +61,6 @@ configure() { # This variable must refer a directory or a zip or jar file. MSIL_CLASSES={#MSIL_CLASSES#}; - # Location of the compiled bcel library. This library may be found - # at http://jakarta.apache.org/bcel/. - # This variable must refer a directory or a zip or jar file. - BCEL_CLASSES={#BCEL_CLASSES#}; - # Command to start the Java VM. JAVA_EXEC="java"; @@ -241,7 +236,6 @@ compute_variable() { TOOLS_CLASSES ) configure_path_variable "$1";; FJBG_CLASSES ) configure_path_variable "$1";; MSIL_CLASSES ) configure_path_variable "$1";; - BCEL_CLASSES ) configure_path_variable "$1";; JAVA_EXEC ) configure_variable "$1";; JAVA_ARGS ) configure_variable "$1";; EXEC ) configure_variable "$1";; @@ -286,7 +280,6 @@ exec_compile() { # compute Java classpath append_path JAVA_CLASSPATH TOOLS_CLASSES; - append_path JAVA_CLASSPATH BCEL_CLASSES; append_path JAVA_CLASSPATH FJBG_CLASSES; append_path JAVA_CLASSPATH MSIL_CLASSES; @@ -416,7 +409,6 @@ scala_info_option_x_variable() { TOOLS_CLASSES ) variable=$2;; FJBG_CLASSES ) variable=$2;; MSIL_CLASSES ) variable=$2;; - BCEL_CLASSES ) variable=$2;; JAVA_EXEC ) variable=$2;; JAVA_ARGS ) variable=$2;; EXEC ) variable=$2;; @@ -442,7 +434,6 @@ scala_info_option_help() { echo " TOOLS_CLASSES Location of the Scala tools"; echo " FJBG_CLASSES Location of the fjbg library"; echo " MSIL_CLASSES Location of the msil library"; - echo " BCEL_CLASSES Location of the bcel library"; echo " JAVA_EXEC Command to start the Java VM"; echo " JAVA_ARGS Additional arguments to pass to the Java VM"; echo " EXEC Command to start subprocesses"; diff --git a/sources/scalac/CompilerCommand.java b/sources/scalac/CompilerCommand.java index 906dddebf9..b67cf14b26 100644 --- a/sources/scalac/CompilerCommand.java +++ b/sources/scalac/CompilerCommand.java @@ -160,7 +160,7 @@ public class CompilerCommand extends CommandParser { "directory", "."), this.target = new ChoiceOptionParser(this, - "target", "Specify which bakend to use (jvm, jvm-bcel, msil)", + "target", "Specify which bakend to use (jvm, msil)", "target", Global.TARGETS, Global.TARGET_JVM), this.noimports = new BooleanOptionParser(this, diff --git a/sources/scalac/CompilerPhases.java b/sources/scalac/CompilerPhases.java index d1db650724..93007eda28 100644 --- a/sources/scalac/CompilerPhases.java +++ b/sources/scalac/CompilerPhases.java @@ -38,7 +38,6 @@ public class CompilerPhases { public final PhaseDescriptor ERASURE; public final PhaseDescriptor GENMSIL; public final PhaseDescriptor GENJVM; - public final PhaseDescriptor GENJVM_BCEL; public final PhaseDescriptor TERMINAL; //######################################################################## @@ -139,11 +138,6 @@ public class CompilerPhases { "generate JVM bytecodes", "generated JVM code", scalac.backend.jvm.GenJVMPhase.class), - this.GENJVM_BCEL = new PhaseDescriptor( - "genjvm-bcel", - "generate JVM bytecodes", - "generated JVM code", - scalac.backend.jvm.GenJVMBCELPhase.class), this.TERMINAL = new PhaseDescriptor( "terminal", "compilation terminated", diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java index 25780805d2..d13798fd8d 100644 --- a/sources/scalac/Global.java +++ b/sources/scalac/Global.java @@ -132,13 +132,11 @@ public class Global { */ public static final String TARGET_INT; public static final String TARGET_JVM; - public static final String TARGET_JVM_BCEL; public static final String TARGET_MSIL; public static final String[] TARGETS = new String[] { TARGET_INT = "int".intern(), TARGET_JVM = "jvm".intern(), - TARGET_JVM_BCEL = "jvm-bcel".intern(), TARGET_MSIL = "msil".intern(), }; @@ -213,7 +211,6 @@ public class Global { if (target != TARGET_JVM) args.phases.TAILCALL.addSkipFlag(); if (target != TARGET_MSIL) args.phases.GENMSIL.addSkipFlag(); if (target != TARGET_JVM) args.phases.GENJVM.addSkipFlag(); - if (target != TARGET_JVM_BCEL) args.phases.GENJVM_BCEL.addSkipFlag(); PHASE.freeze(); PhaseDescriptor[] descriptors = PHASE.phases(); this.firstPhase = descriptors[0].create(this); diff --git a/sources/scalac/backend/jvm/GenJVMBCEL.java b/sources/scalac/backend/jvm/GenJVMBCEL.java deleted file mode 100644 index cb26af50d9..0000000000 --- a/sources/scalac/backend/jvm/GenJVMBCEL.java +++ /dev/null @@ -1,1567 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -// TODO: create arrays with ANEWARRAY & friends - -// TODO: (maybe) add InnerClass attributes to .class files - -package scalac.backend.jvm; - -import ch.epfl.lamp.util.Position; - -import scalac.*; -import scalac.backend.*; -import scalac.util.*; -import scalac.ast.*; -import scalac.symtab.*; -import scalac.symtab.classfile.ClassfileConstants; -import scalac.transformer.*; - -import org.apache.bcel.*; -import org.apache.bcel.generic.*; -import org.apache.bcel.classfile.*; -import org.apache.bcel.generic.Type; - -import java.util.*; -import java.io.*; - -/** - * Backend generating JVM byte-codes. - * - * @version 1.0 - * @author Michel Schinz - */ - -class GenJVMBCEL { - protected final static String JAVA_LANG_OBJECT = "java.lang.Object"; - protected final static String JAVA_LANG_STRING = "java.lang.String"; - protected final static String JAVA_LANG_STRINGBUFFER = "java.lang.StringBuffer"; - protected final static String SCALA_RUNTIME_RUNTIME = "scala.runtime.RunTime"; - protected final static String SCALA_UNIT = "scala.Unit"; - - protected final static String MODULE_INSTANCE_FIELD_NAME = "MODULE$"; - protected final static String VOID_NO_ARGS_SIG = - Type.getMethodSignature(Type.VOID, Type.NO_ARGS); - protected final static String[] EMPTY_STRING_ARRAY = new String[0]; - - protected final static String UNIT_SIG = - (new ObjectType(SCALA_UNIT)).getSignature(); - - protected final static String CONSTRUCTOR_STRING = - Constants.CONSTRUCTOR_NAME; - protected final static Name CONSTRUCTOR_NAME = - Name.fromString(CONSTRUCTOR_STRING); - - protected Unit unit = null; - protected String sourceFileName = null; - - // Shortcut names for interfaces. - protected final static InstructionConstants ic = null; - protected final static Constants cst = null; - - protected final Global global; - protected final Definitions defs; - protected final Primitives prims; - - public GenJVMBCEL(Global global) { - this.global = global; - this.defs = global.definitions; - this.prims = global.primitives; - initTypeMap(); - initArithPrimMap(); - } - - public void translate(Unit unit) { - this.unit = unit; - sourceFileName = unit.source.toString(); - for (int i = 0; i < unit.body.length; ++i) - gen(unit.body[i]); - sourceFileName = null; - this.unit = null; - } - - // Context - protected ClassGen currClass = null; - protected String currClassName = null; - protected ConstantPoolGen currPool = null; - protected MethodGen currMethod = null; - protected InstructionList currIL = null; - protected Map currLocals = null; - protected boolean isModuleClass = false; - - static class InstrContext { - public case Empty; - public case New; - public case Assign; - public case If(InstructionHandle target, boolean when); - } - - // Line numbers attribution - protected HashMap/*<InstructionHandle,Integer>*/ lineAttributedInstrs; - - protected void gen(Tree tree) { - gen(tree, cst.T_VOID, InstrContext.Empty); - } - - protected void gen(Tree tree, byte expectedType) { - gen(tree, expectedType, InstrContext.Empty); - } - - protected void gen(Tree tree, InstrContext ctx) { - gen(tree, cst.T_VOID, ctx); - } - - protected void gen(Tree[] trees) { - for (int i = 0; i < trees.length; ++i) - gen(trees[i]); - } - - protected void gen(Tree[] trees, byte expectedType) { - for (int i = 0; i < trees.length; ++i) - gen(trees[i], expectedType); - } - - protected void gen(Tree[] trees, InstrContext ctx) { - for (int i = 0; i < trees.length; ++i) - gen(trees[i], ctx); - } - - protected void gen(Tree[] trees, byte expectedType, InstrContext ctx) { - for (int i = 0; i < trees.length; ++i) - gen(trees[i], expectedType, ctx); - } - - protected void gen(Tree tree, byte expectedType, InstrContext ctx) { - Symbol sym = tree.symbol(); - byte generatedType = cst.T_VOID; - - // Remember first instruction associated to this tree, to - // generate line numbers. - InstructionHandle startHandle; - if (currIL != null) - startHandle = currIL.getEnd(); - else - startHandle = null; - - switch (tree) { - case PackageDef(_, Tree.Template impl): - gen(impl); - break; - - case ClassDef(_, _, _, _, _, Tree.Template impl) : { - Tree.ClassDef classDef = (Tree.ClassDef)tree; - - boolean oldIsModuleClass = isModuleClass; - isModuleClass = Modifiers.Helper.isModClass(sym.flags); - enterClass(sym); - - addValueClassMembers(classDef); - if (isModuleClass) - addModuleInstanceField(); - - gen(impl); - leaveClass(sym); - isModuleClass = oldIsModuleClass; - } break; - - case Template(_, Tree[] body): - gen(body); - break; - - case ValDef(_, Name name, _, Tree rhs): { - if (currMethod == null) - break; // ignore ValDefs in classes, handled elsewhere - - Type valType = typeStoJ(sym.info()); - LocalVariableGen lGen = currMethod.addLocalVariable(name.toString(), - valType, - currIL.getEnd(), - null); - int index = lGen.getIndex(); - - if (rhs != Tree.Empty) - gen(rhs, valType.getType()); - else { - switch (valType.getType()) { - case cst.T_BOOLEAN: - case cst.T_BYTE: - case cst.T_CHAR: - case cst.T_SHORT: - case cst.T_INT: - currIL.append(new PUSH(currPool, 0)); break; - case cst.T_LONG: - currIL.append(new PUSH(currPool, 0L)); break; - case cst.T_FLOAT: - currIL.append(new PUSH(currPool, 0F)); break; - case cst.T_DOUBLE: - currIL.append(new PUSH(currPool, 0D)); break; - default: - currIL.append(ic.ACONST_NULL); break; - } - } - currIL.append(new Generic_STORE(index, valType)); - - currLocals.put(sym, new Integer(index)); - } break; - - case DefDef(_, _, _, _, _, Tree rhs): { - enterMethod((Tree.DefDef)tree); - if (! Modifiers.Helper.isAbstract(sym.flags)) { - Type retType = currMethod.getReturnType(); - gen(rhs, retType.getType()); - currIL.append(new Generic_RETURN(retType)); - } - leaveMethod(); - } break; - - case LabelDef(_, _, _): - global.fail("not implemented yet " + tree); - break; - - case Block(Tree[] stats): { - int statsNum = stats.length; - for (int i = 0; i < statsNum - 1; ++i) - gen(stats[i], cst.T_VOID); - if (statsNum == 0) - maybeLoadUnit(expectedType); - else - gen(stats[stats.length - 1], expectedType, ctx); - generatedType = expectedType; - } break; - - case Typed(Tree expr, _): - gen(expr, expectedType, ctx); - generatedType = expectedType; - break; - - case New(Tree.Template templ): { - assert templ.body.length == 0; - assert templ.parents.length == 1; - - String className = javaName(tree.type.symbol()); - currIL.append(new NEW(currPool.addClass(className))); - currIL.append(ic.DUP); - gen(templ.parents[0], InstrContext.New); - - generatedType = cst.T_OBJECT; - } break; - - case Apply(TypeApply(Tree fun, Tree[] args), _): { - Type type = typeStoJ(args[0].type); - int typeIndex; - if (type instanceof ObjectType) - typeIndex = currPool.addClass((ObjectType)type); - else if (type instanceof ArrayType) - typeIndex = currPool.addArrayClass((ArrayType)type); - else - throw global.fail("unexpected type " + type); - - genLoadQualifier(fun); - - if (fun.symbol() == defs.IS) { - currIL.append(new INSTANCEOF(typeIndex)); - generatedType = cst.T_BOOLEAN; - } else if (fun.symbol() == defs.AS) { - currIL.append(new CHECKCAST(typeIndex)); - generatedType = type.getType(); - } else - global.fail("unexpected type application"); - } break; - - case Apply(Tree fun, Tree[] args): { - if (isPrimitive(fun.symbol())) { - Tree.Select selectFun = (Tree.Select)fun; - Primitive prim = prims.getPrimitive(fun.symbol()); - - if (prim == Primitive.CONCAT) { - genStringConcatenation(liftStringConcatenations(tree)); - generatedType = cst.T_OBJECT; - } else { - Tree[] allArgs = new Tree[args.length + 1]; - allArgs[0] = unbox(selectFun.qualifier); - System.arraycopy(args, 0, allArgs, 1, args.length); - generatedType = genPrimitive(prim, - allArgs, - typeStoJ(tree.type).getType(), - expectedType, - ctx); - } - } else { - Symbol funSym = fun.symbol(); - Type[] argTypes = argTypesStoJ(funSym.info()); - Type retType = retTypeStoJ(funSym.info()); - boolean isStatic = isStaticMember(funSym); - if (!isStatic && ctx != InstrContext.New) - genLoadQualifier(fun); - for (int i = 0; i < args.length; ++i) - gen(args[i], argTypes[i].getType()); - - String className = javaName(funSym.owner()); - String methodName = funSym.name.toString(); - String methodSig = Type.getMethodSignature(retType, argTypes); - - if (funSym.owner().isInterface()) { - int methodIndex = - currPool.addInterfaceMethodref(className, methodName, methodSig); - int argsSize = 1; - - for (int i = 0; i < args.length; ++i) - argsSize += argTypes[i].getSize(); - currIL.append(new INVOKEINTERFACE(methodIndex, argsSize)); - } else { - int methodIndex = - currPool.addMethodref(className, methodName, methodSig); - boolean isConstrCall = (funSym.name == CONSTRUCTOR_NAME); - boolean isSuperCall; - switch (fun) { - case Select(Super(_, _), _): isSuperCall = true; break; - default: isSuperCall = false; break; - } - - if (isConstrCall || isSuperCall) { - currIL.append(new INVOKESPECIAL(methodIndex)); - if (isConstrCall && isSuperCall && isModuleClass) { - // Initialise module instance field ASAP - String currClassSig = - new ObjectType(currClassName).getSignature(); - int fieldRef = - currPool.addFieldref(currClassName, - MODULE_INSTANCE_FIELD_NAME, - currClassSig); - currIL.append(ic.THIS); - currIL.append(new PUTSTATIC(fieldRef)); - } - } else if (isStatic) - currIL.append(new INVOKESTATIC(methodIndex)); - else - currIL.append(new INVOKEVIRTUAL(methodIndex)); - } - - generatedType = retType.getType(); - } - } break; - - case Ident(Name name): { - Type type = typeStoJ(sym.info()); - if (sym.isModule()) - generatedType = genLoadModule(sym); - else if (sym == defs.NULL) { - currIL.append(ic.ACONST_NULL); - generatedType = expectedType; - } else if (sym.owner().isClass()) { - currIL.append(ic.THIS); - int fieldIdx = currPool.addFieldref(currClassName, - name.toString(), - type.getSignature()); - if (ctx == InstrContext.Assign) { - currIL.append(new PUTFIELD(fieldIdx)); - generatedType = cst.T_VOID; - } else { - currIL.append(new GETFIELD(fieldIdx)); - generatedType = type.getType(); - } - } else { - assert currLocals.containsKey(sym) - : Debug.show(sym) + " not in " + currLocals; - int pos = ((Integer)currLocals.get(sym)).intValue(); - if (ctx == InstrContext.Assign) { - currIL.append(new Generic_STORE(pos, type)); - generatedType = cst.T_VOID; - } else { - currIL.append(new Generic_LOAD(pos, type)); - generatedType = type.getType(); - } - } - } break; - - case Select(Tree qualifier, Name selector): { - if (sym.isModule()) - generatedType = genLoadModule(sym); - else { - Type fieldType = typeStoJ(sym.info()); - int fieldIdx = currPool.addFieldref(javaName(sym.owner()), - selector.toString(), - fieldType.getSignature()); - if (isStaticMember(sym)) { - if (ctx == InstrContext.Assign) { - currIL.append(new PUTSTATIC(fieldIdx)); - generatedType = cst.T_VOID; - } else { - currIL.append(new GETSTATIC(fieldIdx)); - generatedType = fieldType.getType(); - } - } else { - genLoadQualifier(tree); - if (ctx == InstrContext.Assign) { - currIL.append(new PUTFIELD(fieldIdx)); - generatedType = cst.T_VOID; - } else { - currIL.append(new GETFIELD(fieldIdx)); - generatedType = fieldType.getType(); - } - } - } - } break; - - case Assign(Tree lhs, Tree rhs): { - gen(lhs, InstrContext.Assign); - InstructionHandle storeHandle = currIL.getEnd(); - gen(rhs, typeStoJ(lhs.symbol().info()).getType()); - // Work around BCEL bug (see below) - currIL.move(storeHandle, currIL.append(ic.NOP).getPrev()); - } break; - - case If(Tree cond, Tree thenp, Tree elsep): { - byte finalType = typeStoJ(tree.type).getType(); - - InstructionHandle fakeElseH = currIL.append(ic.NOP); - gen(cond, cst.T_VOID, new InstrContext.If(fakeElseH, false)); - InstructionHandle thenH = currIL.append(ic.NOP); - gen(thenp, finalType); - BranchInstruction gotoAfter = new GOTO(null); - currIL.append(gotoAfter); - InstructionHandle elseH = currIL.append(ic.NOP); - if (elsep == Tree.Empty) - maybeLoadUnit(finalType); - else - gen(elsep, finalType); - gotoAfter.setTarget(currIL.append(ic.NOP)); - // We cannot move the instructions sooner because BCEL has - // a bug which makes it impossible to move instructions at - // the end of the list. - currIL.move(fakeElseH, elseH); - generatedType = finalType; - } break; - - case This(_): - currIL.append(ic.THIS); - generatedType = cst.T_OBJECT; - break; - - case Literal(Object value): - if (value instanceof Integer) { - generatedType = cst.T_INT; - currIL.append(new PUSH(currPool, (Integer)value)); - } else if (value instanceof Long) { - generatedType = cst.T_LONG; - currIL.append(new PUSH(currPool, (Long)value)); - } else if (value instanceof Float) { - generatedType = cst.T_FLOAT; - currIL.append(new PUSH(currPool, (Float)value)); - } else if (value instanceof Double) { - generatedType = cst.T_DOUBLE; - currIL.append(new PUSH(currPool, (Double)value)); - } else if (value instanceof Character) { - generatedType = cst.T_CHAR; - currIL.append(new PUSH(currPool, (Character)value)); - } else if (value instanceof String) { - generatedType = cst.T_OBJECT; - currIL.append(new PUSH(currPool, (String)value)); - } else if (value instanceof Boolean) { - generatedType = cst.T_BOOLEAN; - currIL.append(new PUSH(currPool, (Boolean)value)); - } else - throw global.fail("unknown literal " + value); - break; - - case Empty: - case AbsTypeDef(_, _, _, _): - case AliasTypeDef(_, _, _, _): - case TypeApply(_, _): - case FunType(_, _): - case CompoundType(_, _): - case AppliedType(_,_): - break; - - case Sequence(_): - case Super(_, _): - case ModuleDef(_,_,_,_): - case PatDef(_,_,_): - case Import(_, _): - case CaseDef(_, _, _): - case Visitor(_): - case Function(_, _): - throw global.fail("unexpected node", tree); - case Bad(): - throw global.fail("bad tree"); - default: - throw global.fail("unknown node", tree); - } - - // Pop unneeded result from stack, or widen it if needed. - if (expectedType == cst.T_VOID && generatedType != cst.T_VOID) { - if (generatedType == cst.T_LONG || generatedType == cst.T_DOUBLE) - currIL.append(ic.POP2); - else { - switch (ctx) { - case If(InstructionHandle target, boolean when): - assert generatedType == cst.T_BOOLEAN : generatedType; - currIL.append(when ? new IFNE(target) : new IFEQ(target)); - break; - default: - currIL.append(ic.POP); - } - } - } else if (! (expectedType == cst.T_VOID - || generatedType == expectedType - || (generatedType == cst.T_ARRAY - && expectedType == cst.T_OBJECT))) - genWidenConversion(generatedType, expectedType); - - // Associate line numbers to instructions we just generated. - if (currIL != null) { - InstructionHandle ih = - (startHandle == null ? currIL.getStart() : startHandle); - int prevLine = -1; - while (ih != null) { - if (lineAttributedInstrs.containsKey(ih)) - prevLine = ((Integer)lineAttributedInstrs.get(ih)).intValue(); - else { - int line = Position.line(tree.pos); - lineAttributedInstrs.put(ih, new Integer(line)); - if (line != prevLine) { - currMethod.addLineNumber(ih, line); - prevLine = line; - } - } - ih = ih.getNext(); - } - } - } - - protected Tree unbox(Tree tree) { - switch (tree) { - case Apply(Tree fun, Tree[] args): - if (prims.getPrimitive(fun.symbol()) == Primitive.BOX) { - assert args.length == 1; - return args[0]; - } else - return tree; - case Block(Tree[] stats): - if (stats.length == 2 - && prims.getPrimitive(stats[1].symbol()) == Primitive.BOX) { - return stats[0]; - } else - return tree; - default: - return tree; - } - } - - // Add field containing module instance, and code to - // initialize it, to current class. - protected void addModuleInstanceField() { - FieldGen instanceField = - new FieldGen(cst.ACC_PUBLIC - | cst.ACC_FINAL - | cst.ACC_STATIC, - new ObjectType(currClassName), - MODULE_INSTANCE_FIELD_NAME, - currPool); - currClass.addField(instanceField.getField()); - - InstructionList initIL = new InstructionList(); - - int constrRef = currPool.addMethodref(currClassName, - CONSTRUCTOR_STRING, - VOID_NO_ARGS_SIG); - - initIL.append(new NEW(currPool.addClass(currClassName))); - initIL.append(new INVOKESPECIAL(constrRef)); - initIL.append(ic.RETURN); - - MethodGen initMethod = - new MethodGen(cst.ACC_PUBLIC | cst.ACC_STATIC, - Type.VOID, Type.NO_ARGS, Strings.EMPTY_ARRAY, - "<clinit>", - currClassName, - initIL, - currPool); - initMethod.setMaxStack(); - currClass.addMethod(initMethod.getMethod()); - } - - // Add value members (i.e. fields) to current class. - protected void addValueClassMembers(Tree.ClassDef cDef) { - Symbol cSym = cDef.symbol(); - Scope.SymbolIterator memberIt = - new Scope.UnloadIterator(cSym.members().iterator()); - while (memberIt.hasNext()) { - Symbol member = memberIt.next(); - if (member.isTerm() && !member.isMethod()) { - FieldGen fGen = new FieldGen(modifiersStoJ(member.flags), - typeStoJ(member.info()), - member.name.toString(), - currPool); - currClass.addField(fGen.getField()); - } - } - } - - protected void maybeLoadUnit(byte expectedType) { - if (expectedType == cst.T_OBJECT) { - int unitFieldRef = currPool.addFieldref(SCALA_RUNTIME_RUNTIME, - "UNIT_VAL", - UNIT_SIG); - currIL.append(new GETSTATIC(unitFieldRef)); - } - } - - protected byte genLoadModule(Symbol sym) { - String javaSymName = javaName(sym.moduleClass()); - if (javaSymName.equals(currClassName)) - currIL.append(ic.THIS); - else { - int moduleInstIdx = - currPool.addFieldref(javaSymName, - MODULE_INSTANCE_FIELD_NAME, - typeStoJ(sym.info()).getSignature()); - currIL.append(new GETSTATIC(moduleInstIdx)); - } - return cst.T_OBJECT; - } - - protected void genLoadQualifier(Tree tree) { - switch (tree) { - case Select(Super(_, _), _): - case Ident(_): - currIL.append(ic.THIS); - break; - case Select(Tree qualifier, _): - gen(qualifier, cst.T_OBJECT); - break; - default: - throw global.fail("unknown qualifier"); - } - } - - protected boolean isStaticMember(Symbol sym) { - return (sym.name != CONSTRUCTOR_NAME) - && sym.owner().isModuleClass() - && sym.owner().isJava(); - } - - protected boolean isPrimitive(Symbol sym) { - if (prims.isPrimitive(sym)) { - switch (prims.getPrimitive(sym)) { - case POS : case NEG : - case ADD : case SUB : case MUL : case DIV : case MOD : - case NOT : case OR : case XOR : case AND : - case LSL : case LSR : case ASR : - case EQ : case NE : case LT : case LE : case GE : case GT : - case ZNOT : case ZOR : case ZAND : - case NEW_ZARRAY : case NEW_BARRAY : case NEW_SARRAY : - case NEW_CARRAY : case NEW_IARRAY : case NEW_LARRAY : - case NEW_FARRAY : case NEW_DARRAY : - case ZARRAY_GET : case BARRAY_GET : case SARRAY_GET : - case CARRAY_GET : case IARRAY_GET : case LARRAY_GET : - case FARRAY_GET : case DARRAY_GET : case OARRAY_GET : - case ZARRAY_SET : case BARRAY_SET : case SARRAY_SET : - case CARRAY_SET : case IARRAY_SET : case LARRAY_SET : - case FARRAY_SET : case DARRAY_SET : case OARRAY_SET : - case ZARRAY_LENGTH : case BARRAY_LENGTH : case SARRAY_LENGTH : - case CARRAY_LENGTH : case IARRAY_LENGTH : case LARRAY_LENGTH : - case FARRAY_LENGTH : case DARRAY_LENGTH : case OARRAY_LENGTH : - case IS : case AS : - case CONCAT : - case THROW : - case AS_UVALUE : - return true; - - case AS_ZVALUE : case AS_BVALUE : case AS_SVALUE : - case AS_CVALUE : case AS_IVALUE : case AS_LVALUE : - case AS_FVALUE : case AS_DVALUE : - case AS_ZARRAY : case AS_BARRAY : case AS_SARRAY : - case AS_CARRAY : case AS_IARRAY : case AS_LARRAY : - case AS_FARRAY : case AS_DARRAY : case AS_OARRAY : - case NEW_OARRAY : - case EQUALS : - case HASHCODE : - case TOSTRING : - case BOX : - case APPLY : case UPDATE : case LENGTH : - return false; - default: - throw Debug.abort("unknown primitive", sym); - } - } else - return false; - } - - protected byte genPrimitive(Primitive prim, - Tree[] args, - byte resType, - byte expectedType, - InstrContext ctx) { - switch (prim) { - case POS: case NEG: - case ADD: case SUB: case MUL: case DIV: case MOD: - case NOT: case OR : case XOR: case AND: - case LSL: case LSR: case ASR: - return genArithPrim(prim, args, resType, expectedType, ctx); - case EQ: case NE: case LT: case LE: case GE: case GT: - case ZNOT: case ZOR: case ZAND: - return genCompOrLogicalPrim(prim, args, resType, expectedType, ctx); - case THROW: - assert args.length == 1; - return genThrow(args[0]); - case NEW_ZARRAY : - case NEW_BARRAY : - case NEW_SARRAY : - case NEW_CARRAY : - case NEW_IARRAY : - case NEW_LARRAY : - case NEW_FARRAY : - case NEW_DARRAY : - return genArrayCreate(prim, args[1]); -// case NEW_OARRAY : -// return genArrayCreate(prim, args[1], args[2]); - case ZARRAY_SET : case BARRAY_SET : case SARRAY_SET : - case CARRAY_SET : case IARRAY_SET : case LARRAY_SET : - case FARRAY_SET : case DARRAY_SET : case OARRAY_SET : - assert args.length == 4; - return genArrayUpdate(args[1], args[2], args[3]); - case ZARRAY_GET : case BARRAY_GET : case SARRAY_GET : - case CARRAY_GET : case IARRAY_GET : case LARRAY_GET : - case FARRAY_GET : case DARRAY_GET : case OARRAY_GET : - assert args.length == 3 : "get - " + args.length; - return genArrayAccess(args[1], args[2]); - case ZARRAY_LENGTH : case BARRAY_LENGTH : case SARRAY_LENGTH : - case CARRAY_LENGTH : case IARRAY_LENGTH : case LARRAY_LENGTH : - case FARRAY_LENGTH : case DARRAY_LENGTH : case OARRAY_LENGTH : - assert args.length == 2 : args.length; - return genArrayLength(args[1]); - case AS_UVALUE : - assert args.length == 1; - gen(args[0], cst.T_VOID); - return cst.T_VOID; - default: - throw Debug.abort("unknown primitive ", prim); - } - } - - protected Map/*<Primitive, Instruction>*/ arithPrimMap; - protected void addPrim(Primitive prim, - Instruction z, - Instruction i, - Instruction l, - Instruction f, - Instruction d) { - arithPrimMap.put(prim, new Instruction[] { z, i, l, f, d }); - } - - protected void initArithPrimMap() { - arithPrimMap = new HashMap(); - /* boolean int ... long float double */ - addPrim(Primitive.ADD , null, ic.IADD , ic.LADD , ic.FADD , ic.DADD); - addPrim(Primitive.SUB , null, ic.ISUB , ic.LSUB , ic.FSUB , ic.DSUB); - addPrim(Primitive.MUL , null, ic.IMUL , ic.LMUL , ic.FMUL , ic.DMUL); - addPrim(Primitive.DIV , null, ic.IDIV , ic.LDIV , ic.FDIV , ic.DDIV); - addPrim(Primitive.MOD , null, ic.IREM , ic.LREM , ic.FREM , ic.DREM); - addPrim(Primitive.AND , ic.IAND, ic.IAND , ic.LAND , null , null); - addPrim(Primitive.OR , ic.IOR, ic.IOR , ic.LOR , null , null); - addPrim(Primitive.XOR , ic.IXOR, ic.IXOR , ic.LXOR , null , null); - addPrim(Primitive.LSL , null, ic.ISHL , ic.LSHL , null , null); - addPrim(Primitive.LSR , null, ic.IUSHR , ic.LUSHR , null , null); - addPrim(Primitive.ASR , null, ic.ISHR , ic.LSHR , null , null); - addPrim(Primitive.POS , null, null , null , null , null); - addPrim(Primitive.NEG , null, ic.INEG , ic.LNEG , ic.FNEG , ic.DNEG); - } - - protected byte genArithPrim(Primitive prim, - Tree[] args, - byte resType, - byte expectedType, - InstrContext ctx) { - int arity = args.length; - int resTypeIdx = getTypeIndex(resType); - - for (int i = 0; i < arity; ++i) - gen(args[i], resType); - - if (prim == Primitive.NOT) { - assert resType == cst.T_INT || resType == cst.T_LONG; - boolean isLong = (resType == cst.T_LONG); - if (isLong) { - currIL.append(new PUSH(currPool, -1L)); - currIL.append(ic.LXOR); - } else { - currIL.append(new PUSH(currPool, -1)); - currIL.append(ic.IXOR); - } - } else { - assert arithPrimMap.containsKey(prim); - Instruction primInst = ((Instruction[])arithPrimMap.get(prim))[resTypeIdx]; - if (primInst != null) - currIL.append(primInst); - } - return resType; - } - - protected byte genCompOrLogicalPrim(Primitive prim, - Tree[] args, - byte resType, - byte expectedType, - InstrContext ctx) { - // Ensure that all comparisons happen in the context of an - // "if". - InstructionHandle target; - boolean when; - InstructionList epilogue = new InstructionList(); - byte realResType; - switch (ctx) { - case InstrContext.If(InstructionHandle t, boolean w): - target = t; when = w; realResType = cst.T_VOID; break; - default: - epilogue.append(ic.ICONST_1); - BranchInstruction gotoAfter = new GOTO(null); - epilogue.append(gotoAfter); - target = epilogue.append(ic.ICONST_0); - gotoAfter.setTarget(epilogue.append(ic.NOP)); - when = false; - realResType = cst.T_BOOLEAN; - break; - } - - if (prim == Primitive.ZNOT - || prim == Primitive.ZOR - || prim == Primitive.ZAND) - genLogicalPrim(prim, args, resType, expectedType, target, when); - else - genCompPrim(prim, args, resType, expectedType, target, when); - - currIL.append(epilogue); - return realResType; - } - - protected byte getMaxType(Tree[] trees) { - byte maxType = cst.T_BOOLEAN; - int maxTypeIdx = getTypeIndex(maxType); - - for (int i = 0; i < trees.length; ++i) { - byte argType = typeStoJ(trees[i].type).getType(); - if (getTypeIndex(argType) > maxTypeIdx) { - maxType = argType; - maxTypeIdx = getTypeIndex(maxType); - } - } - return maxType; - } - - protected static int tempCounter = 1; - protected void genCompPrim(Primitive prim, - Tree[] args, - byte resType, - byte expectedType, - InstructionHandle target, - boolean when) { - byte maxType = getMaxType(args); - int maxTypeIdx = getTypeIndex(maxType); - int intTypeIdx = getTypeIndex(Type.INT); - boolean intCompareWithZero = false; - for (int i = 0; i < args.length; ++i) { - boolean isIntZero = false; - if (maxTypeIdx <= intTypeIdx) { - switch (args[i]) { - case Literal(Object val): - int intVal; - if (val instanceof Number) - intVal = ((Number)val).intValue(); - else if (val instanceof Character) - intVal = ((Character)val).charValue(); - else if (val instanceof Boolean) - intVal = ((Boolean)val).booleanValue() ? 1 : 0; - else - throw Debug.abort("unknown literal", val); - if (intVal == 0) { - isIntZero = true; - if (i == 0) prim = prim.swap(); - } - } - } - if (intCompareWithZero || !isIntZero) - gen(args[i], maxType); - intCompareWithZero |= isIntZero; - } - - if (maxType == cst.T_OBJECT) { - assert prim == Primitive.EQ || prim == Primitive.NE; - - LocalVariableGen lGen = - currMethod.addLocalVariable("temp" + tempCounter++, - Type.OBJECT, - currIL.getEnd(), - null); - currIL.append(new ASTORE(lGen.getIndex())); - currIL.append(ic.DUP); - BranchInstruction ifNonNull = new IFNONNULL(null); - currIL.append(ifNonNull); - currIL.append(ic.POP); - currIL.append(new ALOAD(lGen.getIndex())); - if (when ^ (prim != Primitive.EQ)) - currIL.append(new IFNULL(target)); - else - currIL.append(new IFNONNULL(target)); - BranchInstruction gotoAfter = new GOTO(null); - currIL.append(gotoAfter); - InstructionHandle nonNullHandle = - currIL.append(new ALOAD(lGen.getIndex())); - ifNonNull.setTarget(nonNullHandle); - lGen.setEnd(nonNullHandle); - String equalsSig = - Type.getMethodSignature(Type.BOOLEAN, - new Type[] { Type.OBJECT }); - int equalsIndex = - currPool.addMethodref(JAVA_LANG_OBJECT, "equals", equalsSig); - currIL.append(new INVOKEVIRTUAL(equalsIndex)); - if (when ^ (prim != Primitive.EQ)) - currIL.append(new IFNE(target)); - else - currIL.append(new IFEQ(target)); - gotoAfter.setTarget(currIL.append(ic.NOP)); - } else if (maxTypeIdx <= intTypeIdx && !intCompareWithZero) { - switch (maybeNegatedPrim(prim, !when)) { - case LT: currIL.append(new IF_ICMPLT(target)); break; - case LE: currIL.append(new IF_ICMPLE(target)); break; - case EQ: currIL.append(new IF_ICMPEQ(target)); break; - case NE: currIL.append(new IF_ICMPNE(target)); break; - case GE: currIL.append(new IF_ICMPGE(target)); break; - case GT: currIL.append(new IF_ICMPGT(target)); break; - default: throw global.fail("unknown primitive " + prim); - } - } else { - switch (maxType) { - case cst.T_LONG: currIL.append(ic.LCMP); break; - case cst.T_FLOAT: currIL.append(ic.FCMPG); break; - case cst.T_DOUBLE: currIL.append(ic.DCMPG); break; - default: - ; // do nothing (int comparison with 0) - } - switch (maybeNegatedPrim(prim, !when)) { - case LT: currIL.append(new IFLT(target)); break; - case LE: currIL.append(new IFLE(target)); break; - case EQ: currIL.append(new IFEQ(target)); break; - case NE: currIL.append(new IFNE(target)); break; - case GE: currIL.append(new IFGE(target)); break; - case GT: currIL.append(new IFGT(target)); break; - default: throw global.fail("unknown primitive " + prim); - } - } - } - - protected Primitive maybeNegatedPrim(Primitive prim, boolean negate) { - return negate ? prim.negate() : prim; - } - - protected void genLogicalPrim(Primitive prim, - Tree[] args, - byte resType, - byte expectedType, - InstructionHandle target, - boolean when) { - if (prim == Primitive.ZNOT) - gen(args[0], new InstrContext.If(target, !when)); - else { - InstructionHandle fakeAfterH = currIL.append(ic.NOP); - if (when ^ (prim == Primitive.ZAND)) { - // x || y jump if true or x && y jump if false - gen(args[0], new InstrContext.If(target, when)); - gen(args[1], new InstrContext.If(target, when)); - } else { - // x || y jump if false or x && y jump if true - gen(args[0], new InstrContext.If(fakeAfterH, !when)); - gen(args[1], new InstrContext.If(target, when)); - currIL.move(fakeAfterH, currIL.append(ic.NOP).getPrev()); - } - } - } - - protected byte genThrow(Tree arg) { - gen(arg, cst.T_OBJECT); - currIL.append(new CHECKCAST(currPool.addClass("java.lang.Throwable"))); - currIL.append(ic.ATHROW); - return cst.T_OBJECT; - } - - protected byte genArrayCreate(Primitive prim, Tree size) { - gen(size, cst.T_INT); - byte type; - switch (prim) { - case NEW_ZARRAY : type = cst.T_BOOLEAN; break; - case NEW_BARRAY : type = cst.T_BYTE; break; - case NEW_SARRAY : type = cst.T_SHORT; break; - case NEW_CARRAY : type = cst.T_CHAR; break; - case NEW_IARRAY : type = cst.T_INT; break; - case NEW_LARRAY : type = cst.T_LONG; break; - case NEW_FARRAY : type = cst.T_FLOAT; break; - case NEW_DARRAY : type = cst.T_DOUBLE; break; - default: throw Debug.abort("unexpected primitive", prim); - } - currIL.append(new NEWARRAY(type)); - return cst.T_ARRAY; - } - - protected byte genArrayUpdate(Tree array, Tree index, Tree value) { - ArrayType arrayType = (ArrayType)typeStoJ(array.type); - Type elemType = arrayType.getElementType(); - gen(array, cst.T_ARRAY); - gen(index, cst.T_INT); - if (elemType instanceof BasicType) - value = unbox(value); - gen(value, elemType.getType()); - currIL.append(new Generic_ASTORE(elemType)); - return cst.T_VOID; - } - - protected byte genArrayAccess(Tree array, Tree index) { - ArrayType arrayType = (ArrayType)typeStoJ(array.type); - Type elemType = arrayType.getElementType(); - gen(array, cst.T_ARRAY); - gen(index, cst.T_INT); - currIL.append(new Generic_ALOAD(elemType)); - return elemType.getType(); - } - - protected byte genArrayLength(Tree array) { - gen(array, cst.T_ARRAY); - currIL.append(ic.ARRAYLENGTH); - return cst.T_INT; - } - - protected Tree[] liftStringConcatenations(Tree tree) { - LinkedList accu = new LinkedList(); - liftStringConcatenations(tree, accu); - return (Tree[])accu.toArray(new Tree[accu.size()]); - } - - protected void liftStringConcatenations(Tree tree, LinkedList accu) { - switch (tree) { - case Apply(Select(Tree qualifier, Name selector), Tree[] args): { - Symbol funSym = ((Tree.Apply)tree).fun.symbol(); - if (prims.isPrimitive(funSym) - && prims.getPrimitive(funSym) == Primitive.CONCAT) { - liftStringConcatenations(qualifier, accu); - liftStringConcatenations(args[0], accu); - } else - accu.addLast(tree); - } break; - default: - accu.addLast(tree); - } - } - - protected void genStringConcatenation(Tree[] elements) { - ObjectType strBufType = new ObjectType (JAVA_LANG_STRINGBUFFER); - - int constRef = currPool.addMethodref(JAVA_LANG_STRINGBUFFER, - "<init>", - VOID_NO_ARGS_SIG); - currIL.append (new NEW (currPool.addClass (JAVA_LANG_STRINGBUFFER))); - currIL.append (ic.DUP); - currIL.append (new INVOKESPECIAL (constRef)); - - for (int i = 0; i < elements.length; ++i) { - Type elemType = typeStoJ(elements[i].type); - if (!elemType.equals(Type.STRING) - && elemType.getType() == cst.T_OBJECT) - elemType = Type.OBJECT; - String appendSig = - Type.getMethodSignature(strBufType, new Type[] { elemType }); - int appendRef = - currPool.addMethodref(JAVA_LANG_STRINGBUFFER, "append", appendSig); - gen(elements[i], elemType.getType()); - currIL.append(new INVOKEVIRTUAL(appendRef)); - } - - String toStringSig = Type.getMethodSignature (Type.STRING, Type.NO_ARGS); - final int toStringRef = - currPool.addMethodref (JAVA_LANG_STRINGBUFFER, "toString", toStringSig); - currIL.append (new INVOKEVIRTUAL (toStringRef)); - } - - protected int getTypeIndex(Type tp) { - return getTypeIndex(tp.getType()); - } - - protected int getTypeIndex(byte tp) { - switch (tp) { - case cst.T_BOOLEAN: return 0; - case cst.T_BYTE: - case cst.T_CHAR: - case cst.T_SHORT: - case cst.T_INT: return 1; - case cst.T_LONG: return 2; - case cst.T_FLOAT: return 3; - case cst.T_DOUBLE: return 4; - case cst.T_ARRAY: - case cst.T_OBJECT: return 5; - default: return -1; - } - } - - protected Instruction[][] WIDENING_CONVERSION_TABLE = { - /* bool int long float double */ - /* boolean */ { null, null , null , null , null }, - /* int ... */ { null, null , ic.I2L , ic.I2F , ic.I2D }, - /* long */ { null, null , null , ic.L2F , ic.L2D }, - /* float */ { null, null , null , null , ic.F2D }, - /* double */ { null, null , null , null , null } - }; - - protected void genWidenConversion(byte origType, byte finalType) { - int origIdx = getTypeIndex(origType); - int finalIdx = getTypeIndex(finalType); - - assert (origIdx <= 4 && finalIdx <= 4) - : cst.TYPE_NAMES[origType] + " -> " + cst.TYPE_NAMES[finalType]; - Instruction instr = WIDENING_CONVERSION_TABLE[origIdx][finalIdx]; - if (instr != null) - currIL.append(instr); - } - - protected void dumpModuleMainClass(ClassGen modClassGen) { - String moduleName = modClassGen.getClassName(); - String mainClassName = moduleName.substring(0, moduleName.length() - 1); - ClassGen mainClassGen = new ClassGen(mainClassName, - JAVA_LANG_OBJECT, - sourceFileName, - cst.ACC_SUPER - | cst.ACC_PUBLIC - | cst.ACC_FINAL, - Strings.EMPTY_ARRAY); - ConstantPoolGen mainPool = mainClassGen.getConstantPool(); - - Method[] methods = modClassGen.getMethods(); - for (int i = 0; i < methods.length; ++i) { - Method m = methods[i]; - if (m.isProtected() || m.isPrivate() || m.isStatic() - || m.getName().equals("<init>")) - continue; - - MethodGen mGen = new MethodGen(m, moduleName, mainPool); - - Type[] argTypes = mGen.getArgumentTypes(); - Type retType = mGen.getReturnType(); - - InstructionList mainIL = new InstructionList(); - MethodGen mainMGen = new MethodGen(m.getAccessFlags() | cst.ACC_STATIC, - retType, - argTypes, mGen.getArgumentNames(), - mGen.getName(), - mainClassName, - mainIL, - mainPool); - int moduleFieldIndex = - mainPool.addFieldref(moduleName, - MODULE_INSTANCE_FIELD_NAME, - (new ObjectType(moduleName)).getSignature()); - int mIndex = mainPool.addMethodref(mGen); - - mainIL.append(new GETSTATIC(moduleFieldIndex)); - int pos = 0; - for (int j = 0; j < argTypes.length; ++j) { - mainIL.append(new Generic_LOAD(pos, argTypes[j])); - pos += argTypes[j].getSize(); - } - mainIL.append(new INVOKEVIRTUAL(mIndex)); - mainIL.append(new Generic_RETURN(retType)); - mainMGen.setMaxStack(); - mainClassGen.addMethod(mainMGen.getMethod()); - } - - addScalaAttr(mainClassGen); - JavaClass mainClass = mainClassGen.getJavaClass(); - try { - mainClass.dump(javaFileName(mainClassName)); - } catch (java.io.IOException e) { - throw global.fail(e.getMessage()); - } - } - - - protected void addScalaAttr(ClassGen classGen) { - ConstantPoolGen poolGen = classGen.getConstantPool(); - - int scalaNameIndex = - poolGen.addUtf8(ClassfileConstants.SCALA_N.toString()); - Unknown scalaAttr = new Unknown(scalaNameIndex, - 0, - null, - poolGen.getConstantPool()); - - classGen.addAttribute(scalaAttr); - } - - // Context manipulation - - protected LinkedList/*<ClassGen>*/ classStack = new LinkedList(); - - protected void enterClass(Symbol cSym) { - String javaName = javaName(cSym); - - scalac.symtab.Type[] baseTps = cSym.info().parents(); - assert baseTps.length > 0 : Debug.show(cSym); - - int offset; - String superClassName; - if (cSym.isInterface()) { - offset = baseTps[0].isSameAs(defs.ANY_TYPE) ? 1 : 0; - superClassName = JAVA_LANG_OBJECT; - } else { - offset = 1; - superClassName = javaName(baseTps[0].symbol()); - } - String[] interfaceNames = new String[baseTps.length - offset]; - for (int i = offset; i < baseTps.length; ++i) { - Symbol baseSym = baseTps[i].symbol(); - assert baseSym.isInterface() : cSym + " implements " + baseSym; - interfaceNames[i - offset] = javaName(baseSym); - } - - ClassGen cGen = new ClassGen(javaName, - superClassName, - sourceFileName, - modifiersStoJ(cSym.flags) | cst.ACC_SUPER, - interfaceNames); - classStack.addFirst(cGen); - updateClassContext(); - } - - protected HashSet seenClasses = new HashSet(); - protected void leaveClass(Symbol cSym) { - if (isModuleClass) { - if (!seenClasses.contains(cSym.fullName())) - dumpModuleMainClass(currClass); - } else - seenClasses.add(cSym.fullName()); - - addScalaAttr(currClass); - JavaClass cls = currClass.getJavaClass(); - try { - String fileName = javaFileName(cls.getClassName()); - cls.dump(fileName); - global.operation("wrote " + fileName); - } catch (java.io.IOException e) { - throw global.fail(e.getMessage()); - } - classStack.removeFirst(); - updateClassContext(); - } - - protected void updateClassContext() { - if (classStack.isEmpty()) { - currClass = null; - currClassName = null; - currPool = null; - } else { - ClassGen cGen = (ClassGen)classStack.getFirst(); - currClass = cGen; - currClassName = currClass.getClassName(); - currPool = currClass.getConstantPool(); - } - } - - protected void enterMethod(Tree.DefDef dDef) { - Symbol dSym = dDef.symbol(); - - global.log("entering method " + Debug.toString(dSym) - + " (type: " + Debug.toString(dSym.info()) + ")"); - - Map locals; - if (currLocals == null) - locals = new HashMap(); - else - locals = new HashMap(currLocals); - - Tree.ValDef[] args = dDef.vparams[0]; - int argsNum = args.length; - - Type[] argTypes = new Type[argsNum]; - String[] argNames = new String[argsNum]; - for (int i = 0, pos = 1; i < argsNum; ++i) { - argTypes[i] = typeStoJ(args[i].symbol().info()); - argNames[i] = args[i].name.toString(); - locals.put(args[i].symbol(), new Integer(pos)); - pos += argTypes[i].getSize(); - } - - MethodGen mGen = new MethodGen(modifiersStoJ(dDef.mods), - retTypeStoJ(dSym.info()), - argTypes, - argNames, - dDef.name.toString(), - currClassName, - new InstructionList(), - currPool); - - currMethod = mGen; - currLocals = locals; - currIL = currMethod.getInstructionList(); - - lineAttributedInstrs = new HashMap(); - } - - protected void leaveMethod() { - global.log(" leaving method"); - - currMethod.setMaxStack(); - currMethod.removeNOPs(); - currClass.addMethod(currMethod.getMethod()); - - currMethod = null; - currLocals = null; - currIL = null; - - lineAttributedInstrs = null; - } - - protected int modifiersStoJ(int flags) { - int jFlags = 0; - - if (Modifiers.Helper.isPrivate(flags)) - jFlags |= cst.ACC_PRIVATE; - else - jFlags |= cst.ACC_PUBLIC; - - if (Modifiers.Helper.isAbstract(flags)) - jFlags |= cst.ACC_ABSTRACT; - if (Modifiers.Helper.isInterface(flags)) - jFlags |= cst.ACC_INTERFACE; - - if (Modifiers.Helper.isFinal(flags) - && !(Modifiers.Helper.isAbstract(flags) - || Modifiers.Helper.isInterface(flags))) - jFlags |= cst.ACC_FINAL; - - return jFlags; - } - - protected boolean isUnboxedType(scalac.symtab.Type tp) { - switch (tp) { - case UnboxedType(_): - case UnboxedArrayType(_): return true; - default: return false; - } - } - - protected HashMap typeMap/*<Symbol,Type>*/ = new HashMap(); - protected void initTypeMap() { - typeMap.put(defs.ANY_CLASS, Type.OBJECT); - typeMap.put(defs.ANYREF_CLASS, Type.OBJECT); - } - protected Type typeStoJ(scalac.symtab.Type tp) { - switch (tp) { - case UnboxedType(TypeTags.BYTE): - return Type.BYTE; - case UnboxedType(TypeTags.CHAR): - return Type.CHAR; - case UnboxedType(TypeTags.SHORT): - return Type.SHORT; - case UnboxedType(TypeTags.INT): - return Type.INT; - case UnboxedType(TypeTags.LONG): - return Type.LONG; - case UnboxedType(TypeTags.FLOAT): - return Type.FLOAT; - case UnboxedType(TypeTags.DOUBLE): - return Type.DOUBLE; - case UnboxedType(TypeTags.BOOLEAN): - return Type.BOOLEAN; - case UnboxedType(TypeTags.UNIT): - return Type.VOID; - case UnboxedType(TypeTags.STRING): - return Type.STRING; - case UnboxedArrayType(scalac.symtab.Type elementType): - return new ArrayType(typeStoJ(elementType), 1); - default: { - Symbol sym = tp.symbol(); - if (sym == Symbol.NONE) - throw global.fail("invalid type ", tp); - else if (typeMap.containsKey(sym)) - return (Type)typeMap.get(sym); - else { - Type jTp = new ObjectType(javaName(sym)); - typeMap.put(sym, jTp); - return jTp; - } - } - } - } - - protected Type[] argTypesStoJ(scalac.symtab.Type tp) { - switch (tp) { - case MethodType(Symbol[] vparams, _): - Type[] argTypes = new Type[vparams.length]; - for (int i = 0; i < vparams.length; ++i) - argTypes[i] = typeStoJ(vparams[i].info()); - return argTypes; - default: - throw global.fail("invalid method type", tp); - } - } - - protected Type retTypeStoJ(scalac.symtab.Type tp) { - switch (tp) { - case MethodType(_, _): - return typeStoJ(tp.resultType()); - default: - throw global.fail("invalid method type", tp); - } - } - - protected String javaName(Symbol sym) { - assert sym.isClass() : Debug.show(sym); - if (sym == defs.ANY_CLASS || sym == defs.ANYREF_CLASS) - return JAVA_LANG_OBJECT; - else { - StringBuffer buf = new StringBuffer(sym.name.toString()); - if ((sym.isModule() || sym.isModuleClass()) && !sym.isJava()) - buf.append('$'); - for (sym = sym.owner(); !sym.isPackage(); sym = sym.owner()) { - buf.insert(0, '$'); - buf.insert(0, sym.name); - } - if (!sym.isRoot()) { - buf.insert(0, '.'); - buf.insert(0, sym.fullName()); - } - return buf.toString(); - } - } - - protected String javaFileName(String className) { - StringTokenizer tokens = new StringTokenizer(className, "."); - File file = new File(global.outpath); - while (tokens.hasMoreElements()) - file = new File(file, tokens.nextToken()); - - return file.getPath() + ".class"; - } - - // Generic instructions - static class Generic_RETURN implements CompoundInstruction { - private ReturnInstruction inst; - - public Generic_RETURN(Type type) { - switch (type.getType()) { - case cst.T_VOID: inst = ic.RETURN; break; - case cst.T_BOOLEAN: - case cst.T_BYTE: - case cst.T_CHAR: - case cst.T_SHORT: - case cst.T_INT: inst = ic.IRETURN; break; - case cst.T_LONG: inst = ic.LRETURN; break; - case cst.T_FLOAT: inst = ic.FRETURN; break; - case cst.T_DOUBLE: inst = ic.DRETURN; break; - case cst.T_ARRAY: - case cst.T_OBJECT: inst = ic.ARETURN; break; - default: throw Debug.abort("unexpected type " + type.getType()); - } - } - - public InstructionList getInstructionList() { - return new InstructionList(inst); - } - } - - static class Generic_LOAD implements CompoundInstruction { - private LoadInstruction inst; - - public Generic_LOAD(int pos, Type type) { - switch (type.getType()) { - case cst.T_BOOLEAN: - case cst.T_BYTE: - case cst.T_CHAR: - case cst.T_SHORT: - case cst.T_INT: inst = new ILOAD(pos); break; - case cst.T_LONG: inst = new LLOAD(pos); break; - case cst.T_FLOAT: inst = new FLOAD(pos); break; - case cst.T_DOUBLE: inst = new DLOAD(pos); break; - case cst.T_ARRAY: - case cst.T_OBJECT: inst = new ALOAD(pos); break; - default: throw Debug.abort("unexpected type"); - } - } - - public InstructionList getInstructionList() { - return new InstructionList(inst); - } - } - - static class Generic_STORE implements CompoundInstruction { - private StoreInstruction inst; - - public Generic_STORE(int pos, Type type) { - switch (type.getType()) { - case cst.T_BOOLEAN: - case cst.T_BYTE: - case cst.T_CHAR: - case cst.T_SHORT: - case cst.T_INT: inst = new ISTORE(pos); break; - case cst.T_LONG: inst = new LSTORE(pos); break; - case cst.T_FLOAT: inst = new FSTORE(pos); break; - case cst.T_DOUBLE: inst = new DSTORE(pos); break; - case cst.T_ARRAY: - case cst.T_OBJECT: inst = new ASTORE(pos); break; - default: throw Debug.abort("unexpected type", type); - } - } - - public InstructionList getInstructionList() { - return new InstructionList(inst); - } - } - - static class Generic_ALOAD implements CompoundInstruction { - private ArrayInstruction inst; - - public Generic_ALOAD(Type type) { - switch (type.getType()) { - case cst.T_BOOLEAN: - case cst.T_BYTE: inst = ic.BALOAD; break; - case cst.T_CHAR: inst = ic.CALOAD; break; - case cst.T_SHORT: inst = ic.SALOAD; break; - case cst.T_INT: inst = ic.IALOAD; break; - case cst.T_LONG: inst = ic.LALOAD; break; - case cst.T_FLOAT: inst = ic.FALOAD; break; - case cst.T_DOUBLE: inst = ic.DALOAD; break; - case cst.T_ARRAY: - case cst.T_OBJECT: inst = ic.AALOAD; break; - default: throw Debug.abort("unexpected type"); - } - } - - public InstructionList getInstructionList() { - return new InstructionList(inst); - } - } - - static class Generic_ASTORE implements CompoundInstruction { - private ArrayInstruction inst; - - public Generic_ASTORE(Type type) { - switch (type.getType()) { - case cst.T_BOOLEAN: - case cst.T_BYTE: inst = ic.BASTORE; break; - case cst.T_CHAR: inst = ic.CASTORE; break; - case cst.T_SHORT: inst = ic.SASTORE; break; - case cst.T_INT: inst = ic.IASTORE; break; - case cst.T_LONG: inst = ic.LASTORE; break; - case cst.T_FLOAT: inst = ic.FASTORE; break; - case cst.T_DOUBLE: inst = ic.DASTORE; break; - case cst.T_ARRAY: - case cst.T_OBJECT: inst = ic.AASTORE; break; - default: throw Debug.abort("unexpected type"); - } - } - - public InstructionList getInstructionList() { - return new InstructionList(inst); - } - } -} diff --git a/sources/scalac/backend/jvm/GenJVMBCELPhase.java b/sources/scalac/backend/jvm/GenJVMBCELPhase.java deleted file mode 100644 index 3d1b50a77e..0000000000 --- a/sources/scalac/backend/jvm/GenJVMBCELPhase.java +++ /dev/null @@ -1,50 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scalac.backend.jvm; - -import scalac.Global; -import scalac.Phase; -import scalac.PhaseDescriptor; -import scalac.Unit; - - -/** - * Phase to generate Java bytecodes using the BCEL library. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class GenJVMBCELPhase extends Phase { - - //######################################################################## - // Private Fields - - /** The tree to code translator */ - private final GenJVMBCEL translator; - - //######################################################################## - // Public Constructors - - /** Initializes this instance. */ - public GenJVMBCELPhase(Global global, PhaseDescriptor descriptor) { - super(global, descriptor); - this.translator = new GenJVMBCEL(global); - } - - //######################################################################## - // Public Methods - - /** Applies this phase to the given compilation units. */ - public void apply(Unit[] units) { - for (int i = 0; i < units.length; i++) translator.translate(units[i]); - } - - //######################################################################## -} diff --git a/sources/scalac/transformer/AddConstructors.java b/sources/scalac/transformer/AddConstructors.java index 4cb258e230..4fdf9f6221 100644 --- a/sources/scalac/transformer/AddConstructors.java +++ b/sources/scalac/transformer/AddConstructors.java @@ -64,8 +64,7 @@ public class AddConstructors extends Transformer { super(global); this.constructors = constructors; this.forINT = global.target == global.TARGET_INT; - this.forJVM = (global.target == global.TARGET_JVM - || global.target == global.TARGET_JVM_BCEL); + this.forJVM = (global.target == global.TARGET_JVM); } /** return new constructor symbol if it isn't already defined |