1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker public class Main { 18*795d594fSAndroid Build Coastguard Worker assertIntEquals(int expected, int result)19*795d594fSAndroid Build Coastguard Worker public static void assertIntEquals(int expected, int result) { 20*795d594fSAndroid Build Coastguard Worker if (expected != result) { 21*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 22*795d594fSAndroid Build Coastguard Worker } 23*795d594fSAndroid Build Coastguard Worker } 24*795d594fSAndroid Build Coastguard Worker assertStringEquals(String expected, String result)25*795d594fSAndroid Build Coastguard Worker public static void assertStringEquals(String expected, String result) { 26*795d594fSAndroid Build Coastguard Worker if (expected != null ? !expected.equals(result) : result != null) { 27*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 28*795d594fSAndroid Build Coastguard Worker } 29*795d594fSAndroid Build Coastguard Worker } 30*795d594fSAndroid Build Coastguard Worker assertClassEquals(Class<?> expected, Class<?> result)31*795d594fSAndroid Build Coastguard Worker public static void assertClassEquals(Class<?> expected, Class<?> result) { 32*795d594fSAndroid Build Coastguard Worker if (expected != result) { 33*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 34*795d594fSAndroid Build Coastguard Worker } 35*795d594fSAndroid Build Coastguard Worker } 36*795d594fSAndroid Build Coastguard Worker $noinline$foo(int x)37*795d594fSAndroid Build Coastguard Worker private static int $noinline$foo(int x) { 38*795d594fSAndroid Build Coastguard Worker return x; 39*795d594fSAndroid Build Coastguard Worker } 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: int Main.testSimple(int) builder (after) 42*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (before) 45*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after) 48*795d594fSAndroid Build Coastguard Worker /// CHECK: X86ComputeBaseMethodAddress 49*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 50*795d594fSAndroid Build Coastguard Worker testSimple(int x)51*795d594fSAndroid Build Coastguard Worker public static int testSimple(int x) { 52*795d594fSAndroid Build Coastguard Worker // This call should use PC-relative .bss array load to retrieve the target method. 53*795d594fSAndroid Build Coastguard Worker return $noinline$foo(x); 54*795d594fSAndroid Build Coastguard Worker } 55*795d594fSAndroid Build Coastguard Worker 56*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: int Main.testSimpleAppImage(int) builder (after) 57*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:AppImageRelRo 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testSimpleAppImage(int) pc_relative_fixups_x86 (before) 60*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testSimpleAppImage(int) pc_relative_fixups_x86 (after) 63*795d594fSAndroid Build Coastguard Worker /// CHECK: X86ComputeBaseMethodAddress 64*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 65*795d594fSAndroid Build Coastguard Worker testSimpleAppImage(int x)66*795d594fSAndroid Build Coastguard Worker public static int testSimpleAppImage(int x) { 67*795d594fSAndroid Build Coastguard Worker // This call should use PC-relative .data.img.rel.ro array load to retrieve the target method. 68*795d594fSAndroid Build Coastguard Worker return AppImageClass.$noinline$foo(x); 69*795d594fSAndroid Build Coastguard Worker } 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: int Main.testDiamond(boolean, int) builder (after) 72*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 73*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (before) 76*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 77*795d594fSAndroid Build Coastguard Worker 78*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 79*795d594fSAndroid Build Coastguard Worker /// CHECK: X86ComputeBaseMethodAddress 80*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after) 83*795d594fSAndroid Build Coastguard Worker /// CHECK: X86ComputeBaseMethodAddress 84*795d594fSAndroid Build Coastguard Worker /// CHECK-NEXT: If 85*795d594fSAndroid Build Coastguard Worker testDiamond(boolean negate, int x)86*795d594fSAndroid Build Coastguard Worker public static int testDiamond(boolean negate, int x) { 87*795d594fSAndroid Build Coastguard Worker // These calls should use PC-relative loads to retrieve the target method. 88*795d594fSAndroid Build Coastguard Worker // PC-relative bases used by X86 should be pulled before the If. 89*795d594fSAndroid Build Coastguard Worker if (negate) { 90*795d594fSAndroid Build Coastguard Worker return $noinline$foo(-x); 91*795d594fSAndroid Build Coastguard Worker } else { 92*795d594fSAndroid Build Coastguard Worker return $noinline$foo(x); 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker } 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before) 97*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 100*795d594fSAndroid Build Coastguard Worker /// CHECK: X86ComputeBaseMethodAddress 101*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 104*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect 105*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after) 108*795d594fSAndroid Build Coastguard Worker /// CHECK: ArrayLength 109*795d594fSAndroid Build Coastguard Worker /// CHECK-NEXT: X86ComputeBaseMethodAddress 110*795d594fSAndroid Build Coastguard Worker /// CHECK-NEXT: Goto 111*795d594fSAndroid Build Coastguard Worker /// CHECK: begin_block 112*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 113*795d594fSAndroid Build Coastguard Worker testLoop(int[] array, int x)114*795d594fSAndroid Build Coastguard Worker public static int testLoop(int[] array, int x) { 115*795d594fSAndroid Build Coastguard Worker // PC-relative bases used by X86 should be pulled before the loop. 116*795d594fSAndroid Build Coastguard Worker for (int i : array) { 117*795d594fSAndroid Build Coastguard Worker x += $noinline$foo(i); 118*795d594fSAndroid Build Coastguard Worker } 119*795d594fSAndroid Build Coastguard Worker return x; 120*795d594fSAndroid Build Coastguard Worker } 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before) 123*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after) 126*795d594fSAndroid Build Coastguard Worker /// CHECK: If 127*795d594fSAndroid Build Coastguard Worker /// CHECK: begin_block 128*795d594fSAndroid Build Coastguard Worker /// CHECK: ArrayLength 129*795d594fSAndroid Build Coastguard Worker /// CHECK-NEXT: X86ComputeBaseMethodAddress 130*795d594fSAndroid Build Coastguard Worker /// CHECK-NEXT: Goto 131*795d594fSAndroid Build Coastguard Worker testLoopWithDiamond(int[] array, boolean negate, int x)132*795d594fSAndroid Build Coastguard Worker public static int testLoopWithDiamond(int[] array, boolean negate, int x) { 133*795d594fSAndroid Build Coastguard Worker // PC-relative bases used by X86 should be pulled before the loop but not outside the if. 134*795d594fSAndroid Build Coastguard Worker if (array != null) { 135*795d594fSAndroid Build Coastguard Worker for (int i : array) { 136*795d594fSAndroid Build Coastguard Worker if (negate) { 137*795d594fSAndroid Build Coastguard Worker x += $noinline$foo(-i); 138*795d594fSAndroid Build Coastguard Worker } else { 139*795d594fSAndroid Build Coastguard Worker x += $noinline$foo(i); 140*795d594fSAndroid Build Coastguard Worker } 141*795d594fSAndroid Build Coastguard Worker } 142*795d594fSAndroid Build Coastguard Worker } 143*795d594fSAndroid Build Coastguard Worker return x; 144*795d594fSAndroid Build Coastguard Worker } 145*795d594fSAndroid Build Coastguard Worker 146*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$getBootImageString() builder (after) 147*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadString load_kind:BootImageRelRo 148*795d594fSAndroid Build Coastguard Worker $noinline$getBootImageString()149*795d594fSAndroid Build Coastguard Worker public static String $noinline$getBootImageString() { 150*795d594fSAndroid Build Coastguard Worker // Empty string is known to be in the boot image. 151*795d594fSAndroid Build Coastguard Worker return ""; 152*795d594fSAndroid Build Coastguard Worker } 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$getNonBootImageString() builder (after) 155*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadString load_kind:BssEntry 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (before) 158*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (after) 161*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: X86ComputeBaseMethodAddress 162*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadString load_kind:BssEntry 163*795d594fSAndroid Build Coastguard Worker $noinline$getNonBootImageString()164*795d594fSAndroid Build Coastguard Worker public static String $noinline$getNonBootImageString() { 165*795d594fSAndroid Build Coastguard Worker // This string is not in the boot image. 166*795d594fSAndroid Build Coastguard Worker return "non-boot-image-string"; 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.Class Main.$noinline$getStringClass() builder (after) 170*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass load_kind:BootImageRelRo class_name:java.lang.String 171*795d594fSAndroid Build Coastguard Worker $noinline$getStringClass()172*795d594fSAndroid Build Coastguard Worker public static Class<?> $noinline$getStringClass() { 173*795d594fSAndroid Build Coastguard Worker // String class is known to be in the boot image. 174*795d594fSAndroid Build Coastguard Worker return String.class; 175*795d594fSAndroid Build Coastguard Worker } 176*795d594fSAndroid Build Coastguard Worker 177*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.Class Main.$noinline$getOtherClass() builder (after) 178*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass load_kind:BssEntry class_name:Other 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (before) 181*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after) 184*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: X86ComputeBaseMethodAddress 185*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other 186*795d594fSAndroid Build Coastguard Worker $noinline$getOtherClass()187*795d594fSAndroid Build Coastguard Worker public static Class<?> $noinline$getOtherClass() { 188*795d594fSAndroid Build Coastguard Worker // Other class is neither in the boot image nor in the app image. 189*795d594fSAndroid Build Coastguard Worker return Other.class; 190*795d594fSAndroid Build Coastguard Worker } 191*795d594fSAndroid Build Coastguard Worker 192*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.Class Main.$noinline$getAppImageClass() builder (after) 193*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass load_kind:AppImageRelRo class_name:AppImageClass 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.Class Main.$noinline$getAppImageClass() pc_relative_fixups_x86 (before) 196*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 197*795d594fSAndroid Build Coastguard Worker 198*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.Class Main.$noinline$getAppImageClass() pc_relative_fixups_x86 (after) 199*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: X86ComputeBaseMethodAddress 200*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass load_kind:AppImageRelRo class_name:AppImageClass 201*795d594fSAndroid Build Coastguard Worker $noinline$getAppImageClass()202*795d594fSAndroid Build Coastguard Worker public static Class<?> $noinline$getAppImageClass() { 203*795d594fSAndroid Build Coastguard Worker // AppImageClass class is in the app image. 204*795d594fSAndroid Build Coastguard Worker return AppImageClass.class; 205*795d594fSAndroid Build Coastguard Worker } 206*795d594fSAndroid Build Coastguard Worker 207*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$toHexString(int) builder (after) 208*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:BootImageRelRo $noinline$toHexString(int value)209*795d594fSAndroid Build Coastguard Worker public static String $noinline$toHexString(int value) { 210*795d594fSAndroid Build Coastguard Worker return Integer.toString(value, 16); 211*795d594fSAndroid Build Coastguard Worker } 212*795d594fSAndroid Build Coastguard Worker 213*795d594fSAndroid Build Coastguard Worker /// CHECK-START-{ARM,ARM64,X86,X86_64,RISCV64}: java.lang.String Main.$noinline$toHexStringIndirect(int) builder (after) 214*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect method_load_kind:BssEntry 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (before) 217*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: X86ComputeBaseMethodAddress 218*795d594fSAndroid Build Coastguard Worker 219*795d594fSAndroid Build Coastguard Worker /// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (after) 220*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: X86ComputeBaseMethodAddress 221*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect method_load_kind:BssEntry $noinline$toHexStringIndirect(int value)222*795d594fSAndroid Build Coastguard Worker public static String $noinline$toHexStringIndirect(int value) { 223*795d594fSAndroid Build Coastguard Worker return $noinline$toHexString(value); 224*795d594fSAndroid Build Coastguard Worker } 225*795d594fSAndroid Build Coastguard Worker main(String[] args)226*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 227*795d594fSAndroid Build Coastguard Worker assertIntEquals(1, testSimple(1)); 228*795d594fSAndroid Build Coastguard Worker assertIntEquals(1, testSimpleAppImage(1)); 229*795d594fSAndroid Build Coastguard Worker assertIntEquals(1, testDiamond(false, 1)); 230*795d594fSAndroid Build Coastguard Worker assertIntEquals(-1, testDiamond(true, 1)); 231*795d594fSAndroid Build Coastguard Worker assertIntEquals(3, testLoop(new int[]{ 2 }, 1)); 232*795d594fSAndroid Build Coastguard Worker assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1)); 233*795d594fSAndroid Build Coastguard Worker assertIntEquals(1, testLoopWithDiamond(null, false, 1)); 234*795d594fSAndroid Build Coastguard Worker assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1)); 235*795d594fSAndroid Build Coastguard Worker assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1)); 236*795d594fSAndroid Build Coastguard Worker assertStringEquals("", $noinline$getBootImageString()); 237*795d594fSAndroid Build Coastguard Worker assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString()); 238*795d594fSAndroid Build Coastguard Worker assertClassEquals(String.class, $noinline$getStringClass()); 239*795d594fSAndroid Build Coastguard Worker assertClassEquals(Other.class, $noinline$getOtherClass()); 240*795d594fSAndroid Build Coastguard Worker assertStringEquals("12345678", $noinline$toHexString(0x12345678)); 241*795d594fSAndroid Build Coastguard Worker assertStringEquals("76543210", $noinline$toHexStringIndirect(0x76543210)); 242*795d594fSAndroid Build Coastguard Worker } 243*795d594fSAndroid Build Coastguard Worker } 244*795d594fSAndroid Build Coastguard Worker 245*795d594fSAndroid Build Coastguard Worker class AppImageClass { $noinline$foo(int x)246*795d594fSAndroid Build Coastguard Worker public static int $noinline$foo(int x) { 247*795d594fSAndroid Build Coastguard Worker return x; 248*795d594fSAndroid Build Coastguard Worker } 249*795d594fSAndroid Build Coastguard Worker } 250*795d594fSAndroid Build Coastguard Worker 251*795d594fSAndroid Build Coastguard Worker class Other { 252*795d594fSAndroid Build Coastguard Worker } 253*795d594fSAndroid Build Coastguard Worker 254*795d594fSAndroid Build Coastguard Worker class MainExtension extends Main { 255*795d594fSAndroid Build Coastguard Worker } 256