blob: d0ddf00ffa218f2bb83083b8d544076367c0df3a [file] [log] [blame]
// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debuginfo;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class InliningWithoutPositionsTestSourceDump implements Opcodes {
public enum Location {
MAIN(123),
FOO1(234),
BAR(345),
FOO2(456);
final int line;
Location(int line) {
this.line = line;
}
};
/*
This generator creates the class 'InliningWithoutPositionsTestSource' with three methods,
'main', calling 'foo', which is calling 'bar'.
Depending on the mainPos, foo1Pos, barPos and foo2Pos parameters, we insert line numbers in
'main', in 'foo' before calling 'bar' (marked foo1), in 'foo' after calling 'bar' (marked foo2)
and in 'bar'. The methods contain no other line numbers.
The throwLocation parameter determines at which location will be an exception thrown.
The generator code is based on the ASMifier dump of the following class:
package com.android.tools.r8.debuginfo;
public class InliningWithoutPositionsTestSource {
private static void throwingBar() {
throw new RuntimeException("<BAR-exception>");
}
private static void printingBar() {
System.err.println("<in-BAR>");
}
private static void foo(boolean b) {
if (b) throw new RuntimeException("<FOO1-exception>");
throwingBar();
}
private static void foo2() {
throwingBar();
throw new RuntimeException("<FOO2-exception>");
}
public static void main(String[] args) {
foo(true);
}
}
*/
public static byte[] dump(
boolean mainPos, boolean foo1Pos, boolean barPos, boolean foo2Pos, Location throwLocation) {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(
V1_8,
ACC_PUBLIC + ACC_SUPER,
"com/android/tools/r8/debuginfo/InliningWithoutPositionsTestSource",
null,
"java/lang/Object",
null);
cw.visitSource("InliningWithoutPositionsTestSource.java", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable(
"this",
"Lcom/android/tools/r8/debuginfo/InliningWithoutPositionsTestSource;",
null,
l0,
l1,
0);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
if (throwLocation == Location.BAR) {
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC, "bar", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
if (barPos) {
mv.visitLineNumber(Location.BAR.line, l0);
}
mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
mv.visitInsn(DUP);
mv.visitLdcInsn("<BAR-exception>");
mv.visitMethodInsn(
INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V", false);
mv.visitInsn(ATHROW);
mv.visitMaxs(3, 0);
mv.visitEnd();
} else {
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC, "bar", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
if (barPos) {
mv.visitLineNumber(Location.BAR.line, l0);
}
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
mv.visitLdcInsn("<in-BAR>");
mv.visitMethodInsn(
INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 0);
mv.visitEnd();
}
if (throwLocation == Location.FOO2) {
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC, "foo", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
if (foo1Pos) {
mv.visitLineNumber(Location.FOO1.line, l0);
}
mv.visitMethodInsn(
INVOKESTATIC,
"com/android/tools/r8/debuginfo/InliningWithoutPositionsTestSource",
"bar",
"()V",
false);
Label l1 = new Label();
mv.visitLabel(l1);
if (foo2Pos) {
mv.visitLineNumber(Location.FOO2.line, l1);
}
mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
mv.visitInsn(DUP);
mv.visitLdcInsn("<FOO2-exception>");
mv.visitMethodInsn(
INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V", false);
mv.visitInsn(ATHROW);
mv.visitMaxs(3, 0);
mv.visitEnd();
} else {
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC, "foo", "(Z)V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
if (foo1Pos) {
mv.visitLineNumber(Location.FOO1.line, l0);
}
mv.visitVarInsn(ILOAD, 0);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1);
mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
mv.visitInsn(DUP);
mv.visitLdcInsn("<FOO1-exception>");
mv.visitMethodInsn(
INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V", false);
mv.visitInsn(ATHROW);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitMethodInsn(
INVOKESTATIC,
"com/android/tools/r8/debuginfo/InliningWithoutPositionsTestSource",
"bar",
"()V",
false);
Label l2 = new Label();
mv.visitLabel(l2);
if (foo2Pos) {
mv.visitLineNumber(Location.FOO2.line, l2);
}
mv.visitInsn(RETURN);
Label l3 = new Label();
mv.visitLabel(l3);
mv.visitLocalVariable("b", "Z", null, l0, l3, 0);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
if (mainPos) {
mv.visitLineNumber(Location.MAIN.line, l0);
}
if (throwLocation == Location.FOO2) {
mv.visitMethodInsn(
INVOKESTATIC,
"com/android/tools/r8/debuginfo/InliningWithoutPositionsTestSource",
"foo",
"()V",
false);
} else {
mv.visitInsn(throwLocation == Location.FOO1 ? ICONST_1 : ICONST_0);
mv.visitMethodInsn(
INVOKESTATIC,
"com/android/tools/r8/debuginfo/InliningWithoutPositionsTestSource",
"foo",
"(Z)V",
false);
}
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitInsn(RETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l2, 0);
if (throwLocation == Location.FOO2) {
mv.visitMaxs(0, 1);
} else {
mv.visitMaxs(1, 1);
}
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}