parabase.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generic calling convention handling
  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 parabase;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,globtype,
  22. cpubase,cgbase,cgutils,
  23. symtype, ppu;
  24. type
  25. TCGParaReference = record
  26. index : tregister;
  27. offset : aint;
  28. end;
  29. PCGParaLocation = ^TCGParaLocation;
  30. TCGParaLocation = record
  31. Next : PCGParaLocation;
  32. Size : TCGSize; { size of this location }
  33. Loc : TCGLoc;
  34. case TCGLoc of
  35. LOC_REFERENCE : (reference : TCGParaReference);
  36. LOC_FPUREGISTER,
  37. LOC_CFPUREGISTER,
  38. LOC_MMREGISTER,
  39. LOC_CMMREGISTER,
  40. LOC_REGISTER,
  41. LOC_CREGISTER : (
  42. {
  43. * If shiftval > 0:
  44. The number of bits the value in the register must be shifted to the left before
  45. it can be stored to memory in the function prolog.
  46. This is used for passing OS_NO memory blocks less than register size and of "odd"
  47. (3, 5, 6, 7) size on big endian machines, so that small memory blocks passed via
  48. registers are properly aligned.
  49. E.g. the value $5544433 is passed in bits 40-63 of the register (others are zero),
  50. but they should actually be stored in the first bits of the stack location reserved
  51. for this value. So they have to be shifted left by this amount of bits before.
  52. * if shiftval < 0:
  53. Similar as above, but the shifting must always be done and
  54. 1) for all parameter sizes < regsize
  55. 2) on the caller side
  56. }
  57. shiftval : shortint;
  58. register : tregister);
  59. end;
  60. TCGPara = object
  61. Location : PCGParalocation;
  62. IntSize : tcgint; { size of the total location in bytes }
  63. Alignment : ShortInt;
  64. Size : TCGSize; { Size of the parameter included in all locations }
  65. {$ifdef powerpc}
  66. composite: boolean; { under the AIX abi, how certain parameters are passed depends on whether they are composite or not }
  67. {$endif powerpc}
  68. constructor init;
  69. destructor done;
  70. procedure reset;
  71. function getcopy:tcgpara;
  72. procedure check_simple_location;
  73. function add_location:pcgparalocation;
  74. procedure get_location(var newloc:tlocation);
  75. procedure ppuwrite(ppufile:tcompilerppufile);
  76. procedure ppuload(ppufile:tcompilerppufile);
  77. end;
  78. tvarargsinfo = (
  79. va_uses_float_reg
  80. );
  81. tparalist = class(TFPObjectList)
  82. procedure SortParas;
  83. end;
  84. tvarargsparalist = class(tparalist)
  85. varargsinfo : set of tvarargsinfo;
  86. {$ifdef x86_64}
  87. { x86_64 requires %al to contain the no. SSE regs passed }
  88. mmregsused : longint;
  89. {$endif x86_64}
  90. end;
  91. implementation
  92. uses
  93. systems,verbose,
  94. symsym;
  95. {****************************************************************************
  96. TCGPara
  97. ****************************************************************************}
  98. constructor tcgpara.init;
  99. begin
  100. alignment:=0;
  101. size:=OS_NO;
  102. intsize:=0;
  103. location:=nil;
  104. {$ifdef powerpc}
  105. composite:=false;
  106. {$endif powerpc}
  107. end;
  108. destructor tcgpara.done;
  109. begin
  110. reset;
  111. end;
  112. procedure tcgpara.reset;
  113. var
  114. hlocation : pcgparalocation;
  115. begin
  116. while assigned(location) do
  117. begin
  118. hlocation:=location^.next;
  119. dispose(location);
  120. location:=hlocation;
  121. end;
  122. alignment:=0;
  123. size:=OS_NO;
  124. intsize:=0;
  125. {$ifdef powerpc}
  126. composite:=false;
  127. {$endif powerpc}
  128. end;
  129. function tcgpara.getcopy:tcgpara;
  130. var
  131. hlocation : pcgparalocation;
  132. begin
  133. result.init;
  134. while assigned(location) do
  135. begin
  136. hlocation:=result.add_location;
  137. hlocation^:=location^;
  138. hlocation^.next:=nil;
  139. location:=location^.next;
  140. end;
  141. result.alignment:=alignment;
  142. result.size:=size;
  143. result.intsize:=intsize;
  144. {$ifdef powerpc}
  145. result.composite:=composite;
  146. {$endif powerpc}
  147. end;
  148. function tcgpara.add_location:pcgparalocation;
  149. var
  150. prevlocation,
  151. hlocation : pcgparalocation;
  152. begin
  153. prevlocation:=nil;
  154. hlocation:=location;
  155. while assigned(hlocation) do
  156. begin
  157. prevlocation:=hlocation;
  158. hlocation:=hlocation^.next;
  159. end;
  160. new(hlocation);
  161. Fillchar(hlocation^,sizeof(tcgparalocation),0);
  162. if assigned(prevlocation) then
  163. prevlocation^.next:=hlocation
  164. else
  165. location:=hlocation;
  166. result:=hlocation;
  167. end;
  168. procedure tcgpara.check_simple_location;
  169. begin
  170. if not assigned(location) then
  171. internalerror(200408161);
  172. if assigned(location^.next) then
  173. internalerror(200408162);
  174. end;
  175. procedure tcgpara.get_location(var newloc:tlocation);
  176. begin
  177. if not assigned(location) then
  178. internalerror(200408205);
  179. fillchar(newloc,sizeof(newloc),0);
  180. newloc.loc:=location^.loc;
  181. newloc.size:=size;
  182. case location^.loc of
  183. LOC_REGISTER :
  184. begin
  185. {$ifndef cpu64bitalu}
  186. if size in [OS_64,OS_S64] then
  187. begin
  188. if not assigned(location^.next) then
  189. internalerror(200408206);
  190. if (location^.next^.loc<>LOC_REGISTER) then
  191. internalerror(200408207);
  192. if (target_info.endian = ENDIAN_BIG) then
  193. begin
  194. newloc.register64.reghi:=location^.register;
  195. newloc.register64.reglo:=location^.next^.register;
  196. end
  197. else
  198. begin
  199. newloc.register64.reglo:=location^.register;
  200. newloc.register64.reghi:=location^.next^.register;
  201. end;
  202. end
  203. else
  204. {$endif}
  205. newloc.register:=location^.register;
  206. end;
  207. LOC_FPUREGISTER,
  208. LOC_MMREGISTER :
  209. newloc.register:=location^.register;
  210. LOC_REFERENCE :
  211. begin
  212. newloc.reference.base:=location^.reference.index;
  213. newloc.reference.offset:=location^.reference.offset;
  214. newloc.reference.alignment:=alignment;
  215. end;
  216. end;
  217. end;
  218. procedure TCGPara.ppuwrite(ppufile: tcompilerppufile);
  219. var
  220. hparaloc: PCGParaLocation;
  221. nparaloc: byte;
  222. begin
  223. ppufile.putbyte(byte(Alignment));
  224. ppufile.putbyte(ord(Size));
  225. ppufile.putaint(IntSize);
  226. {$ifdef powerpc}
  227. ppufile.putbyte(byte(composite));
  228. {$endif}
  229. nparaloc:=0;
  230. hparaloc:=location;
  231. while assigned(hparaloc) do
  232. begin
  233. inc(nparaloc);
  234. hparaloc:=hparaloc^.Next;
  235. end;
  236. ppufile.putbyte(nparaloc);
  237. hparaloc:=location;
  238. while assigned(hparaloc) do
  239. begin
  240. ppufile.putbyte(byte(hparaloc^.Size));
  241. ppufile.putbyte(byte(hparaloc^.loc));
  242. case hparaloc^.loc of
  243. LOC_REFERENCE:
  244. begin
  245. ppufile.putlongint(longint(hparaloc^.reference.index));
  246. ppufile.putaint(hparaloc^.reference.offset);
  247. end;
  248. LOC_FPUREGISTER,
  249. LOC_CFPUREGISTER,
  250. LOC_MMREGISTER,
  251. LOC_CMMREGISTER,
  252. LOC_REGISTER,
  253. LOC_CREGISTER :
  254. begin
  255. ppufile.putbyte(hparaloc^.shiftval);
  256. ppufile.putlongint(longint(hparaloc^.register));
  257. end;
  258. { This seems to be required for systems using explicitparaloc (eg. MorphOS)
  259. or otherwise it hits the internalerror below. I don't know if this is
  260. the proper way to fix this, someone else with clue might want to take a
  261. look. The compiler cycles on the affected systems with this enabled. (KB) }
  262. LOC_VOID:
  263. begin end
  264. else
  265. internalerror(2010053115);
  266. end;
  267. hparaloc:=hparaloc^.next;
  268. end;
  269. end;
  270. procedure TCGPara.ppuload(ppufile: tcompilerppufile);
  271. var
  272. hparaloc: PCGParaLocation;
  273. nparaloc: byte;
  274. begin
  275. reset;
  276. Alignment:=shortint(ppufile.getbyte);
  277. Size:=TCgSize(ppufile.getbyte);
  278. IntSize:=ppufile.getaint;
  279. {$ifdef powerpc}
  280. composite:=boolean(ppufile.getbyte);
  281. {$endif}
  282. nparaloc:=ppufile.getbyte;
  283. while nparaloc>0 do
  284. begin
  285. hparaloc:=add_location;
  286. hparaloc^.size:=TCGSize(ppufile.getbyte);
  287. hparaloc^.loc:=TCGLoc(ppufile.getbyte);
  288. case hparaloc^.loc of
  289. LOC_REFERENCE:
  290. begin
  291. hparaloc^.reference.index:=tregister(ppufile.getlongint);
  292. hparaloc^.reference.offset:=ppufile.getaint;
  293. end;
  294. LOC_FPUREGISTER,
  295. LOC_CFPUREGISTER,
  296. LOC_MMREGISTER,
  297. LOC_CMMREGISTER,
  298. LOC_REGISTER,
  299. LOC_CREGISTER :
  300. begin
  301. hparaloc^.shiftval:=ppufile.getbyte;
  302. hparaloc^.register:=tregister(ppufile.getlongint);
  303. end;
  304. { This seems to be required for systems using explicitparaloc (eg. MorphOS)
  305. or otherwise it hits the internalerror below. I don't know if this is
  306. the proper way to fix this, someone else with clue might want to take a
  307. look. The compiler cycles on the affected systems with this enabled. (KB) }
  308. LOC_VOID:
  309. begin end
  310. else
  311. internalerror(2010051301);
  312. end;
  313. dec(nparaloc);
  314. end;
  315. end;
  316. {****************************************************************************
  317. TParaList
  318. ****************************************************************************}
  319. function ParaNrCompare(Item1, Item2: Pointer): Integer;
  320. var
  321. I1 : tparavarsym absolute Item1;
  322. I2 : tparavarsym absolute Item2;
  323. begin
  324. Result:=longint(I1.paranr)-longint(I2.paranr);
  325. end;
  326. procedure TParaList.SortParas;
  327. begin
  328. Sort(@ParaNrCompare);
  329. end;
  330. end.