summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNAME <USER@epfl.ch>2004-03-09 13:46:42 +0000
committerNAME <USER@epfl.ch>2004-03-09 13:46:42 +0000
commitb918f65c2e33075714351124b23d6e032b686af5 (patch)
tree184dbd731f14dda5df7f4e1e8ac7a3aa0660faff
parentd0f5e90b5b99095e5fb5325f0276dc9e5c512145 (diff)
downloadscala-b918f65c2e33075714351124b23d6e032b686af5.tar.gz
scala-b918f65c2e33075714351124b23d6e032b686af5.tar.bz2
scala-b918f65c2e33075714351124b23d6e032b686af5.zip
Some modifications on the intermediate code
-rw-r--r--sources/scala/tools/scalac/backend/GenJVMFromICode.scala75
-rw-r--r--sources/scala/tools/scalac/icode/IBasicBlock.scala53
-rw-r--r--sources/scala/tools/scalac/icode/ICInstruction.scala1
-rw-r--r--sources/scala/tools/scalac/icode/ICode.scala20
-rw-r--r--sources/scala/tools/scalac/icode/ICodePhase.scala13
-rw-r--r--sources/scala/tools/scalac/icode/ICodePrinter.scala1
-rw-r--r--sources/scalac/atree/AShiftOp.java6
-rw-r--r--sources/scalac/atree/ATreeFactory.java2
8 files changed, 125 insertions, 46 deletions
diff --git a/sources/scala/tools/scalac/backend/GenJVMFromICode.scala b/sources/scala/tools/scalac/backend/GenJVMFromICode.scala
index 8c75a732c2..8b45f08bd9 100644
--- a/sources/scala/tools/scalac/backend/GenJVMFromICode.scala
+++ b/sources/scala/tools/scalac/backend/GenJVMFromICode.scala
@@ -255,10 +255,29 @@ class GenJVMFromICode(global: scalac_Global) {
val icode : ICode = jvmMethod.aMethod.icode.asInstanceOf[ICode];
var stack : ICTypeStack = new ICTypeStack();
val jCode = jvmMethod.jCode;
- icode.icTraverse((bb: IBasicBlock) => {
+ icode.icTraverseFeedBack((bb: IBasicBlock, hm: HashMap[IBasicBlock, boolean]) => {
val blockLabel = jvmMethod.labels.apply(bb);
blockLabel.anchorToNext();
bb.bbTraverse((ic : ICInstruction) => stack = emitICInstruction(jvmMethod, stack)(ic));
+
+ bb.getLastInstruction match {
+ case CJUMP(_,failure,_) =>
+ if (hm(failure))
+ jCode.emitGOTO(jvmMethod.labels(failure));
+ case CZJUMP(_,failure,_) =>
+ if (hm(failure))
+ jCode.emitGOTO(jvmMethod.labels(failure));
+ case JUMP(where) =>
+ if (hm(where))
+ jCode.emitGOTO(jvmMethod.labels(where));
+ case _ =>
+ ;
+ }
+
+
+ //if (bb.successors != Nil) // !!! Dont work with switch. TO DO QUICKLY
+// if (hm(bb.successors.head))
+// jCode.emitGOTO(jvmMethod.labels(bb.successors.head));
});
}
@@ -291,9 +310,9 @@ class GenJVMFromICode(global: scalac_Global) {
case CONSTANT(AConstant.NULL) =>
jcode.emitACONST_NULL();
case CONSTANT(AConstant.UNIT) =>
- ; // ??
+ throw(Debug.abort("Illegal constant type: UNIT"));
case CONSTANT(AConstant.ZERO) =>
- ; // ??
+ throw(Debug.abort("Illegal constant type: ZERO"));
case LOAD_ARRAY_ITEM() => {
// depend the type of the elements of the array
@@ -305,7 +324,7 @@ class GenJVMFromICode(global: scalac_Global) {
jcode.emitLOAD(jvmMethod.locals.apply(local));
case LOAD_LOCAL(local, true) =>
- jcode.emitLOAD(jvmMethod.args.apply(local), typeStoJ(local.getType()));
+ jcode.emitLOAD(jvmMethod.args(local), typeStoJ(local.getType()));
case LOAD_FIELD(field, static) => {
val className = javaName(field.owner());
@@ -345,11 +364,31 @@ class GenJVMFromICode(global: scalac_Global) {
case CALL_PRIMITIVE(APrimitive$Negation(ATypeKind.R4)) => jcode.emitFNEG();
case CALL_PRIMITIVE(APrimitive$Negation(ATypeKind.R8)) => jcode.emitDNEG();
- //case CALL_PRIMITIVE(APrimitive$Test(*))
- // !! Regarder les Test
+ case CALL_PRIMITIVE(APrimitive$Test(op, typ, false)) => {
+ // !!! ne traite pas tous les types
- //case CALL_PRIMITIVE(AComparisonOp(*))
- // !! Regarder les comparison
+ val condTag = condAtoJ(op);
+ val thenLabel : JCode$Label = jvmMethod.jCode.newLabel();
+ val contLabel : JCode$Label = jvmMethod.jCode.newLabel();
+
+ typ match {
+ case ATypeKind.REF => jcode.emitIF_ACMP(condTag, thenLabel);
+ case ATypeKind.I4 => jcode.emitIF_ICMP(condTag, thenLabel);
+ case _ => throw(Debug.abort("Unexpected type for the Test primitive.")); // !!!
+ }
+ jcode.emitPUSH(false);
+ jcode.emitGOTO(contLabel);
+ thenLabel.anchorToNext();
+ jcode.emitPUSH(true);
+ contLabel.anchorToNext();
+ }
+
+ case CALL_PRIMITIVE(APrimitive$Comparison(AComparisonOp.CMPL, ATypeKind.R4)) => jcode.emitFCMPL();
+ case CALL_PRIMITIVE(APrimitive$Comparison(AComparisonOp.CMPG, ATypeKind.R4)) => jcode.emitFCMPG();
+ case CALL_PRIMITIVE(APrimitive$Comparison(AComparisonOp.CMP, ATypeKind.R4)) => jcode.emitFCMPG(); // Default is 1
+ case CALL_PRIMITIVE(APrimitive$Comparison(AComparisonOp.CMPL, ATypeKind.R8)) => jcode.emitDCMPL();
+ case CALL_PRIMITIVE(APrimitive$Comparison(AComparisonOp.CMPG, ATypeKind.R8)) => jcode.emitDCMPG();
+ case CALL_PRIMITIVE(APrimitive$Comparison(AComparisonOp.CMP, ATypeKind.R8)) => jcode.emitDCMPG(); // Default is 1
case CALL_PRIMITIVE(APrimitive$Arithmetic(AArithmeticOp.ADD, ATypeKind.I4)) => jcode.emitIADD();
case CALL_PRIMITIVE(APrimitive$Arithmetic(AArithmeticOp.ADD, ATypeKind.I8)) => jcode.emitLADD();
@@ -388,8 +427,8 @@ class GenJVMFromICode(global: scalac_Global) {
case CALL_PRIMITIVE(APrimitive$Logical(ALogicalOp.XOR, ATypeKind.BOOL)) => jcode.emitIXOR(); // ??? is that true
case CALL_PRIMITIVE(APrimitive$Logical(ALogicalOp.XOR, ATypeKind.I8)) => jcode.emitLXOR();
- case CALL_PRIMITIVE(APrimitive$Shift(AShiftOp.ASL, ATypeKind.I4)) => jcode.emitISHL();
- case CALL_PRIMITIVE(APrimitive$Shift(AShiftOp.ASL, ATypeKind.I8)) => jcode.emitLSHL();
+ case CALL_PRIMITIVE(APrimitive$Shift(AShiftOp.LSL, ATypeKind.I4)) => jcode.emitISHL();
+ case CALL_PRIMITIVE(APrimitive$Shift(AShiftOp.LSL, ATypeKind.I8)) => jcode.emitLSHL();
case CALL_PRIMITIVE(APrimitive$Shift(AShiftOp.ASR, ATypeKind.I4)) => jcode.emitISHR();
case CALL_PRIMITIVE(APrimitive$Shift(AShiftOp.ASR, ATypeKind.I8)) => jcode.emitLSHR();
@@ -415,8 +454,8 @@ class GenJVMFromICode(global: scalac_Global) {
case CALL_PRIMITIVE(APrimitive$ArrayLength(_)) => jcode.emitARRAYLENGTH();
- case CALL_PRIMITIVE(APrimitive$StringConcat(_,_)) =>
- ; // !!!
+ //case CALL_PRIMITIVE(APrimitive$StringConcat(ATypeKind.REF,ATypeKind.REF)) =>
+ // jcode.emitINVOKEVIRTUAL("String","concat",?);
case CALL_METHOD(method, style) => {
var calledMethod : JMethod = null;
@@ -492,21 +531,21 @@ class GenJVMFromICode(global: scalac_Global) {
keys_l.copyToArray(keys_a,0);
branches_l.copyToArray(branches_a,0);
- jcode.emitSWITCH(keys_a, branches_a, defaultBranch, 15); // Min density = 15 ??? !!!
+ jcode.emitSWITCH(keys_a, branches_a, defaultBranch, 0.65);
}
case JUMP(basicBlock) =>
- jcode.emitGOTO(jvmMethod.labels(basicBlock));
+ ; //jcode.emitGOTO(jvmMethod.labels(basicBlock));
case CJUMP(success, failure, cond) => {
+ // !!! Type cases are missing
val condTag : int = condAtoJ(cond);
val typ = typeStoJ(stack.head);
if (typ.getTag() == JType.T_REFERENCE)
jcode.emitIF_ACMP(condTag, jvmMethod.labels(success));
else if (typ.getTag() == JType.T_INT)
jcode.emitIF_ICMP(condTag, jvmMethod.labels(success));
- // Tres tres bizarre !!! Et les autres cas ???
- jcode.emitGOTO(jvmMethod.labels.apply(failure)); // HA ha ha !
+
}
case CZJUMP(success, failure, cond) => {
@@ -517,8 +556,7 @@ class GenJVMFromICode(global: scalac_Global) {
case RETURN() => {
if (stack.isEmpty)
- //jcode.emitRETURN(); malheureusement ca ne marche pas
- jcode.emitRETURN(JType.VOID); // mais ca oui
+ jcode.emitRETURN(JType.VOID);
else
jcode.emitRETURN(typeStoJ(stack.head));
}
@@ -574,6 +612,7 @@ class GenJVMFromICode(global: scalac_Global) {
case MONITOR_EXIT() => jcode.emitMONITOREXIT();
+ case _ => throw(Debug.abort("Invalid ICInstruction for the JVMBackend", instruction));
}
return stack.eval(instruction);
}
diff --git a/sources/scala/tools/scalac/icode/IBasicBlock.scala b/sources/scala/tools/scalac/icode/IBasicBlock.scala
index 056a415aaf..27e1a897f1 100644
--- a/sources/scala/tools/scalac/icode/IBasicBlock.scala
+++ b/sources/scala/tools/scalac/icode/IBasicBlock.scala
@@ -4,6 +4,7 @@
** /_____/\____/\___/\____/____/ **
\* */
+
// $Id$
import scalac.symtab.Symbol;
@@ -32,11 +33,13 @@ class IBasicBlock (theLabel: int) {
/* The stack at the end of the block */
var endStack : ICTypeStack = null;
+
+
/* The successors of this block */
- var successors : List[IBasicBlock] = Nil;
+ //var successors : List[IBasicBlock] = Nil;
/* Is the block closed*/
- var isClosedBlock : boolean = false;
+ //var isClosedBlock : boolean = false;
//##################################################
// Private fields
@@ -44,6 +47,10 @@ class IBasicBlock (theLabel: int) {
/* ICode instructions */
private var instructions : List[ICInstruction] = Nil;
+ private var lastInstruction : ICInstruction = null;
+
+ private var closed : boolean = false;
+
//##################################################
// Public methods
@@ -51,40 +58,64 @@ class IBasicBlock (theLabel: int) {
override def hashCode() = label;
/* Apply a function to all the instructions of the block*/
- def bbTraverse(f: ICInstruction => unit) = instructions.reverse.foreach(f);
+ def bbTraverse(f: ICInstruction => unit) =
+ instructions.reverse.foreach(f);
+
/* Initialize the stack of the block, must be done before evaluing
* the type stack */
def initStack(stack : ICTypeStack) = {
if (initialStack == null) {
initialStack = stack;
- endStack = stack;
+ endStack = null;
}
}
/* Add a new instruction at the end of the block */
def emit(instr: ICInstruction) = {
- assert (!isClosedBlock, "IBasicBlock closed.");
+ assert (!closed, "IBasicBlock closed.");
instructions = instr::instructions;
+ lastInstruction = instr;
}
/* Compute the type stack of the block */
def typeBlock = {
assert(initialStack != null, "Stack not initialized");
+ endStack = initialStack;
bbTraverse((ic : ICInstruction) => endStack = endStack.eval(ic));
}
/* Add a successor to the block */
- def addSuccessor(s: IBasicBlock) =
- if (!successors.contains(s))
- successors = s::successors;
+ //def addSuccessor(s: IBasicBlock) =
+ // if (!successors.contains(s))
+ // successors = s::successors;
/* Add a list of successors to the block */
- def addSuccessors(ss: List[IBasicBlock]) =
- ss.foreach(addSuccessor);
+ //def addSuccessors(ss: List[IBasicBlock]) =
+ // ss.reverse.foreach(addSuccessor);
/* Close the block */
- def close = isClosedBlock = true;;
+ def close = {
+ //successors; // assertion
+ closed = true;
+ }
+
+ def isClosedBlock = closed;
+
+ def getLastInstruction = lastInstruction;
+
+ def successors : List[IBasicBlock] = // here order will count
+ lastInstruction match {
+ case JUMP (where) => List(where);
+ case CJUMP(success, failure, _) => failure::success::Nil;
+ case CZJUMP(success, failure, _) => failure::success::Nil;
+ case SWITCH(_,labels) => labels;
+ case _ => {
+ assert ((lastInstruction.isInstanceOf[RETURN]), "The last instruction is not a control flow instruction");
+ Nil;
+ }
+ }
+
//##################################################
// Public methods - printing (used for debbuging)
diff --git a/sources/scala/tools/scalac/icode/ICInstruction.scala b/sources/scala/tools/scalac/icode/ICInstruction.scala
index b40ed3e5f4..673c4034b1 100644
--- a/sources/scala/tools/scalac/icode/ICInstruction.scala
+++ b/sources/scala/tools/scalac/icode/ICInstruction.scala
@@ -4,6 +4,7 @@
** /_____/\____/\___/\____/____/ **
\* */
+
// $Id$
diff --git a/sources/scala/tools/scalac/icode/ICode.scala b/sources/scala/tools/scalac/icode/ICode.scala
index e0776aa311..57cb299bc6 100644
--- a/sources/scala/tools/scalac/icode/ICode.scala
+++ b/sources/scala/tools/scalac/icode/ICode.scala
@@ -58,8 +58,10 @@ class ICode(label: String, global: scalac_Global) {
producedStack = ctx.currentBlock.endStack;
}
+ def icTraverse(f: IBasicBlock => unit) = icTraverseFeedBack((bb: IBasicBlock, hm: HashMap[IBasicBlock, boolean]) => f(bb));
+
/* This method applies the given function to all the block */
- def icTraverse(f: IBasicBlock => unit) = {
+ def icTraverseFeedBack(f: (IBasicBlock, HashMap[IBasicBlock, boolean]) => unit) = {
// ?? Define order (actually preorder)
val visited : HashMap[IBasicBlock, boolean] = new HashMap;
visited.incl(blocks.elements.map((x: IBasicBlock) => Pair(x, false)));
@@ -70,7 +72,7 @@ class ICode(label: String, global: scalac_Global) {
blockToVisit match {
case b::xs => {
if (!visited(b)) {
- f(b);
+ f(b, visited);
blockToVisit = b.successors:::xs;
visited += b -> true;
} else
@@ -259,7 +261,7 @@ class ICode(label: String, global: scalac_Global) {
var ctx1 = gen(test, ctx);
ctx1.emit(SWITCH(tags, switchBlocks));
- ctx1.currentBlock.addSuccessors(switchBlocks);
+ //ctx1.currentBlock.addSuccessors(switchBlocks);
switchPairs.foreach((p: Pair[ACode, IBasicBlock]) => {
val code = p._1;
@@ -289,6 +291,7 @@ class ICode(label: String, global: scalac_Global) {
}
case ACode$Label(label, locals, value) => {
+ global.log("Add new label: "+label);
val loopBlock = newBlock;
var ctx1 = ctx.changeBlock(loopBlock);
@@ -406,7 +409,7 @@ class ICode(label: String, global: scalac_Global) {
ctx1 = gen(vargs(1), ctx1);
ctx1.emit(CJUMP(successBlock, failureBlock, op));
}
- ctx1.currentBlock.addSuccessors(successBlock::failureBlock::Nil);
+ //ctx1.currentBlock.addSuccessors(failureBlock::successBlock::Nil);
}
case ACode$Apply(AFunction$Primitive(APrimitive$Negation(_)),_,vargs) =>
@@ -414,9 +417,10 @@ class ICode(label: String, global: scalac_Global) {
// ??? Test with TestOp opposite ?
case _ => {
ctx1 = gen(cond, ctx1);
- ctx1.emit(CONSTANT(AConstant.INT(1)));
- ctx1.emit(CJUMP(successBlock, failureBlock, ATestOp.EQ));
- ctx1.currentBlock.addSuccessors(successBlock::failureBlock::Nil);
+ //ctx1.emit(CONSTANT(AConstant.INT(1)));
+ // We have a boolean value
+ ctx1.emit(CZJUMP(successBlock, failureBlock, ATestOp.NE));
+ //ctx1.currentBlock.addSuccessors(failureBlock::successBlock::Nil);
}
}
ctx1;
@@ -476,7 +480,7 @@ class ICode(label: String, global: scalac_Global) {
if (!currentBlock.isClosedBlock) {
if (nextBlock != null) {
emit(JUMP(nextBlock));
- currentBlock.addSuccessor(nextBlock);
+ //currentBlock.addSuccessor(nextBlock);
}
currentBlock.close;
}
diff --git a/sources/scala/tools/scalac/icode/ICodePhase.scala b/sources/scala/tools/scalac/icode/ICodePhase.scala
index 6fb5716665..847205b38d 100644
--- a/sources/scala/tools/scalac/icode/ICodePhase.scala
+++ b/sources/scala/tools/scalac/icode/ICodePhase.scala
@@ -42,11 +42,12 @@ class ICodePhase(global: scalac_Global, descriptor: PhaseDescriptor) extends sca
// ##################################################
// Private methods
- /** This method translate a single unit, it traverses all methods and
- * generate ICode for each of them */
+ /** This method translates a single unit, it traverses all methods and
+ * generates ICode for each of them */
private def translate(u: scalac_Unit) : unit = {
- val classes_it = new IterableArray(u.repository.classes()).elements;
- classes_it.foreach((c: AClass) => {
+ def genClass(c: AClass) : unit = {
+ val nestedClasses_it = Iterator.fromArray(c.classes());
+ nestedClasses_it.foreach(genClass);
val methods_it = new IterableArray(c.methods()).elements;
methods_it.foreach((m: AMethod) => {
val label : String = m.symbol().name.toString();
@@ -58,7 +59,9 @@ class ICodePhase(global: scalac_Global, descriptor: PhaseDescriptor) extends sca
m.icode = ic;
});
- });
+ }
+ val classes_it = new IterableArray(u.repository.classes()).elements;
+ classes_it.foreach(genClass);
}
}
diff --git a/sources/scala/tools/scalac/icode/ICodePrinter.scala b/sources/scala/tools/scalac/icode/ICodePrinter.scala
index 0c99e041c6..8cf1c9fb01 100644
--- a/sources/scala/tools/scalac/icode/ICodePrinter.scala
+++ b/sources/scala/tools/scalac/icode/ICodePrinter.scala
@@ -4,6 +4,7 @@
** /_____/\____/\___/\____/____/ **
\* */
+
// $Id$
import ch.epfl.lamp.util.CodePrinter;
diff --git a/sources/scalac/atree/AShiftOp.java b/sources/scalac/atree/AShiftOp.java
index fbed80fcde..791ce54328 100644
--- a/sources/scalac/atree/AShiftOp.java
+++ b/sources/scalac/atree/AShiftOp.java
@@ -16,8 +16,8 @@ public class AShiftOp {
//########################################################################
// Public Cases
- /** An arithmetic shift to the left */
- public case ASL;
+ /** A logical shift to the left */
+ public case LSL;
/** An arithmetic shift to the right */
public case ASR;
@@ -31,7 +31,7 @@ public class AShiftOp {
/** Returns a string representation of this operation. */
public String toString() {
switch (this) {
- case ASL: return "ASL";
+ case LSL: return "LSL";
case ASR: return "ASR";
case LSR: return "LSR";
default: throw Debug.abort("unknown case", this);
diff --git a/sources/scalac/atree/ATreeFactory.java b/sources/scalac/atree/ATreeFactory.java
index e28b220340..0c09650a16 100644
--- a/sources/scalac/atree/ATreeFactory.java
+++ b/sources/scalac/atree/ATreeFactory.java
@@ -411,7 +411,7 @@ public class ATreeFactory {
/** Builds a LSL primitive. */
public APrimitive LSL(ATypeKind kind) {
- return APrimitive.Shift(AShiftOp.ASL, kind);
+ return APrimitive.Shift(AShiftOp.LSL, kind);
}
/** Builds a LSR primitive. */