njvmset.pas 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. {
  2. Copyright (c) 2011 by Jonas Maebe
  3. Generate JVM bytecode for in set/case nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit njvmset;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. node,nset,ncgset;
  23. type
  24. tjvminnode = class(tcginnode)
  25. function pass_1: tnode; override;
  26. end;
  27. tjvmcasenode = class(tcgcasenode)
  28. function pass_1: tnode; override;
  29. end;
  30. implementation
  31. uses
  32. symconst,symdef,
  33. pass_1,
  34. ncal,ncnv,ncon,nmem,
  35. njvmcon,
  36. cgbase;
  37. {*****************************************************************************
  38. TJVMINNODE
  39. *****************************************************************************}
  40. function tjvminnode.pass_1: tnode;
  41. var
  42. setparts: Tsetparts;
  43. numparts: byte;
  44. use_small: boolean;
  45. isenum: boolean;
  46. begin
  47. { before calling "inherited pass_1", so that in case left is an enum
  48. constant it's not yet translated into a class instance }
  49. isenum:=left.resultdef.typ=enumdef;
  50. { if we can use jumps, don't transform the set constant and (if
  51. applicable) the value to be tested }
  52. if checkgenjumps(setparts,numparts,use_small) then
  53. begin
  54. if right.nodetype=setconstn then
  55. tjvmsetconstnode(right).setconsttype:=sct_notransform;
  56. if isenum and
  57. (left.nodetype=ordconstn) then
  58. tjvmordconstnode(left).enumconstok:=true;
  59. end;
  60. result:=inherited pass_1;
  61. if assigned(result) then
  62. exit;
  63. { in case of jumps let the regular code handle it }
  64. if expectloc=LOC_JUMP then
  65. exit;
  66. { otherwise call set helper }
  67. right:=caddrnode.create_internal(right);
  68. include(right.flags,nf_typedaddr);
  69. if isenum then
  70. begin
  71. inserttypeconv_explicit(left,java_jlenum);
  72. inserttypeconv_explicit(right,java_juenumset);
  73. end
  74. else
  75. begin
  76. inserttypeconv_explicit(left,s32inttype);
  77. inserttypeconv_explicit(right,java_jubitset);
  78. end;
  79. result:=ccallnode.createinternmethod(right,'CONTAINS',ccallparanode.create(left,nil));
  80. right:=nil;
  81. left:=nil;
  82. end;
  83. {*****************************************************************************
  84. TJVMCASENODE
  85. *****************************************************************************}
  86. function tjvmcasenode.pass_1: tnode;
  87. begin
  88. { convert case expression to an integer in case it's an enum, since
  89. enums are class instances in the JVM. All labels are stored as
  90. ordinal values, so it doesn't matter that we change the type }
  91. if left.resultdef.typ=enumdef then
  92. inserttypeconv_explicit(left,s32inttype);
  93. result:=inherited pass_1;
  94. end;
  95. begin
  96. cinnode:=tjvminnode;
  97. ccasenode:=tjvmcasenode;
  98. end.