diff options
author | mihaylov <mihaylov@epfl.ch> | 2003-07-24 16:25:59 +0000 |
---|---|---|
committer | mihaylov <mihaylov@epfl.ch> | 2003-07-24 16:25:59 +0000 |
commit | 4fdf2ee3ca88ae22997b7dc279d2143e22e80717 (patch) | |
tree | b04ead32c2521177f776e5172b8a65f53b8ff4e2 /sources | |
parent | 7dc9bd0f1cd2def0850a12a311ad2123ac37878a (diff) | |
download | scala-4fdf2ee3ca88ae22997b7dc279d2143e22e80717.tar.gz scala-4fdf2ee3ca88ae22997b7dc279d2143e22e80717.tar.bz2 scala-4fdf2ee3ca88ae22997b7dc279d2143e22e80717.zip |
- changed to use the Primitives wherever possible
- implemented the proper semantics of == and !=
- many additional bugfixes and adjustments
Diffstat (limited to 'sources')
-rw-r--r-- | sources/scalac/backend/msil/GenMSIL.java | 657 | ||||
-rw-r--r-- | sources/scalac/backend/msil/TypeCreator.java | 36 |
2 files changed, 424 insertions, 269 deletions
diff --git a/sources/scalac/backend/msil/GenMSIL.java b/sources/scalac/backend/msil/GenMSIL.java index cd1ce73774..157440c074 100644 --- a/sources/scalac/backend/msil/GenMSIL.java +++ b/sources/scalac/backend/msil/GenMSIL.java @@ -27,6 +27,7 @@ import scalac.symtab.Modifiers; import scalac.symtab.Definitions; import Scope.SymbolIterator; +import scalac.backend.Primitive; import scalac.backend.Primitives; import ch.epfl.lamp.compiler.msil.*; @@ -70,28 +71,6 @@ public class GenMSIL /*implements Modifiers */ { Symbol currentPackage; - static final HashMap opMap = new HashMap(); - static final HashMap cmpMap = new HashMap(); - { - opMap.put(Names.ADD, OpCodes.Add); - opMap.put(Names.SUB, OpCodes.Sub ); - opMap.put(Names.MUL, OpCodes.Mul); - opMap.put(Names.DIV, OpCodes.Div); - opMap.put(Names.MOD, OpCodes.Rem); - opMap.put(Names.AND, OpCodes.And); - opMap.put(Names.OR, OpCodes.Or); - opMap.put(Names.XOR, OpCodes.Xor); - opMap.put(Names.LSL, OpCodes.Shl); - opMap.put(Names.ASR, OpCodes.Shr); - opMap.put(Names.LSR, OpCodes.Shr_Un); - - cmpMap.put(Names.EQ, new Integer(Test.EQ)); - cmpMap.put(Names.NE, new Integer(Test.NE)); - cmpMap.put(Names.LT, new Integer(Test.LT_IS)); - cmpMap.put(Names.GT, new Integer(Test.GT_IS)); - cmpMap.put(Names.LE, new Integer(Test.LE_IS)); - cmpMap.put(Names.GE, new Integer(Test.GE_IS)); - } static final Item TRUE_ITEM = Item.CondItem(Test.True, null, null); static final Item FALSE_ITEM = Item.CondItem(Test.False, null, null); @@ -121,8 +100,7 @@ public class GenMSIL /*implements Modifiers */ { } - /** Generate .NET assembly - */ + /** Generate .NET assembly */ public ModuleBuilder getPackage(String name, boolean isRealAssembly) { AssemblyBuilder assem = (AssemblyBuilder) assemblies.get(name); if (assem == null) { @@ -179,6 +157,10 @@ public class GenMSIL /*implements Modifiers */ { Iterator iter = assemblies.values().iterator(); while (iter.hasNext()) { AssemblyBuilder assem = (AssemblyBuilder) iter.next(); +// log("Types defined in assembly: " + assem.FullName); +// Type[] types = assem.GetTypes(); +// for (int i = 0; i < types.length; i++) +// log("\t" + types[i]); assem.Save(assem.FullName + ".il"); } } @@ -483,7 +465,7 @@ public class GenMSIL /*implements Modifiers */ { Symbol sym = tree.hasSymbol() ? tree.symbol() : null; switch (tree) { case Empty: - return items.VoidItem();; + return items.VoidItem(); case Block(Tree[] stats): return gen(stats); @@ -535,6 +517,8 @@ public class GenMSIL /*implements Modifiers */ { } } if (!qualifier.hasSymbol()) { +// log("gen2(): " + Debug.show(tree)); +// log("\tqualifier = " + Debug.show(qualifier)); return items.SelectItem(type2MSILType(tree.type), gen(qualifier), tc.getField(sym)); } @@ -564,18 +548,6 @@ public class GenMSIL /*implements Modifiers */ { log("gen.Select: Dunno what to do with: " + dumpSym(sym)); break; -// switch (sym.kind) { -// case Kinds.VAL: -// case Kinds.VAR: -// //log("gen.Select: qualifier " + dumpSym(qualifier.symbol()) + ";;; " + dumpSym(sym)); -// //log("MSILType = " + type2MSILType(sym.type())); -// return items.SelectItem(type2MSILType(sym.type()), -// gen(qualifier, type2MSILType(qualifier.type)), -// tc.getField(sym)); -// default: -// log("gen.Select: Dunno what to do with: " + dumpSym(sym)); -// } -// break; case Apply(Tree fun, Tree[] args): return check(genApply(fun, args, type2MSILType(tree.type))); @@ -615,8 +587,15 @@ public class GenMSIL /*implements Modifiers */ { return items.SelfItem(tc.getType(currentClass)); case Super(Tree tpe): - //logErr("Super not implemented yet"); - return items.VoidItem(); + //logErr("Not implemented yet: Super(" + Debug.show(sym) + ")"); + //log("gen.Super(_): Super.symbol() = " + dumpSym(sym)); + //log("gen.Super(tpe): tpe.symbol() = " + dumpSym(tpe.symbol())); + //log("gen.Super(tpe): tpe = " + Debug.show(tpe)); + //log("gen.Super(tpe): tpe.type() = " + Debug.show(tpe.type())); + //return items.VoidItem(); + Item retItem = items.SelfItem(tc.getType(currentClass)); + //log("gen.Super: generated item: " + retItem); + return retItem; case Literal(Object value): //log("Literal: " + Debug.show(tree)); @@ -626,9 +605,6 @@ public class GenMSIL /*implements Modifiers */ { return items.LiteralItem(t, value); case If(Tree cond, Tree thenp, Tree elsep): - //log("gen.If: cond = " + Debug.show(cond)); - //log(" then = " + Debug.show(thenp)); - //log(" else = " + Debug.show(elsep)); Item item = genIf(cond, thenp, elsep, toType); return check(item); @@ -703,6 +679,8 @@ public class GenMSIL /*implements Modifiers */ { Item coerce(Item item, MSILType toType) { + //log("coerce(): coercing item " + item + " to " + toType); + assert toType != null; if (toType == MSILType.VOID) return drop(item); switch (item) { @@ -752,45 +730,89 @@ public class GenMSIL /*implements Modifiers */ { Item genApply(Tree fun, Tree[] args, MSILType resType) { boolean tmpLastStatement = lastStatement; lastStatement = false; Symbol sym = fun.symbol(); +// if (primitives.isPrimitive(sym)) { +// log("genApply: primitive " + primitives.getPrimitive(sym).tag + +// " = " + dumpSym(sym)); +// } + switch (fun) { case Ident(_): emitThis(); lastStatement = tmpLastStatement; - return check(invokeMethod(sym, args, resType)); + return check(invokeMethod(sym, args, resType, true)); case Select(Tree qualifier, Name selector): -// log("genApply.Select: " + dumpSym(sym)); -// log("\tfun: " + Debug.show(fun)); -// log("\tqualifier: " + Debug.show(qualifier)); -// log("\tqualifier.symbol(): " + Debug.show(qualifier.symbol())); -// log("\tqualifier.type: " + Debug.show(qualifier.type)); -// if (primitives.isPrimitive(sym)) { -// log("genApply: TypeRef: " + primitives.getPrimitiveIndex(sym)); -// log("\t" + dumpSym(sym)); -// } +// log("\tfun: " + Debug.show(fun)); +// log("\tqualifier: " + Debug.show(qualifier)); +// log("\tqualifier.symbol(): " + Debug.show(qualifier.symbol())); +// log("\tqualifier.type: " + Debug.show(qualifier.type)); + + if (sym == primitives.BOX_UVALUE) { + return items.StaticItem(MSILType.REF(SCALA_UNIT), RUNTIME_UNIT_VAL); + } // if (sym == global.primitives.AS_UVALUE) { // return coerce(gen(qualifier, MSILType.VOID), MSILType.VOID); // } - if (sym == global.primitives.BOX_UVALUE) { - return items.StaticItem(MSILType.REF(SCALA_UNIT), RUNTIME_UNIT_VAL); + + if (sym == defs.EQEQ) { + return genEq(qualifier, args[0]); + } + if (sym == defs.BANGEQ) { + return negate(genEq(qualifier, args[0])); } - if (selector == Names.PLUS) { - //if (sym == defs.STRING_PLUS_ANY) { + + if (sym == STRING_CONCAT) { assert args.length == 1; - if (type2MSILType(qualifier.type). - isType(TypeCreator.SYSTEM_STRING) || - type2MSILType(args[0].type). - isType(TypeCreator.SYSTEM_STRING) ) - { - //log("genApply: + -> " + dumpSym(sym)); - Item i1 = load(gen(qualifier)); - Item i2 = load(gen(args[0])); - code.Emit(OpCodes.Call, TypeCreator.CONCAT_OBJECT_OBJECT); - return items.StackItem(MSILType.REF(TypeCreator.SYSTEM_STRING)); + load(gen(qualifier)); + load(gen(args[0])); + code.Emit(OpCodes.Call, TypeCreator.CONCAT_OBJECT_OBJECT); + return items.StackItem(MSILType.STRING_REF); + } + + if (isPrimitiveArrayOp(sym)) { + Primitive prim = primitives.getPrimitive(sym); + loadArgs(args, tc.getMethod(sym).GetParameters()); + Type elemType = getArrayType(prim); + switch (prim) { + 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: + code.Emit(OpCodes.Ldlen); + return items.StackItem(MSILType.I4); + 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 NEW_OARRAY: + code.Emit(OpCodes.Newarr, elemType); + return items.StackItem(MSILType.ARRAY(type2MSILType(elemType))); + + 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: + emitLdelem(MSILArrayElemType(elemType)); + return items.StackItem(MSILType.BOOL); + + 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: + emitStelem(MSILArrayElemType(elemType)); + return items.VoidItem(); } } + + if (isPrimitiveOp(sym)) { + assert args.length <= 1; + Tree right = args.length > 0 ? args[0] : Tree.Empty; + return primitiveOp(qualifier, sym, right, resType); + } + switch (qualifier.type) { case TypeRef(_, _, _): case SingleType(_, _): @@ -801,167 +823,42 @@ public class GenMSIL /*implements Modifiers */ { // log("\tqualifier.symbol(): " + Debug.show(qualifier.symbol())); // log("\tqualifier.type: " + Debug.show(qualifier.type)); - //log("genApply: qualifier " + dumpSym(qualifier.symbol()) + "; selector = " + selector); - switch (qualifier) { - case Apply(Select(Tree qual, Name sel), Tree[] boxArgs): - if (sel == Name.fromString("box")) { - if (args.length == 0) { - if (selector == Names.MINUS) { - Item item = load(gen(boxArgs[0])); - code.Emit(OpCodes.Neg); - return check(item); - } - if (selector == Names.TILDE) { - Item item = load(gen(boxArgs[0])); - code.Emit(OpCodes.Not); - return check(item); - } - if (selector == Names.BANG) { - Item.CondItem cond = mkCond(gen(boxArgs[0])); - //return items.CondItem(cond.test, cond.failure, cond.success); - return items.CondItem(negate(cond.test), - cond.success, cond.failure); - } - } else if (args.length == 1) { - assert sym.name == selector; - return binaryOp(boxArgs[0], sym, args[0], resType); - } - } - break; - } - if (sym == defs.EQEQ) { - load(gen(qualifier)); - load(gen(args[0])); - code.Emit(OpCodes.Callvirt, TypeCreator.OBJECT_EQUALS); - return items.StackItem(MSILType.BOOL); - } - if (sym == defs.BANGEQ) { - log("genApply: != : " + dumpSym(sym)); - Item i1 = load(gen(qualifier)); - Item i2 = load(gen(args[0])); - return items.CondItem(Test.Binary(Test.NE, i2.type), - null, null); - } - if (selector == Names.BANG) { - Item.CondItem cond = mkCond(gen(qualifier)); - // swap the failure and success chains - return items.CondItem(cond.test, cond.failure, cond.success); - } - if (sym == defs.THROW) { - load(gen(qualifier)); - code.Emit(OpCodes.Throw); - code.Emit(OpCode.Ldnull); - //return items.StackItem(MSILType.NULL_REF); - return items.StackItem(MSILType.OBJECT); - } - if (sym == defs.STRING_PLUS_ANY || sym == STRING_CONCAT) { - load(gen(qualifier)); - load(gen(args[0])); - code.Emit(OpCodes.Call, TypeCreator.CONCAT_OBJECT_OBJECT); - return items.StackItem(resType); - } MethodBase method = tc.getMethod(sym); + boolean virtualCall = false; if (!method.IsStatic || becomesStatic(sym)) { - load(gen(qualifier)); - } - lastStatement = tmpLastStatement; - return check(invokeMethod(sym, args, resType)); - - case UnboxedArrayType(_): - if (primitives.isPrimitive(sym)) { - log("genApply: " + primitives.getPrimitive(sym)); - } else { - log("genApply: Array stuff is not primitive!"); - } - // handle array.length - if (selector == Names.length) { - assert args.length == 0; - load(gen(qualifier)); - code.Emit(OpCodes.Ldlen); - return items.StackItem(MSILType.I4); - } - // handle array indexing - else if (selector == Names.apply) { - assert args.length == 1; - Item i = load(gen(qualifier)); - MSILType elemtype = ((MSILType.ARRAY) i.type).t; - load(gen(args[0])); - switch (elemtype) { - case I1: code.Emit(OpCodes.Ldelem_I1); break; - case I2: code.Emit(OpCodes.Ldelem_I2); break; - case I4: code.Emit(OpCodes.Ldelem_I4); break; - case I8: code.Emit(OpCodes.Ldelem_I8); break; - case R4: code.Emit(OpCodes.Ldelem_R4); break; - case R8: code.Emit(OpCodes.Ldelem_R8); break; - case BOOL: code.Emit(OpCodes.Ldelem_I1); break; - case REF(_): code.Emit(OpCodes.Ldelem_Ref); break; - case ARRAY(_): code.Emit(OpCodes.Ldelem_Ref); break; + //log("genApply.Select: qualifier = " + Debug.show(qualifier)); + //log("genApply.Select: qualifier.type() = " + + //Debug.show(qualifier.type())); + /// FIXME after the Super attribution is correct + switch (qualifier) { + case Super(_): + load(items.SelfItem(tc.getType(currentClass))); + break; default: - throw new ApplicationError(); + load(gen(qualifier)); + virtualCall = true; } - return items.StackItem(elemtype); + //load(gen(qualifier)); } - // hande array update - else if (selector == Names.update) { - assert args.length == 2; - Item i = load(gen(qualifier)); - MSILType elemtype = ((MSILType.ARRAY) i.type).t; - load(gen(args[0])); - load(gen(args[1])); - switch (elemtype) { - case I1: code.Emit(OpCodes.Stelem_I1); break; - case I2: code.Emit(OpCodes.Stelem_I2); break; - case I4: code.Emit(OpCodes.Stelem_I4); break; - case I8: code.Emit(OpCodes.Stelem_I8); break; - case R4: code.Emit(OpCodes.Stelem_R4); break; - case R8: code.Emit(OpCodes.Stelem_R8); break; - case BOOL: code.Emit(OpCodes.Stelem_I1); break; - case REF(_): code.Emit(OpCodes.Stelem_Ref); break; - case ARRAY(_): code.Emit(OpCodes.Stelem_Ref); break; - default: - throw new ApplicationError(); - } - return items.VoidItem(); - } - throw new ApplicationError("Applying selector '" + selector + - "' to qualifier " + - dumpSym(qualifier.symbol())); + lastStatement = tmpLastStatement; + return check(invokeMethod(sym, args, resType, virtualCall)); default: throw new ApplicationError(); } // switch(qualifier.type) -// case TypeApply(Select(Tree qualifier,_), Tree[] targs): case TypeApply(Tree tfun, Tree[] targs): final Symbol tsym = tfun.symbol(); - switch (tfun) { - case Select(Tree qualifier, _): - Item i = load(gen(qualifier)); - final Type type = tc.getTypeFromType(targs[0].type); - if (tsym == defs.IS) { - code.Emit(OpCodes.Isinst, type); - return mkCond(items.StackItem(MSILType.REF(type))); - } - if (tsym == defs.AS) { - if (!i.type.isType(type) && type != TypeCreator.SYSTEM_OBJECT) { - //log("genApply: casting item: " + i + " to type: " + type); - code.Emit(OpCodes.Castclass, type); - } - return items.StackItem(MSILType.REF(type)); - } - - log("genApply.TypeApply.Select: Dunno how to process TypeApply: " - + Debug.show(fun)); - log("\tTypeApply.fun: " + Debug.show(tfun)); - log("\tTypeApply.fun.symbol(): " + tsym); - throw new ApplicationError(); - default: - log("default: genApply.TypeApply: Dunno how to process TypeApply: " - + Debug.show(fun)); - log("\tTypeApply.fun: " + Debug.show(tfun)); - log("\tTypeApply.fun.symbol(): " + tsym); - throw new ApplicationError(); + if (primitives.isPrimitive(tsym)) { +// log("genApply.TypeApply: primitive " + primitives.getPrimitive(tsym).tag + +// " = " + dumpSym(tsym)); + return primitiveOp(((Select)tfun).qualifier, tsym, targs[0], resType); } + log("genApply.TypeApply.Select: Dunno how to process TypeApply: " + + Debug.show(fun)); + log("\tTypeApply.fun: " + Debug.show(tfun)); + log("\tTypeApply.fun.symbol(): " + tsym); + throw new ApplicationError(); default: throw new ApplicationError @@ -970,6 +867,31 @@ public class GenMSIL /*implements Modifiers */ { } //genApply() + /** Generate code for scala's '==' */ + Item genEq(Tree left, Tree right) { + LocalBuilder tmpLocal = (LocalBuilder)locals.get(defs.EQEQ); + if (tmpLocal == null) { + tmpLocal = code.DeclareLocal(TypeCreator.SYSTEM_OBJECT); + locals.put(defs.EQEQ, tmpLocal); + } + Label l1 = code.DefineLabel(), l2 = code.DefineLabel(); + load(gen(left)); + load(gen(right)); + code.Emit(OpCodes.Stloc, tmpLocal); + code.Emit(OpCodes.Dup); + code.Emit(OpCodes.Ldnull); + code.Emit(OpCodes.Bne_Un, l1); + code.Emit(OpCodes.Ldloc, tmpLocal); + code.Emit(OpCodes.Ceq); + code.Emit(OpCodes.Br, l2); + code.MarkLabel(l1); + code.Emit(OpCodes.Ldloc, tmpLocal); + code.Emit(OpCodes.Callvirt, TypeCreator.OBJECT_EQUALS); + code.MarkLabel(l2); + return items.StackItem(MSILType.BOOL); + } + + MSILType arithmCoercion(MSILType t1, MSILType t2) { if (t1 == t2) return t1; int i, j, n = MSILType.ARITHM_PRECISION.length; @@ -980,54 +902,138 @@ public class GenMSIL /*implements Modifiers */ { if (t2 == MSILType.ARITHM_PRECISION[j]) break; if (i >= n || j >= n) - log("arithmCoercion: cannot find coercion for (" + t1 + ", " + t2 + ")"); + log("arithmCoercion(): cannot find coercion for (" + + t1 + ", " + t2 + ")"); else return MSILType.ARITHM_PRECISION[Math.max(i, j)]; return null; } + public boolean isPrimitiveOp(Symbol sym) { + switch (primitives.getPrimitive(sym)) { + case POS: case NEG: case NOT: + case ADD: case SUB: case MUL: case DIV: case MOD: + case OR: case XOR: case AND: + case LSL: case LSR: case ASR: + case EQ: case NE: case LT: case LE: case GT: case GE: + case ZNOT: case ZOR: case ZAND: + case IS: case AS: + case CONCAT: + case THROW: + return true; + default: + return false; + } + } + + public boolean isPrimitiveArrayOp(Symbol sym) { + switch (primitives.getPrimitive(sym)) { + 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 NEW_OARRAY: + 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 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: + return true; + default: + return false; + } + } + + //------------------------------------------------------------------------ + public Item primitiveOp(Tree left, Symbol opSym, Tree right, + MSILType resType) + { + assert primitives.isPrimitive(opSym); + Primitive op = primitives.getPrimitive(opSym); +// log("primaryOp(): primitive index = " + op.tag); +// log("\t" + dumpSym(opSym)); + + // treat some special cases + switch (op) { + case BOX: + return invokeMethod(opSym, new Tree[]{right}, resType, false); + + case CONCAT: +// log("primaryOp().CONCAT: string concat!"); + load(gen(left)); + load(gen(right)); + code.Emit(OpCodes.Call, TypeCreator.CONCAT_OBJECT_OBJECT); + return items.StackItem(MSILType.STRING_REF); + + case ADD: + if (tc.getTypeFromType(right.type) == TypeCreator.SYSTEM_STRING) { + log("primaryOp().ADD: string concat!"); + load(gen(left)); + load(gen(right)); + code.Emit(OpCodes.Call, TypeCreator.CONCAT_OBJECT_OBJECT); + return items.StackItem(MSILType.STRING_REF); + } + break; + + case IS: +// log("primitiveOp(): Any.is"); + load(gen(left)); + final Type type = tc.getTypeFromType(right.type); + code.Emit(OpCodes.Isinst, type); + return mkCond(items.StackItem(MSILType.REF(type))); + + case AS: +// log("primitiveOp(): Any.as"); + Item i = load(gen(left)); + final Type type = tc.getTypeFromType(right.type); + if (!i.type.isType(type) && type != TypeCreator.SYSTEM_OBJECT) { + //log("genApply: casting item: " + i + " to type: " + type); + code.Emit(OpCodes.Castclass, type); + } + return items.StackItem(MSILType.REF(type)); + } - /** generate code for binary operators - */ - public Item binaryOp(Tree left, Symbol opSym, Tree right, MSILType resType) { - Name op = opSym.name; Item iLeft = null; -// if (global.primitives.isPrimitive(opSym)) { -// log("binaryOP: prmitive -> " + dumpSym(opSym)); -// log("\tleft = " + Debug.show(left)); -// log("\tright = " + Debug.show(right)); -// } + switch (left) { - case Apply(Select(Tree qualifier, Name selector), Tree[] args): - if (selector == Name.fromString("box")) { - log("binaryOp(): qualifier = " + dumpSym(qualifier.symbol())); + case Apply(Tree fun , Tree[] args): + Primitive p = primitives.getPrimitive(fun.symbol()); + //log("primitiveOp: primitive.tag = " + p.tag); + switch (p) { + case BOX: assert args.length == 1; iLeft = gen(args[0]); + break; + default: + iLeft = gen(left); } - else iLeft = gen(left, resType); break; default: - iLeft = gen(left, resType); + iLeft = gen(left); } - OpCode opcode = (OpCode) opMap.get(op); - if (opcode != null) { - //log("binaryOp: arithm" + type2MSILType(left.type) + " " + op + " " + type2MSILType(right.type) + " -> " + resType); - load(coerce(iLeft, resType)); - load(coerce(gen(right, resType), resType)); - code.Emit(opcode); - return items.StackItem(resType); - } - Integer test = (Integer) cmpMap.get(op); - if (test != null) { - resType = arithmCoercion(type2MSILType(left.type), - type2MSILType(right.type)); - //log("binaryOp: test: " + type2MSILType(left.type) + " " + op + " " + type2MSILType(right.type) + " -> " + resType); - - load(coerce(iLeft, resType)); - load(coerce(gen(right, resType), resType)); - return items.CondItem(Test.Binary(test.intValue(), resType), null, null); - } - if (opSym == defs.BARBAR()) { + + switch (op) { + case THROW: + //log("primitiveOp().THROW: " + Debug.show(left)); + load(iLeft); + code.Emit(OpCodes.Throw); + code.Emit(OpCodes.Ldnull); + return items.StackItem(MSILType.NULL_REF); + + case POS: return load(coerce(iLeft, resType)); + case NEG: + iLeft = load(coerce(iLeft, resType)); + code.Emit(OpCodes.Neg); + return iLeft; + case NOT: + iLeft = load(coerce(iLeft, resType)); + code.Emit(OpCodes.Not); + return iLeft; + case ZNOT: + return negate(mkCond(iLeft)); + case ZOR: Item.CondItem lcond = mkCond(iLeft), rcond = null; Chain success = lcond.success, failure = lcond.failure; switch (lcond.test) { @@ -1052,8 +1058,7 @@ public class GenMSIL /*implements Modifiers */ { merge(success, rcond.success), merge(failure, rcond.failure)); return rcond; - } - if (opSym == defs.AMPAMP()) { + case ZAND: Item.CondItem lcond = mkCond(iLeft), rcond = null; Chain success = lcond.success, failure = lcond.failure; switch (lcond.test) { @@ -1079,8 +1084,37 @@ public class GenMSIL /*implements Modifiers */ { merge(failure, rcond.failure)); return rcond; } - throw new ApplicationError("Unknown binary op: " + op); - } // binaryOp() + MSILType toType = arithmCoercion(primitiveType(left.type), + primitiveType(right.type)); + load(coerce(iLeft, toType)); + load(coerce(gen(right, toType), toType)); + switch (op) { + case ADD: code.Emit(OpCodes.Add); return items.StackItem(resType); + case SUB: code.Emit(OpCodes.Sub); return items.StackItem(resType); + case MUL: code.Emit(OpCodes.Mul); return items.StackItem(resType); + case DIV: code.Emit(OpCodes.Div); return items.StackItem(resType); + case MOD: code.Emit(OpCodes.Rem); return items.StackItem(resType); + + case OR: code.Emit(OpCodes.Or); return items.StackItem(resType); + case XOR: code.Emit(OpCodes.Xor); return items.StackItem(resType); + case AND: code.Emit(OpCodes.And); return items.StackItem(resType); + + case LSL: code.Emit(OpCodes.Shl); return items.StackItem(resType); + case LSR: code.Emit(OpCodes.Shr); return items.StackItem(resType); + case ASR: code.Emit(OpCodes.Shr_Un); return items.StackItem(resType); + + case EQ: return items.CondItem(Test.Binary(Test.EQ, toType), null, null); + case NE: return items.CondItem(Test.Binary(Test.NE, toType), null, null); + case LT: return items.CondItem(Test.Binary(Test.LT_IS, toType), null, null); + case LE: return items.CondItem(Test.Binary(Test.LE_IS, toType), null, null); + case GT: return items.CondItem(Test.Binary(Test.GT_IS, toType), null, null); + case GE: return items.CondItem(Test.Binary(Test.GE_IS, toType), null, null); + + } + + log("primitiveOp(): dunno what to do with primitive: " + op.tag); + return items.StackItem(resType); + } void loadArgs(Tree[] args, ParameterInfo[] params) { @@ -1110,7 +1144,8 @@ public class GenMSIL /*implements Modifiers */ { /** Generate code for method invocation */ - Item invokeMethod(Symbol fun, Tree[] args, MSILType resType) { + Item invokeMethod(Symbol fun, Tree[] args, MSILType resType, + boolean virtualCall) { //log("invokeMethod: " + dumpSym(fun)); MethodBase method = tc.getMethod(fun); assert method != null : "Coudn't resolve method: " + dumpSym(fun); @@ -1131,7 +1166,7 @@ public class GenMSIL /*implements Modifiers */ { items.StackItem(resType); } else if (method.IsConstructor) { // used only for calls to super constructor - emitThis(); + //emitThis(); loadArgs(args, method.GetParameters()); code.Emit(OpCodes.Call, (ConstructorInfo)method); res = items.VoidItem(); @@ -1139,7 +1174,8 @@ public class GenMSIL /*implements Modifiers */ { loadArgs(args, method.GetParameters()); if (enableTailCalls && lastStatement && method == currentMethod) code.Emit(OpCodes.Tailcall); - code.Emit(OpCodes.Callvirt, (MethodInfo)method); + code.Emit(virtualCall ? OpCodes.Callvirt : OpCodes.Call, + (MethodInfo)method); res = returnsVoid(method) ? items.VoidItem() : items.StackItem(resType); } return check(res); @@ -1152,10 +1188,13 @@ public class GenMSIL /*implements Modifiers */ { case TypeRef(_, Symbol s, _): //log("TypeRef: " + dumpSym(s)); return MSILType.REF(tc.getType(s)); + case ThisType(Symbol s): + //log("TypeRef: " + dumpSym(s)); + return MSILType.REF(tc.getType(s)); case UnboxedArrayType(scalac.symtab.Type t): return MSILType.ARRAY(type2MSILType(t)); default: - log("type2MSILType: don't know how to convert type " + type); + log("type2MSILType: don't know how to convert type " + Debug.show(type)); //return MSILType.NULL_REF; return MSILType.OBJECT; //logErr("type2MSILType: " + Debug.show(type)); @@ -1178,7 +1217,87 @@ public class GenMSIL /*implements Modifiers */ { return mtype; } + public MSILType primitiveType(scalac.symtab.Type type) { + MSILType mtype = type2MSILType(type); + switch (mtype) { + case REF(Type t): + if (t == TypeCreator.SCALA_BYTE) return MSILType.I1; + if (t == TypeCreator.SCALA_SHORT) return MSILType.I2; + if (t == TypeCreator.SCALA_INT) return MSILType.I4; + if (t == TypeCreator.SCALA_LONG) return MSILType.I8; + if (t == TypeCreator.SCALA_FLOAT) return MSILType.R4; + if (t == TypeCreator.SCALA_DOUBLE) return MSILType.R8; + if (t == TypeCreator.SCALA_CHAR) return MSILType.CHAR; + if (t == TypeCreator.SCALA_BOOLEAN) return MSILType.BOOL; + return type2MSILType(t); + case ARRAY(_): log("primitiveType: cannot convert " + mtype); return null; + default: return mtype; + } + } + + public MSILType MSILArrayElemType(Type type) { + MSILType mtype = type2MSILType(type); + switch (mtype) { + case BOOL: return MSILType.I1; + case CHAR: return MSILType.I4; + default: return mtype; + } + } + + public Type getArrayType(Primitive p) { + switch (p) { + case NEW_ZARRAY: case ZARRAY_LENGTH: case ZARRAY_GET: case ZARRAY_SET: + return TypeCreator.BOOLEAN; + case NEW_BARRAY: case BARRAY_LENGTH: case BARRAY_GET: case BARRAY_SET: + return TypeCreator.BYTE; + case NEW_SARRAY: case SARRAY_LENGTH: case SARRAY_GET: case SARRAY_SET: + return TypeCreator.SHORT; + case NEW_CARRAY: case CARRAY_LENGTH: case CARRAY_GET: case CARRAY_SET: + return TypeCreator.CHAR; + case NEW_IARRAY: case IARRAY_LENGTH: case IARRAY_GET: case IARRAY_SET: + return TypeCreator.INT; + case NEW_LARRAY: case LARRAY_LENGTH: case LARRAY_GET: case LARRAY_SET: + return TypeCreator.LONG; + case NEW_FARRAY: case FARRAY_LENGTH: case FARRAY_GET: case FARRAY_SET: + return TypeCreator.FLOAT; + case NEW_DARRAY: case DARRAY_LENGTH: case DARRAY_GET: case DARRAY_SET: + return TypeCreator.DOUBLE; + case NEW_OARRAY: case OARRAY_LENGTH: case OARRAY_GET: case OARRAY_SET: + return TypeCreator.SYSTEM_OBJECT; + } + log("getArrayElemType(): unknown primitive " + p.tag); + return null; + } + + public Item emitLdelem(MSILType type) { + switch (type) { + case I1: code.Emit(OpCodes.Ldelem_I1); break; + case I2: code.Emit(OpCodes.Ldelem_I2); break; + case I4: code.Emit(OpCodes.Ldelem_I4); break; + case I8: code.Emit(OpCodes.Ldelem_I8); break; + case R4: code.Emit(OpCodes.Ldelem_R4); break; + case R8: code.Emit(OpCodes.Ldelem_R8); break; + case ARRAY(_): + case REF(_): + code.Emit(OpCodes.Ldelem_Ref); break; + } + return items.StackItem(type); + } + public Item emitStelem(MSILType type) { + switch (type) { + case I1: code.Emit(OpCodes.Stelem_I1); break; + case I2: code.Emit(OpCodes.Stelem_I2); break; + case I4: code.Emit(OpCodes.Stelem_I4); break; + case I8: code.Emit(OpCodes.Stelem_I8); break; + case R4: code.Emit(OpCodes.Stelem_R4); break; + case R8: code.Emit(OpCodes.Stelem_R8); break; + case ARRAY(_): + case REF(_): + code.Emit(OpCodes.Stelem_Ref); break; + } + return items.StackItem(type); + } /** load an item onto the stack */ @@ -1449,6 +1568,12 @@ public class GenMSIL /*implements Modifiers */ { } } + public Item.CondItem negate(Item item) { + Item.CondItem cond = mkCond(item); + // swap the failure and success chains + return items.CondItem(negate(cond.test), cond.success, cond.failure); + } + void negate_load() { code.Emit(OpCodes.Ldc_I4_1); code.Emit(OpCodes.Xor); @@ -1746,7 +1871,7 @@ class Item { public case VoidItem(); public case StackItem(); public case SelfItem(); - public case LiteralItem(MSILType type, Object value); + public case LiteralItem(MSILType typ, Object value); public case ArgItem(int slot); public case LocalItem(LocalBuilder local); public case StaticItem(FieldInfo field); @@ -1755,16 +1880,16 @@ class Item { public String toString() { switch (this) { - case VoidItem(): return "VoidItem"; - case StackItem(): return "StackItem : " + type ; - case SelfItem(): return ""; - case LiteralItem(_, Object value): return "LiteralItem(" + value + ")";; - case ArgItem( int slot): return "ArgItem(" + slot + ")"; - case LocalItem( LocalBuilder local): return "LocalItem(" + local + ")"; - case StaticItem( FieldInfo field): return "StaticItem(" + field + ")"; - case SelectItem(_, FieldInfo field): return "SelectItem(" + field + ")"; + case VoidItem(): return "VoidItem: " + type; + case StackItem(): return "StackItem: " + type ; + case SelfItem(): return "this: " + type; + case LiteralItem(_, Object value): return "LiteralItem(" + value + "): " + type; + case ArgItem( int slot): return "ArgItem(" + slot + "): " + type; + case LocalItem( LocalBuilder local): return "LocalItem(" + local + "): " + type; + case StaticItem( FieldInfo field): return "StaticItem(" + field + "): " + type; + case SelectItem(_, FieldInfo field): return "SelectItem(" + field + "): " +type; case CondItem(Test test, Chain success, Chain failure): - return "CondItem(" + test + ", " + success + ", " + failure + ")"; + return "CondItem(" + test + ", " + success + ", " + failure + "): " + type; } return "??Item??"; } diff --git a/sources/scalac/backend/msil/TypeCreator.java b/sources/scalac/backend/msil/TypeCreator.java index f5b7806174..8d7c4fa1a5 100644 --- a/sources/scalac/backend/msil/TypeCreator.java +++ b/sources/scalac/backend/msil/TypeCreator.java @@ -91,6 +91,15 @@ public final class TypeCreator MONITOR.GetMethod("Wait", new Type[] {SYSTEM_OBJECT, INT}); + static final Type SCALA_BYTE = getJavaType("scala.Byte"); + static final Type SCALA_SHORT = getJavaType("scala.Short"); + static final Type SCALA_INT = getJavaType("scala.Int"); + static final Type SCALA_LONG = getJavaType("scala.Long"); + static final Type SCALA_FLOAT = getJavaType("scala.Float"); + static final Type SCALA_DOUBLE = getJavaType("scala.Double"); + static final Type SCALA_CHAR = getJavaType("scala.Char"); + static final Type SCALA_BOOLEAN = getJavaType("scala.Boolean"); + public static Type getJavaType(String name) { try { return JavaType.fromString(name); } catch (ClassNotFoundException e) { @@ -330,7 +339,9 @@ public final class TypeCreator else { switch (sym.info()) { case CompoundType(_, _): - String fullname = sym.type().symbol().fullNameString(); + String fullname = sym.type().symbol().fullNameString() + + (sym.isModuleClass() ? "$" : "");; + type = Type.GetType(fullname); if (type == null) type = createType(sym); @@ -377,9 +388,18 @@ public final class TypeCreator Type[] interfaces = null; int inum = baseTypes.length; if (sym.isInterface()) { +// log("interface " + sym.fullNameString() + +// " extends " + dumpSym(baseTypes[0].symbol())); + int baseIndex = 0; + if (baseTypes[0].symbol() == defs.ANY_CLASS) { + --inum; + baseIndex = 1; + } interfaces = new Type[inum]; - for (int i = 0; i < inum; i++) - interfaces[i] = getType(baseTypes[i].symbol()); + for (int i = 0; i < inum; i++) { + assert baseTypes[i + baseIndex].symbol().isInterface(); + interfaces[i] = getType(baseTypes[i + baseIndex].symbol()); + } } else { superType = getType(baseTypes[0].symbol()); assert inum > 0; @@ -390,10 +410,18 @@ public final class TypeCreator // i.e. top level class if (owner.isRoot() || owner.isPackage()) { +// log("createType():"); +// log("\ttypeName = " + typeName); +// log("\tsuperType = " + superType); +// log("\tinterfaces: "); +// for (int i = 0; i < interfaces.length; i++) +// log("\t\t" + interfaces[i]); type = module.DefineType (typeName, translateTypeAttributes(sym.flags, false), superType, interfaces); } else { + final Type oT = getType(owner); + //log("createType: owner type = " + oT); final TypeBuilder outerType = (TypeBuilder) getType(owner); type = outerType.DefineNestedType (typeName, translateTypeAttributes(sym.flags, true), @@ -431,6 +459,8 @@ public final class TypeCreator // force the creation of the type //log("UnboxedArrayType: " + elemtp + "[]"); return Type.GetType(getTypeFromType(elemtp) + "[]"); + case NoType: + return VOID; default: global.fail("getTypeFromType: " + Debug.show(type)); |