2
0

nllvmld.pas 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. {
  2. Copyright (c) 2012 by Jonas Maebe
  3. Generate LLVM bytecode for nodes that handle loads and assignments
  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 nllvmld;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. cgutils,
  23. symtype,
  24. node,ncgld,ncgnstld;
  25. type
  26. tllvmloadnode = class(tcgnestloadnode)
  27. function pass_1: tnode; override;
  28. procedure pass_generate_code; override;
  29. end;
  30. { tllvmarrayconstructornode }
  31. tllvmarrayconstructornode = class(tcgarrayconstructornode)
  32. protected
  33. procedure makearrayref(var ref: treference; eledef: tdef); override;
  34. end;
  35. implementation
  36. uses
  37. systems,
  38. aasmbase,aasmdata,aasmllvm,
  39. nld,
  40. symtable,symconst,symdef,symsym,defutil,
  41. procinfo,tgobj,
  42. llvmbase,cgbase,hlcgobj;
  43. function tllvmloadnode.pass_1: tnode;
  44. begin
  45. result:=inherited;
  46. if assigned(result) then
  47. exit;
  48. case symtableentry.typ of
  49. procsym:
  50. begin
  51. if assigned(left) then
  52. expectloc:=LOC_REFERENCE;
  53. end;
  54. else
  55. ;
  56. end;
  57. end;
  58. procedure tllvmloadnode.pass_generate_code;
  59. var
  60. pvdef: tprocvardef;
  61. href, mpref: treference;
  62. field: tfieldvarsym;
  63. procreg, selfreg: tregister;
  64. selfdef: tdef;
  65. ai: taillvm;
  66. begin
  67. inherited;
  68. case symtableentry.typ of
  69. procsym:
  70. begin
  71. { if the result is returned in two registers, force it to memory into
  72. a single memory location, as we don't use the registerhi/register
  73. location hack for llvm (llvm will put it back into registers itself)
  74. }
  75. if assigned(left) and
  76. (resultdef.typ in [symconst.procdef,procvardef]) and
  77. not tabstractprocdef(resultdef).is_addressonly then
  78. begin
  79. pvdef:=cprocvardef.getreusableprocaddr(procdef,pc_normal);
  80. { on little endian, location.register contains proc and
  81. location.registerhi contains self; on big endian, it's the
  82. other way around }
  83. tg.gethltemp(current_asmdata.CurrAsmList,pvdef,pvdef.size,tt_normal,href);
  84. if target_info.endian=endian_little then
  85. begin
  86. procreg:=location.register;
  87. selfreg:=location.registerhi
  88. end
  89. else
  90. begin
  91. procreg:=location.registerhi;
  92. selfreg:=location.register
  93. end;
  94. { left can be a pointerdef when we take the address of a nested
  95. procedure, as left will then be a pointer to the nestedfpstruct
  96. }
  97. if is_implicit_pointer_object_type(left.resultdef) or
  98. (left.resultdef.typ in [classrefdef,pointerdef]) then
  99. selfdef:=left.resultdef
  100. else
  101. selfdef:=cpointerdef.getreusable(left.resultdef);
  102. mpref:=href;
  103. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(pvdef),cpointerdef.getreusable(methodpointertype),mpref);
  104. hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef,pc_address_only),trecorddef(methodpointertype),procreg,'proc',mpref);
  105. hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,selfdef,trecorddef(methodpointertype),selfreg,'self',mpref);
  106. location_reset_ref(location,LOC_REFERENCE,location.size,href.alignment,href.volatility);
  107. location.reference:=href;
  108. end;
  109. end;
  110. labelsym:
  111. begin
  112. selfreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidcodepointertype);
  113. ai:=taillvm.blockaddress(voidcodepointertype,
  114. current_asmdata.RefAsmSymbol(current_procinfo.procdef.mangledname,AT_FUNCTION),
  115. location.reference.symbol
  116. );
  117. current_asmdata.CurrAsmList.concat(
  118. taillvm.op_reg_tai_size(la_bitcast,selfreg,ai,voidcodepointertype)
  119. );
  120. reference_reset_base(location.reference,selfreg,0,ctempposinvalid,location.reference.alignment,location.reference.volatility);
  121. end;
  122. else
  123. ;
  124. end;
  125. end;
  126. { tllvmarrayconstructornode }
  127. procedure tllvmarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  128. begin
  129. { the array elements are addressed as pointer to the individual elements ->
  130. convert }
  131. hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef),cpointerdef.getreusable(eledef),ref);
  132. end;
  133. begin
  134. cloadnode:=tllvmloadnode;
  135. carrayconstructornode:=tllvmarrayconstructornode;
  136. end.