diff options
author | Eric Holk <eholk@google.com> | 2018-12-13 11:35:58 -0800 |
---|---|---|
committer | Eric Holk <eholk@google.com> | 2018-12-14 09:14:12 -0800 |
commit | c69449d95c145365d192cf9d347674494bc8fa70 (patch) | |
tree | 2aed52610e6a258fe85c4943b1641d53cf1b2004 /startop/view_compiler/dex_testcase_generator.cc | |
parent | 657d61220648e924b24973c62f984d8654f7bd1f (diff) |
[view-compiler] DexBuilder: Add more instructions
This CL adds the ability to generate code that calls static and virtual methods
which return objects, as well as the not-equal-to-zero comparison operator.
Bug: 111895153
Change-Id: I4ae9b3cb2edc6540671112b73c02bf6380d23051
Diffstat (limited to 'startop/view_compiler/dex_testcase_generator.cc')
-rw-r--r-- | startop/view_compiler/dex_testcase_generator.cc | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc index e2bf43bc1d0c..2781aa55d1df 100644 --- a/startop/view_compiler/dex_testcase_generator.cc +++ b/startop/view_compiler/dex_testcase_generator.cc @@ -108,6 +108,27 @@ void GenerateSimpleTestCases(const string& outdir) { } returnIfZero.Encode(); + // int returnIfNotZero(int x) { if (x != 0) { return 5; } else { return 3; } } + MethodBuilder returnIfNotZero{cbuilder.CreateMethod( + "returnIfNotZero", Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})}; + { + Value resultIfNotZero{returnIfNotZero.MakeRegister()}; + Value else_target{returnIfNotZero.MakeLabel()}; + returnIfNotZero.AddInstruction(Instruction::OpWithArgs( + Instruction::Op::kBranchNEqz, /*dest=*/{}, Value::Parameter(0), else_target)); + // else branch + returnIfNotZero.BuildConst4(resultIfNotZero, 3); + returnIfNotZero.AddInstruction( + Instruction::OpWithArgs(Instruction::Op::kReturn, /*dest=*/{}, resultIfNotZero)); + // then branch + returnIfNotZero.AddInstruction( + Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target)); + returnIfNotZero.BuildConst4(resultIfNotZero, 5); + returnIfNotZero.AddInstruction( + Instruction::OpWithArgs(Instruction::Op::kReturn, /*dest=*/{}, resultIfNotZero)); + } + returnIfNotZero.Encode(); + // Make sure backwards branches work too. // // Pseudo code for test: @@ -216,6 +237,38 @@ void GenerateSimpleTestCases(const string& outdir) { method.Encode(); }(returnStringIfZeroBA); + // Make sure we can invoke static methods that return an object + // String invokeStaticReturnObject(int n, int radix) { return java.lang.Integer.toString(n, + // radix); } + MethodBuilder invokeStaticReturnObject{ + cbuilder.CreateMethod("invokeStaticReturnObject", + Prototype{string_type, TypeDescriptor::Int(), TypeDescriptor::Int()})}; + [&](MethodBuilder& method) { + Value result{method.MakeRegister()}; + MethodDeclData to_string{dex_file.GetOrDeclareMethod( + TypeDescriptor::FromClassname("java.lang.Integer"), + "toString", + Prototype{string_type, TypeDescriptor::Int(), TypeDescriptor::Int()})}; + method.AddInstruction(Instruction::InvokeStaticObject( + to_string.id, result, Value::Parameter(0), Value::Parameter(1))); + method.BuildReturn(result, /*is_object=*/true); + method.Encode(); + }(invokeStaticReturnObject); + + // Make sure we can invoke virtual methods that return an object + // String invokeVirtualReturnObject(String s, int n) { return s.substring(n); } + MethodBuilder invokeVirtualReturnObject{cbuilder.CreateMethod( + "invokeVirtualReturnObject", Prototype{string_type, string_type, TypeDescriptor::Int()})}; + [&](MethodBuilder& method) { + Value result{method.MakeRegister()}; + MethodDeclData substring{dex_file.GetOrDeclareMethod( + string_type, "substring", Prototype{string_type, TypeDescriptor::Int()})}; + method.AddInstruction(Instruction::InvokeVirtualObject( + substring.id, result, Value::Parameter(0), Value::Parameter(1))); + method.BuildReturn(result, /*is_object=*/true); + method.Encode(); + }(invokeVirtualReturnObject); + slicer::MemView image{dex_file.CreateImage()}; std::ofstream out_file(outdir + "/simple.dex"); out_file.write(image.ptr<const char>(), image.size()); |