Skip to content

Commit 0e42211

Browse files
committed
Merge branch 'insertAttr' into erasure-annot
2 parents e8320fa + dac2630 commit 0e42211

16 files changed

+1366
-7
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import dotty.tools.dotc.core.Phases.*
2525
import dotty.tools.dotc.core.Decorators.em
2626
import dotty.tools.dotc.report
2727
import dotty.tools.dotc.ast.Trees.SyntheticUnit
28+
import dotty.tools.dotc.transform.InvokeReturnType
29+
import dotty.tools.dotc.transform.InstructionTypeArguments
2830

2931
/*
3032
*
@@ -869,7 +871,11 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
869871
defn.ObjectClass
870872
} else qualSym
871873
}
872-
generatedType = genCallMethod(sym, invokeStyle, app.span, receiverClass)
874+
// println("GenApply.case Apply:" + fun)
875+
// println(s" returnType: ${app.getAttachment(InvokeReturnType)} InstructionTypeArg: ${fun.getAttachment(InstructionTypeArguments)}")
876+
// InvokeReturnType, InstructionTypeArguments are fetched here
877+
generatedType = genCallMethod(sym, invokeStyle, app.span, receiverClass,
878+
app.getAttachment(InvokeReturnType), fun.getAttachment(InstructionTypeArguments))
873879
}
874880
}
875881
}
@@ -1397,7 +1403,8 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
13971403
* invocation instruction, otherwise `method.owner`. A specific receiver class is needed to
13981404
* prevent an IllegalAccessError, (aladdin bug 455).
13991405
*/
1400-
def genCallMethod(method: Symbol, style: InvokeStyle, pos: Span = NoSpan, specificReceiver: Symbol = null): BType = {
1406+
def genCallMethod(method: Symbol, style: InvokeStyle, pos: Span = NoSpan, specificReceiver: Symbol = null,
1407+
invokeReturnType : Option[dotty.tools.dotc.transform.TypeB] = None, instrTypeArgs : Option[List[dotty.tools.dotc.transform.TypeA]] = None): BType = {
14011408
val methodOwner = method.owner
14021409

14031410
// the class used in the invocation's method descriptor in the classfile
@@ -1450,16 +1457,20 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14501457
val staticDesc = MethodBType(ownerBType :: bmType.argumentTypes, bmType.returnType).descriptor
14511458
val staticName = traitSuperAccessorName(method)
14521459
bc.invokestatic(receiverName, staticName, staticDesc, isInterface)
1460+
// bc.invokestatic(receiverName, staticName, staticDesc, isInterface, invokeReturnType, instrTypeArgs)
14531461
} else {
14541462
bc.invokespecial(receiverName, jname, mdescr, isInterface)
1463+
// bc.invokespecial(receiverName, jname, mdescr, isInterface, invokeReturnType, instrTypeArgs)
14551464
}
14561465
} else {
14571466
val opc = style match {
14581467
case Static => Opcodes.INVOKESTATIC
14591468
case Special => Opcodes.INVOKESPECIAL
14601469
case Virtual => if (isInterface) Opcodes.INVOKEINTERFACE else Opcodes.INVOKEVIRTUAL
14611470
}
1462-
bc.emitInvoke(opc, receiverName, jname, mdescr, isInterface)
1471+
// println("genCallMethod" + method.show + " : " + method.getAnnotation(defn.ErasurePreservationAnnot))
1472+
bc.emitInvoke(opc, receiverName, jname, mdescr, isInterface, invokeReturnType, instrTypeArgs)
1473+
// bc.emitInvoke(opc, receiverName, jname, mdescr, isInterface, invokeReturnType, instrTypeArgs)
14631474
}
14641475

14651476
bmType.returnType

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import scala.tools.asm.AnnotationVisitor
1010
import scala.tools.asm.ClassWriter
1111
import scala.collection.mutable
1212
import scala.compiletime.uninitialized
13+
import scala.jdk.CollectionConverters.*
1314

1415
import dotty.tools.dotc.CompilationUnit
1516
import dotty.tools.dotc.ast.tpd
@@ -36,6 +37,11 @@ import dotty.tools.dotc.report
3637

3738
import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions
3839

