| skipped 56 lines |
57 | 57 | | protected final MethodGen mgen; |
58 | 58 | | protected final MethodNode mth; |
59 | 59 | | protected final RootNode root; |
60 | | - | private final boolean fallback; |
| 60 | + | protected final boolean fallback; |
61 | 61 | | |
62 | 62 | | private static enum Flags { |
63 | 63 | | BODY_ONLY, |
64 | 64 | | BODY_ONLY_NOWRAP, |
65 | 65 | | } |
66 | 66 | | |
67 | | - | public InsnGen(MethodGen mgen, MethodNode mth, boolean fallback) { |
| 67 | + | public InsnGen(MethodGen mgen, boolean fallback) { |
68 | 68 | | this.mgen = mgen; |
69 | | - | this.mth = mth; |
| 69 | + | this.mth = mgen.getMethodNode(); |
70 | 70 | | this.root = mth.dex().root(); |
71 | 71 | | this.fallback = fallback; |
72 | 72 | | } |
| skipped 2 lines |
75 | 75 | | return fallback; |
76 | 76 | | } |
77 | 77 | | |
78 | | - | @Deprecated |
79 | | - | public CodeWriter arg(InsnNode insn, int arg) throws CodegenException { |
80 | | - | return arg(insn.getArg(arg)); |
81 | | - | } |
82 | | - | |
83 | | - | @Deprecated |
84 | | - | public CodeWriter arg(InsnArg arg) throws CodegenException { |
85 | | - | return arg(arg, true); |
86 | | - | } |
87 | | - | |
88 | | - | @Deprecated |
89 | | - | public CodeWriter arg(InsnArg arg, boolean wrap) throws CodegenException { |
90 | | - | CodeWriter code = new CodeWriter(); |
91 | | - | addArg(code, arg, wrap); |
92 | | - | return code; |
93 | | - | } |
94 | | - | |
95 | 78 | | public void addArgDot(CodeWriter code, InsnArg arg) throws CodegenException { |
96 | 79 | | int len = code.length(); |
97 | 80 | | addArg(code, arg, true); |
| skipped 30 lines |
128 | 111 | | } |
129 | 112 | | } |
130 | 113 | | |
131 | | - | public String assignVar(InsnNode insn) throws CodegenException { |
| 114 | + | public void assignVar(CodeWriter code, InsnNode insn) throws CodegenException { |
132 | 115 | | RegisterArg arg = insn.getResult(); |
133 | 116 | | if (insn.getAttributes().contains(AttributeFlag.DECLARE_VAR)) { |
134 | | - | return declareVar(arg); |
| 117 | + | declareVar(code, arg); |
135 | 118 | | } else { |
136 | | - | return arg(arg).toString(); |
| 119 | + | addArg(code, arg, false); |
137 | 120 | | } |
138 | 121 | | } |
139 | 122 | | |
140 | | - | public String declareVar(RegisterArg arg) { |
141 | | - | return useType(arg.getType()) + " " + mgen.assignArg(arg); |
| 123 | + | public void declareVar(CodeWriter code, RegisterArg arg) { |
| 124 | + | code.add(useType(arg.getType())); |
| 125 | + | code.add(' '); |
| 126 | + | code.add(mgen.assignArg(arg)); |
142 | 127 | | } |
143 | 128 | | |
144 | 129 | | private static String lit(LiteralArg arg) { |
| skipped 29 lines |
174 | 159 | | return clsGen.useClass(declClass) + '.' + field.getName(); |
175 | 160 | | } |
176 | 161 | | |
177 | | - | private void fieldPut(IndexInsnNode insn) { |
178 | | - | FieldInfo field = (FieldInfo) insn.getIndex(); |
179 | | - | String thisClass = mth.getParentClass().getFullName(); |
180 | | - | if (field.getDeclClass().getFullName().equals(thisClass)) { |
181 | | - | // if we generate this field - don't init if its final and used |
182 | | - | FieldNode fn = mth.getParentClass().searchField(field); |
183 | | - | if (fn != null && fn.getAccessFlags().isFinal()) { |
184 | | - | fn.getAttributes().remove(AttributeType.FIELD_VALUE); |
185 | | - | } |
186 | | - | } |
187 | | - | } |
188 | | - | |
189 | 162 | | protected String staticField(FieldInfo field) { |
190 | 163 | | return makeStaticFieldAccess(field, mgen.getClassGen()); |
191 | 164 | | } |
| skipped 25 lines |
217 | 190 | | code.attachAnnotation(insn.getSourceLine()); |
218 | 191 | | } |
219 | 192 | | if (insn.getResult() != null && insn.getType() != InsnType.ARITH_ONEARG) { |
220 | | - | code.add(assignVar(insn)).add(" = "); |
| 193 | + | assignVar(code, insn); |
| 194 | + | code.add(" = "); |
221 | 195 | | } |
222 | 196 | | makeInsnBody(code, insn, state); |
223 | 197 | | code.add(';'); |
| skipped 49 lines |
273 | 247 | | makeArithOneArg((ArithNode) insn, code, state); |
274 | 248 | | break; |
275 | 249 | | |
276 | | - | case NEG: |
277 | | - | String base = "-" + arg(insn.getArg(0)); |
278 | | - | if (state.contains(Flags.BODY_ONLY)) { |
279 | | - | code.add('(').add(base).add(')'); |
280 | | - | } else { |
281 | | - | code.add(base); |
| 250 | + | case NEG: { |
| 251 | + | boolean wrap = state.contains(Flags.BODY_ONLY); |
| 252 | + | if (wrap) { |
| 253 | + | code.add('('); |
| 254 | + | } |
| 255 | + | code.add('-'); |
| 256 | + | addArg(code, insn.getArg(0)); |
| 257 | + | if (wrap) { |
| 258 | + | code.add(')'); |
282 | 259 | | } |
283 | 260 | | break; |
| 261 | + | } |
284 | 262 | | |
285 | 263 | | case RETURN: |
286 | 264 | | if (insn.getArgsCount() != 0) { |
| skipped 19 lines |
306 | 284 | | |
307 | 285 | | case CMP_L: |
308 | 286 | | case CMP_G: |
309 | | - | code.add(String.format("(%1$s > %2$s ? 1 : (%1$s == %2$s ? 0 : -1))", arg(insn, 0), arg(insn, 1))); |
| 287 | + | code.add('('); |
| 288 | + | addArg(code, insn.getArg(0)); |
| 289 | + | code.add(" > "); |
| 290 | + | addArg(code, insn.getArg(1)); |
| 291 | + | code.add(" ? 1 : ("); |
| 292 | + | addArg(code, insn.getArg(0)); |
| 293 | + | code.add(" == "); |
| 294 | + | addArg(code, insn.getArg(1)); |
| 295 | + | code.add("? 0 : -1))"); |
310 | 296 | | break; |
311 | 297 | | |
312 | 298 | | case INSTANCE_OF: { |
| skipped 1 lines |
314 | 300 | | if (wrap) { |
315 | 301 | | code.add('('); |
316 | 302 | | } |
317 | | - | code.add(arg(insn, 0)); |
| 303 | + | addArg(code, insn.getArg(0)); |
318 | 304 | | code.add(" instanceof "); |
319 | 305 | | code.add(useType((ArgType) ((IndexInsnNode) insn).getIndex())); |
320 | 306 | | if (wrap) { |
| skipped 11 lines |
332 | 318 | | |
333 | 319 | | case NEW_ARRAY: { |
334 | 320 | | ArgType arrayType = insn.getResult().getType(); |
| 321 | + | code.add("new ").add(useType(arrayType.getArrayRootElement())); |
| 322 | + | code.add('['); |
| 323 | + | addArg(code, insn.getArg(0)); |
| 324 | + | code.add(']'); |
335 | 325 | | int dim = arrayType.getArrayDimension(); |
336 | | - | code.add("new ").add(useType(arrayType.getArrayRootElement())).add('[').add(arg(insn, 0)).add(']'); |
337 | 326 | | for (int i = 0; i < dim - 1; i++) { |
338 | 327 | | code.add("[]"); |
339 | 328 | | } |
| skipped 1 lines |
341 | 330 | | } |
342 | 331 | | |
343 | 332 | | case ARRAY_LENGTH: |
344 | | - | code.add(arg(insn, 0)).add(".length"); |
| 333 | + | addArg(code, insn.getArg(0)); |
| 334 | + | code.add(".length"); |
345 | 335 | | break; |
346 | 336 | | |
347 | 337 | | case FILL_ARRAY: |
| skipped 36 lines |
384 | 374 | | code.add(staticField((FieldInfo) ((IndexInsnNode) insn).getIndex())); |
385 | 375 | | break; |
386 | 376 | | case SPUT: |
387 | | - | IndexInsnNode node = (IndexInsnNode) insn; |
388 | | - | fieldPut(node); |
389 | | - | code.add(staticField((FieldInfo) node.getIndex())).add(" = "); |
390 | | - | addArg(code, node.getArg(0), false); |
| 377 | + | FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex(); |
| 378 | + | code.add(staticField(field)).add(" = "); |
| 379 | + | addArg(code, insn.getArg(0), false); |
391 | 380 | | break; |
392 | 381 | | |
393 | 382 | | case STR_CONCAT: |
394 | | - | StringBuilder sb = new StringBuilder(); |
| 383 | + | boolean wrap = state.contains(Flags.BODY_ONLY); |
| 384 | + | if (wrap) { |
| 385 | + | code.add('('); |
| 386 | + | } |
395 | 387 | | for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) { |
396 | | - | sb.append(arg(it.next())); |
| 388 | + | addArg(code, it.next()); |
397 | 389 | | if (it.hasNext()) { |
398 | | - | sb.append(" + "); |
| 390 | + | code.add(" + "); |
399 | 391 | | } |
400 | 392 | | } |
401 | | - | // TODO: wrap in braces only if necessary |
402 | | - | if (state.contains(Flags.BODY_ONLY)) { |
403 | | - | code.add('(').add(sb.toString()).add(')'); |
404 | | - | } else { |
405 | | - | code.add(sb.toString()); |
| 393 | + | if (wrap) { |
| 394 | + | code.add(')'); |
406 | 395 | | } |
407 | 396 | | break; |
408 | 397 | | |
409 | 398 | | case MONITOR_ENTER: |
410 | 399 | | if (isFallback()) { |
411 | | - | code.add("monitor-enter(").add(arg(insn.getArg(0))).add(')'); |
| 400 | + | code.add("monitor-enter("); |
| 401 | + | addArg(code, insn.getArg(0)); |
| 402 | + | code.add(')'); |
412 | 403 | | } |
413 | 404 | | break; |
414 | 405 | | |
415 | 406 | | case MONITOR_EXIT: |
416 | 407 | | if (isFallback()) { |
417 | | - | code.add("monitor-exit(").add(arg(insn, 0)).add(')'); |
| 408 | + | code.add("monitor-exit("); |
| 409 | + | addArg(code, insn.getArg(0)); |
| 410 | + | code.add(')'); |
418 | 411 | | } |
419 | 412 | | break; |
420 | 413 | | |
| skipped 1 lines |
422 | 415 | | if (isFallback()) { |
423 | 416 | | code.add("move-exception"); |
424 | 417 | | } else { |
425 | | - | code.add(arg(insn, 0)); |
| 418 | + | addArg(code, insn.getArg(0)); |
426 | 419 | | } |
427 | 420 | | break; |
428 | 421 | | |
| skipped 2 lines |
431 | 424 | | break; |
432 | 425 | | |
433 | 426 | | case ARGS: |
434 | | - | code.add(arg(insn, 0)); |
| 427 | + | addArg(code, insn.getArg(0)); |
435 | 428 | | break; |
436 | 429 | | |
437 | 430 | | /* fallback mode instructions */ |
| skipped 1 lines |
439 | 432 | | assert isFallback() : "if insn in not fallback mode"; |
440 | 433 | | IfNode ifInsn = (IfNode) insn; |
441 | 434 | | code.add("if ("); |
442 | | - | code.add(arg(insn.getArg(0))).add(' '); |
| 435 | + | addArg(code, insn.getArg(0)); |
| 436 | + | code.add(' '); |
443 | 437 | | code.add(ifInsn.getOp().getSymbol()).add(' '); |
444 | | - | code.add(arg(insn.getArg(1))); |
| 438 | + | addArg(code, insn.getArg(1)); |
445 | 439 | | code.add(") goto ").add(MethodGen.getLabelName(ifInsn.getTarget())); |
446 | 440 | | break; |
447 | 441 | | |
| skipped 5 lines |
453 | 447 | | case SWITCH: |
454 | 448 | | assert isFallback(); |
455 | 449 | | SwitchNode sw = (SwitchNode) insn; |
456 | | - | code.add("switch(").add(arg(insn, 0)).add(") {"); |
| 450 | + | code.add("switch("); |
| 451 | + | addArg(code, insn.getArg(0)); |
| 452 | + | code.add(") {"); |
457 | 453 | | code.incIndent(); |
458 | 454 | | for (int i = 0; i < sw.getCasesCount(); i++) { |
459 | 455 | | code.startLine("case ").add(sw.getKeys()[i]).add(": goto "); |
| skipped 21 lines |
481 | 477 | | code.add("new ").add(useType(insn.getResult().getType())); |
482 | 478 | | code.add('{'); |
483 | 479 | | for (int i = 0; i < c; i++) { |
484 | | - | code.add(arg(insn, i)); |
| 480 | + | addArg(code, insn.getArg(i)); |
485 | 481 | | if (i + 1 < c) { |
486 | 482 | | code.add(", "); |
487 | 483 | | } |
| skipped 77 lines |
565 | 561 | | defCtr.getAttributes().add(AttributeFlag.DONT_GENERATE); |
566 | 562 | | } |
567 | 563 | | code.add("new ").add(parent == null ? "Object" : useClass(parent)).add("() "); |
568 | | - | new ClassGen(cls, mgen.getClassGen().getParentGen(), fallback).makeClassBody(code); |
| 564 | + | new ClassGen(cls, mgen.getClassGen().getParentGen(), fallback).addClassBody(code); |
569 | 565 | | return; |
570 | 566 | | } |
571 | 567 | | if (insn.isSelf()) { |
| skipped 133 lines |
705 | 701 | | } |
706 | 702 | | |
707 | 703 | | private void makeTernary(TernaryInsn insn, CodeWriter code, EnumSet<Flags> state) throws CodegenException { |
708 | | - | String cond = ConditionGen.make(this, insn.getCondition()); |
709 | | - | CodeWriter th = arg(insn.getArg(0), false); |
710 | | - | CodeWriter els = arg(insn.getArg(1), false); |
711 | | - | if (th.toString().equals("true") && els.toString().equals("false")) { |
712 | | - | code.add(cond); |
| 704 | + | boolean wrap = state.contains(Flags.BODY_ONLY); |
| 705 | + | if (wrap) { |
| 706 | + | code.add('('); |
| 707 | + | } |
| 708 | + | InsnArg first = insn.getArg(0); |
| 709 | + | InsnArg second = insn.getArg(1); |
| 710 | + | ConditionGen condGen = new ConditionGen(this); |
| 711 | + | if (first.equals(LiteralArg.TRUE) && second.equals(LiteralArg.FALSE)) { |
| 712 | + | condGen.add(code, insn.getCondition()); |
713 | 713 | | } else { |
714 | | - | if (state.contains(Flags.BODY_ONLY)) { |
715 | | - | code.add("((").add(cond).add(')').add(" ? ").add(th).add(" : ").add(els).add(')'); |
716 | | - | } else { |
717 | | - | code.add('(').add(cond).add(')').add(" ? ").add(th).add(" : ").add(els); |
718 | | - | } |
| 714 | + | condGen.wrap(code, insn.getCondition()); |
| 715 | + | code.add(" ? "); |
| 716 | + | addArg(code, first, false); |
| 717 | + | code.add(" : "); |
| 718 | + | addArg(code, second, false); |
| 719 | + | } |
| 720 | + | if (wrap) { |
| 721 | + | code.add(')'); |
719 | 722 | | } |
720 | 723 | | } |
721 | 724 | | |
| skipped 21 lines |
743 | 746 | | if (arg.isLiteral() && (op == ArithOp.ADD || op == ArithOp.SUB)) { |
744 | 747 | | LiteralArg lit = (LiteralArg) arg; |
745 | 748 | | if (lit.isInteger() && lit.getLiteral() == 1) { |
| 749 | + | assignVar(code, insn); |
746 | 750 | | String opSymbol = op.getSymbol(); |
747 | | - | code.add(assignVar(insn)).add(opSymbol).add(opSymbol); |
| 751 | + | code.add(opSymbol).add(opSymbol); |
748 | 752 | | return; |
749 | 753 | | } |
750 | 754 | | } |
751 | 755 | | // +=, -= ... |
752 | | - | code.add(assignVar(insn)).add(' ').add(op.getSymbol()).add("= "); |
| 756 | + | assignVar(code, insn); |
| 757 | + | code.add(' ').add(op.getSymbol()).add("= "); |
753 | 758 | | addArg(code, arg, false); |
754 | 759 | | } |
755 | 760 | | } |
| skipped 1 lines |