nllvmcal.pas 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. {
  2. Copyright (c) 2014 by Jonas Maebe
  3. Generate LLVM bytecode for call 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 nllvmcal;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. parabase,
  22. ncal,ncgcal,
  23. cgutils;
  24. type
  25. tllvmcallparanode = class(tcgcallparanode)
  26. procedure push_formal_para; override;
  27. end;
  28. tllvmcallnode = class(tcgcallnode)
  29. protected
  30. function paraneedsinlinetemp(para: tcallparanode; const pushconstaddr, complexpara: boolean): boolean; override;
  31. function can_call_ref(var ref: treference): boolean; override;
  32. procedure pushparas; override;
  33. procedure pass_generate_code; override;
  34. end;
  35. implementation
  36. uses
  37. verbose,
  38. aasmbase,aasmdata,aasmllvm,
  39. symconst,symdef;
  40. procedure tllvmcallparanode.push_formal_para;
  41. begin
  42. if parasym.vardef<>llvm_metadatatype then
  43. begin;
  44. inherited;
  45. exit;
  46. end;
  47. push_value_para;
  48. end;
  49. {*****************************************************************************
  50. TLLVMCALLNODE
  51. *****************************************************************************}
  52. function tllvmcallnode.paraneedsinlinetemp(para: tcallparanode; const pushconstaddr, complexpara: boolean): boolean;
  53. begin
  54. { We don't insert type conversions for self node trees to the type of
  55. the self parameter (and doing so is quite hard due to all kinds of
  56. ugly hacks with this parameter). This means that if we pass on a
  57. self parameter through multiple levels of inlining, it may no
  58. longer match the actual type of the parameter it has been passed to
  59. -> always store in a temp which by definition will have the right
  60. type (if it's a pointer-like type) }
  61. if (vo_is_self in para.parasym.varoptions) and
  62. (is_class_or_interface_or_dispinterface(para.parasym.vardef) or
  63. is_classhelper(para.parasym.vardef) or
  64. ((para.parasym.vardef.typ=classrefdef) and
  65. is_class(tclassrefdef(para.parasym.vardef).pointeddef))) then
  66. result:=true
  67. else
  68. result:=inherited;
  69. end;
  70. function tllvmcallnode.can_call_ref(var ref: treference): boolean;
  71. begin
  72. result:=false;
  73. end;
  74. procedure tllvmcallnode.pushparas;
  75. var
  76. n: tcgcallparanode;
  77. paraindex: longint;
  78. begin
  79. { we just pass the temp paralocs here }
  80. if not assigned(varargsparas) then
  81. setlength(paralocs,procdefinition.paras.count)
  82. else
  83. setlength(paralocs,procdefinition.paras.count+varargsparas.count);
  84. n:=tcgcallparanode(left);
  85. while assigned(n) do
  86. begin
  87. { TODO: check whether this is correct for left-to-right calling
  88. conventions, may also depend on whether or not llvm knows about
  89. the calling convention }
  90. if not(cpf_varargs_para in n.callparaflags) then
  91. paraindex:=procdefinition.paras.indexof(n.parasym)
  92. else
  93. paraindex:=procdefinition.paras.count+varargsparas.indexof(n.parasym);
  94. if paraindex=-1 then
  95. internalerror(2014010602);
  96. paralocs[paraindex]:[email protected];
  97. n:=tcgcallparanode(n.right);
  98. end;
  99. end;
  100. procedure tllvmcallnode.pass_generate_code;
  101. var
  102. asmsym: tasmsymbol;
  103. begin
  104. inherited;
  105. if assigned(overrideprocnamedef) and
  106. not overrideprocnamedef.in_currentunit then
  107. begin
  108. { insert an llvm declaration for this def if it's not defined in
  109. the current unit, because otherwise we will define it in the
  110. LLVM IR using the def for which this procdef's name is used
  111. first, which may be something completely different from the original
  112. def. LLVM can take the original def into account to load certain
  113. registers, so if we use a wrong def this can result in wrong code
  114. generation. }
  115. asmsym:=current_asmdata.RefAsmSymbol(overrideprocnamedef.mangledname,AT_FUNCTION);
  116. if not asmsym.declared then
  117. begin
  118. current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.createdecl(asmsym,symtableprocentry,overrideprocnamedef,nil,sec_code,overrideprocnamedef.alignment));
  119. end;
  120. end;
  121. end;
  122. begin
  123. ccallparanode:=tllvmcallparanode;
  124. ccallnode:=tllvmcallnode;
  125. end.