40+
import dotty.tools.backend.jvm.attributes.MethodTypeParameterCount
41+
import dotty.tools.backend.jvm.attributes.MethodReturnType
42+
import dotty.tools.backend.jvm.attributes.MethodParameterType
43+
import dotty.tools.backend.jvm.attributes.TypeHints
44+
3945
/*
4046
* Traits encapsulating functionality to convert Scala AST Trees into ASM ClassNodes.
4147
*
@@ -215,6 +221,38 @@ trait BCodeHelpers extends BCodeIdiomatic {
215221
val av = cw.visitAnnotation(typeDescriptor(typ), isRuntimeVisible(annot))
216222
emitAssocs(av, assocs, BCodeHelpers.this)(this)
217223
}
224+
225+
def toJTypeB(tpe: dotty.tools.dotc.transform.TypeB): TypeHints.TypeB =
226+
tpe match
227+
case dotty.tools.dotc.transform.TypeB.None => TypeHints.TypeB.NO_HINT
228+
case dotty.tools.dotc.transform.TypeB.M(index) => new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
229+
// case _ =>
230+
// report.error("unexpected type in to Java TypeB: " + tpe)
231+
// TypeHints.TypeB.NO_HINT // fallback, should not happen
232+
233+
def addMethodTypeParameterCountAttribute(mw: asm.MethodVisitor, count: Int): Unit =
234+
if (count > 0){
235+
val attr = new MethodTypeParameterCount(count)
236+
mw.visitAttribute(attr)
237+
}
238+
239+
def addMethodReturnTypeAttribute(mw: asm.MethodVisitor, tpe: dotty.tools.dotc.transform.TypeB): Unit =
240+
tpe match
241+
case dotty.tools.dotc.transform.TypeB.M(index) =>
242+
val typeB = new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
243+
val attr = new MethodReturnType(typeB)
244+
mw.visitAttribute(attr)
245+
case dotty.tools.dotc.transform.TypeB.None => //do nothing
246+
// case _ =>
247+
// report.error("Unexpected type for method return type attribute: " + tpe)
248+
249+
250+
def addMethodParameterTypeAttribute(mw: asm.MethodVisitor, lst: List[dotty.tools.dotc.transform.TypeB]) : Unit =
251+
if (lst.isEmpty) return
252+
val lstJTypeB = lst.map(toJTypeB)
253+
val len = lstJTypeB.length
254+
val attr = new MethodParameterType(len, lstJTypeB.asJava)
255+
mw.visitAttribute(attr)
218256

219257
/*
220258
* must-single-thread

compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ package backend
33
package jvm
44

55
import scala.language.unsafeNulls
6+
import scala.jdk.CollectionConverters.*
67

78
import scala.tools.asm
89
import scala.annotation.switch
910
import Primitives.{NE, EQ, TestOp, ArithmeticOp}
1011
import scala.tools.asm.tree.MethodInsnNode
1112
import dotty.tools.dotc.report
13+
import dotty.tools.backend.jvm.attributes.InvokeReturnType
14+
import dotty.tools.backend.jvm.attributes.TypeHints
1215

1316
/*
1417
* A high-level facade to the ASM API for bytecode generation.
@@ -423,9 +426,42 @@ trait BCodeIdiomatic {
423426
emitInvoke(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf = false)
424427
}
425428

426-
def emitInvoke(opcode: Int, owner: String, name: String, desc: String, itf: Boolean): Unit = {
429+
def toJTypeB(tpe: dotty.tools.dotc.transform.TypeB): TypeHints.TypeB =
430+
tpe match
431+
case dotty.tools.dotc.transform.TypeB.None => TypeHints.TypeB.NO_HINT
432+
case dotty.tools.dotc.transform.TypeB.M(index) => new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
433+
434+
def toJTypeA(tpe: dotty.tools.dotc.transform.TypeA): TypeHints.TypeA =
435+
tpe match
436+
case dotty.tools.dotc.transform.TypeA.Byte => TypeHints.TypeA.TYPEA_BYTE
437+
case dotty.tools.dotc.transform.TypeA.Char => TypeHints.TypeA.TYPEA_CHAR
438+
case dotty.tools.dotc.transform.TypeA.Double => TypeHints.TypeA.TYPEA_DOUBLE
439+
case dotty.tools.dotc.transform.TypeA.Float => TypeHints.TypeA.TYPEA_FLOAT
440+
case dotty.tools.dotc.transform.TypeA.Int => TypeHints.TypeA.TYPEA_INT
441+
case dotty.tools.dotc.transform.TypeA.Long => TypeHints.TypeA.TYPEA_LONG
442+
case dotty.tools.dotc.transform.TypeA.Short => TypeHints.TypeA.TYPEA_SHORT
443+
case dotty.tools.dotc.transform.TypeA.Boolean => TypeHints.TypeA.TYPEA_BOOLEAN
444+
case dotty.tools.dotc.transform.TypeA.M(x) => TypeHints.TypeA(TypeHints.TypeA.M_KIND, x)
445+
case dotty.tools.dotc.transform.TypeA.K(x) => TypeHints.TypeA(TypeHints.TypeA.K_KIND, x)
446+
case dotty.tools.dotc.transform.TypeA.Ref => TypeHints.TypeA.TYPEA_REFERENCE
447+
448+
449+
def emitInvoke(opcode: Int, owner: String, name: String, desc: String, itf: Boolean,
450+
invokeReturnType : Option[dotty.tools.dotc.transform.TypeB] = None, instrTypeArgs : Option[List[dotty.tools.dotc.transform.TypeA]] = None): Unit = {
427451
val node = new MethodInsnNode(opcode, owner, name, desc, itf)
428452
jmethod.instructions.add(node)
453+
invokeReturnType match {
454+
case None => {}
455+
case Some(typeB) =>
456+
val bcTypeB = toJTypeB(typeB)
457+
jmethod.asInstanceOf[MethodNode1].invokeReturnTypeBs.put(node, bcTypeB);
458+
}
459+
instrTypeArgs match {
460+
case None => {}
461+
case Some(lstTypeAs) =>
462+
val bcTypeAs = lstTypeAs.map(toJTypeA)
463+
jmethod.asInstanceOf[MethodNode1].instructionTypeArgTypeAs.put(node, bcTypeAs.asJava);
464+
}
429465
}
430466

431467

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import dotty.tools.dotc.core.Types.*
2020
import dotty.tools.dotc.core.Contexts.*
2121
import dotty.tools.dotc.util.Spans.*
2222
import dotty.tools.dotc.report
23+
import dotty.tools.dotc.transform.ErasedInfo
2324

2425

2526
/*
@@ -717,6 +718,16 @@ trait BCodeSkelBuilder extends BCodeHelpers {
717718
val (excs, others) = methSymbol.annotations.partition(_.symbol eq defn.ThrowsAnnot)
718719
val thrownExceptions: List[String] = getExceptions(excs)
719720

721+
// information for: MethodTypeParameterCount, MethodParameterType, MethodReturnType
722+
val methodDeclarationAttrs = methSymbol.getAnnotation(defn.ErasurePreservationAnnot)
723+
val (cnt, paramType, retType) = methodDeclarationAttrs match {
724+
case Some(e : ErasedInfo) => (e.paramCount, e.paramType, e.returnType)
725+
case _ => (0, List.empty[dotty.tools.dotc.transform.TypeB], dotty.tools.dotc.transform.TypeB.None)
726+
}
727+
//val typeBs =
728+
// println(s"GenBCode.genDefDef.initJMethod: ${methSymbol.show} ${methodDeclarationAttrs} " +
729+
// s"${cnt} ${paramType} ${retType}")
730+
720731
val bytecodeName =
721732
if (isMethSymStaticCtor) CLASS_CONSTRUCTOR_NAME
722733
else jMethodName
@@ -731,7 +742,9 @@ trait BCodeSkelBuilder extends BCodeHelpers {
731742
).asInstanceOf[MethodNode1]
732743

733744
// TODO param names: (m.params map (p => javaName(p.sym)))
734-
745+
addMethodTypeParameterCountAttribute(mnode, cnt)
746+
addMethodParameterTypeAttribute(mnode, paramType)
747+
addMethodReturnTypeAttribute(mnode, retType)
735748
emitAnnotations(mnode, others)
736749
emitParamNames(mnode, params)
737750
emitParamAnnotations(mnode, params.map(_.annotations))
@@ -928,6 +941,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
928941
if (AsmUtils.traceMethodEnabled && mnode.name.contains(AsmUtils.traceMethodPattern))
929942
AsmUtils.traceMethod(mnode)
930943

944+
mnode.setAttribtues();
931945
mnode = null
932946
} // end of method genDefDef()
933947

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package dotty.tools.backend.jvm;
2+
3+
import scala.tools.asm.Opcodes;
4+
5+
final class Constants1 {
6+
static final int F_INSERT = 256;
7+
8+
// The JVM opcode values which are not part of the ASM public API.
9+
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
10+
11+
static final int LDC_W = 19;
12+
static final int LDC2_W = 20;
13+
static final int ILOAD_0 = 26;
14+
static final int ILOAD_1 = 27;
15+
static final int ILOAD_2 = 28;
16+
static final int ILOAD_3 = 29;
17+
static final int LLOAD_0 = 30;
18+
static final int LLOAD_1 = 31;
19+
static final int LLOAD_2 = 32;
20+
static final int LLOAD_3 = 33;
21+
static final int FLOAD_0 = 34;
22+
static final int FLOAD_1 = 35;
23+
static final int FLOAD_2 = 36;
24+
static final int FLOAD_3 = 37;
25+
static final int DLOAD_0 = 38;
26+
static final int DLOAD_1 = 39;
27+
static final int DLOAD_2 = 40;
28+
static final int DLOAD_3 = 41;
29+
static final int ALOAD_0 = 42;
30+
static final int ALOAD_1 = 43;
31+
static final int ALOAD_2 = 44;
32+
static final int ALOAD_3 = 45;
33+
static final int ISTORE_0 = 59;
34+
static final int ISTORE_1 = 60;
35+
static final int ISTORE_2 = 61;
36+
static final int ISTORE_3 = 62;
37+
static final int LSTORE_0 = 63;
38+
static final int LSTORE_1 = 64;
39+
static final int LSTORE_2 = 65;
40+
static final int LSTORE_3 = 66;
41+
static final int FSTORE_0 = 67;
42+
static final int FSTORE_1 = 68;
43+
static final int FSTORE_2 = 69;
44+
static final int FSTORE_3 = 70;
45+
static final int DSTORE_0 = 71;
46+
static final int DSTORE_1 = 72;
47+
static final int DSTORE_2 = 73;
48+
static final int DSTORE_3 = 74;
49+
static final int ASTORE_0 = 75;
50+
static final int ASTORE_1 = 76;
51+
static final int ASTORE_2 = 77;
52+
static final int ASTORE_3 = 78;
53+
static final int WIDE = 196;
54+
static final int GOTO_W = 200;
55+
static final int JSR_W = 201;
56+
57+
// Constants to convert between normal and wide jump instructions.
58+
59+
// The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP.
60+
static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - Opcodes.GOTO;
61+
62+
// Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa.
63+
64+
// The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes
65+
// and IFEQ, ..., IF_ACMPNE, GOTO and JSR.
66+
static final int ASM_OPCODE_DELTA = 49;
67+
68+
// The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL.
69+
static final int ASM_IFNULL_OPCODE_DELTA = 20;
70+
71+
// ASM specific opcodes, used for long forward jump instructions.
72+
73+
static final int ASM_IFEQ = Opcodes.IFEQ + ASM_OPCODE_DELTA;
74+
static final int ASM_IFNE = Opcodes.IFNE + ASM_OPCODE_DELTA;
75+
static final int ASM_IFLT = Opcodes.IFLT + ASM_OPCODE_DELTA;
76+
static final int ASM_IFGE = Opcodes.IFGE + ASM_OPCODE_DELTA;
77+
static final int ASM_IFGT = Opcodes.IFGT + ASM_OPCODE_DELTA;
78+
static final int ASM_IFLE = Opcodes.IFLE + ASM_OPCODE_DELTA;
79+
static final int ASM_IF_ICMPEQ = Opcodes.IF_ICMPEQ + ASM_OPCODE_DELTA;
80+
static final int ASM_IF_ICMPNE = Opcodes.IF_ICMPNE + ASM_OPCODE_DELTA;
81+
static final int ASM_IF_ICMPLT = Opcodes.IF_ICMPLT + ASM_OPCODE_DELTA;
82+
static final int ASM_IF_ICMPGE = Opcodes.IF_ICMPGE + ASM_OPCODE_DELTA;
83+
static final int ASM_IF_ICMPGT = Opcodes.IF_ICMPGT + ASM_OPCODE_DELTA;
84+
static final int ASM_IF_ICMPLE = Opcodes.IF_ICMPLE + ASM_OPCODE_DELTA;
85+
static final int ASM_IF_ACMPEQ = Opcodes.IF_ACMPEQ + ASM_OPCODE_DELTA;
86+
static final int ASM_IF_ACMPNE = Opcodes.IF_ACMPNE + ASM_OPCODE_DELTA;
87+
static final int ASM_GOTO = Opcodes.GOTO + ASM_OPCODE_DELTA;
88+
static final int ASM_JSR = Opcodes.JSR + ASM_OPCODE_DELTA;
89+
static final int ASM_IFNULL = Opcodes.IFNULL + ASM_IFNULL_OPCODE_DELTA;
90+
static final int ASM_IFNONNULL = Opcodes.IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
91+
static final int ASM_GOTO_W = 220;
92+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dotty.tools.backend.jvm;
2+
3+
import scala.tools.asm.tree.AbstractInsnNode;
4+
import scala.tools.asm.util.Textifier;
5+
import scala.tools.asm.MethodVisitor;
6+
import scala.tools.asm.util.TraceMethodVisitor;
7+
8+
import java.io.PrintWriter;
9+
10+
public class InsnPrinter {
11+
public static void printInsn(AbstractInsnNode insn){
12+
Textifier textifier = new Textifier();
13+
MethodVisitor printer = new TraceMethodVisitor(textifier);
14+
insn.accept(printer);
15+
PrintWriter pw = new PrintWriter(System.out);
16+
textifier.print(pw);
17+
pw.flush();
18+
}
19+
}

0 commit comments

Comments
 (0)