list.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /* list.c: List model definitions
  2. Copyright (C) 2003 Sebastian Reichelt, Kevin Kofler
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software Foundation,
  13. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  14. #include "list.h"
  15. #include "../../integers.h"
  16. #include "../../manip.h"
  17. #include "../../special.h"
  18. #include <stdlib.h>
  19. #include <string.h>
  20. // Get the number of items from the LIST_MODEL passed to the
  21. // function via the Model parameter, for a particular source section.
  22. COUNT GetSectionItemCount (LIST_MODEL *Model, SECTION *SourceSection, void *UserData)
  23. {
  24. void *NextItem = NULL;
  25. return Model (SourceSection, &NextItem, UserData, TRUE, FALSE);
  26. }
  27. // Get the number of items from the LIST_MODEL passed to the
  28. // function via the Model parameter. If SourceSection is NULL, loop
  29. // through all sections in the program.
  30. COUNT GetItemCount (LIST_MODEL *Model, PROGRAM *Program, SECTION *SourceSection, void *UserData)
  31. {
  32. COUNT GetCurrentItemCount (void)
  33. {
  34. return GetSectionItemCount (Model, SourceSection, UserData);
  35. }
  36. if (SourceSection)
  37. return GetCurrentItemCount ();
  38. else
  39. {
  40. COUNT Result = 0;
  41. for_each (SourceSection, Program->Sections)
  42. Result += GetCurrentItemCount ();
  43. return Result;
  44. }
  45. }
  46. // A LIST_MODEL for relocs. This list model will return all relocs
  47. // in SourceSection (that point to TargetSection if it is not NULL).
  48. OFFSET RelocListModel (SECTION *SourceSection, RELOC **NextItem, RELOC_USER_DATA *UserData, BOOLEAN Count, BOOLEAN Emit)
  49. {
  50. COUNT Counter = 0;
  51. RELOC *CurReloc;
  52. // If no next item is specified yet, this must be the first call to this model
  53. // with this SourceSection. The caller cannot fill *NextItem because it does
  54. // not know how to get the first item.
  55. if (!(*NextItem))
  56. *NextItem = TreeFirst (SourceSection->Relocs);
  57. // Loop until we are done with counting or can return the next reloc that is
  58. // important for us.
  59. while ((CurReloc = *NextItem))
  60. {
  61. *NextItem = TreeNext (CurReloc);
  62. // Returning a location < 0 would be fatal, since it means we are done.
  63. if ((CurReloc->Location >= 0) && (CurReloc->Location + CurReloc->Size <= SourceSection->Size))
  64. {
  65. // Ignore relocs which we will not emit.
  66. if (!(CurReloc->Relative || CurReloc->Target.Builtin || CurReloc->Parent->DebuggingInfoType || (CurReloc->Target.Symbol && CurReloc->Target.Symbol->Parent->DebuggingInfoType)))
  67. {
  68. // We can only emit 4-byte absolute relocs.
  69. // Everything else would need to be specified in the user data structure.
  70. if (CurReloc->Size == 4)
  71. {
  72. // If a target section is specified, use only relocs that explicitly point to it.
  73. // Otherwise, use all relocs that do not explicitly point to a handled section.
  74. if (UserData->TargetSection ? (CurReloc->Target.Symbol && (CurReloc->Target.Symbol->Parent == UserData->TargetSection)) : (!(CurReloc->Target.Symbol && (CurReloc->Target.Symbol->Parent->Handled))))
  75. {
  76. // When counting, simply increment the counter.
  77. if (Count)
  78. Counter++;
  79. // Otherwise, return the location.
  80. else
  81. {
  82. // If Emit is true, we must emit the fixed/target offset of the reloc
  83. // into the section contents.
  84. if (Emit)
  85. {
  86. // Change CurReloc to be relative to the section or program.
  87. SetRelocRelation (CurReloc, UserData->TargetSection, 0);
  88. // We won't see this reloc any more,
  89. // so increase the statistics.
  90. SourceSection->Relocs.EmittedCount++;
  91. SourceSection->Parent->OptimizeInfo->RelocCount++;
  92. }
  93. // Return the location.
  94. return CurReloc->Location;
  95. }
  96. }
  97. }
  98. }
  99. }
  100. // Output an error message only when counting, so we get it only once.
  101. else if (Count)
  102. Error (SourceSection->FileName, "Ignoring reloc outside of section.");
  103. }
  104. // We have reached the end of the section.
  105. // Return the number of items when counting.
  106. if (Count)
  107. return Counter;
  108. else
  109. return -1;
  110. }
  111. // A LIST_MODEL for ROM calls. This list model will return all ROM calls
  112. // in SourceSection (that point to CurFunction if it is >= 0).
  113. OFFSET ROMCallListModel (SECTION *SourceSection, ROM_CALL **NextItem, ROM_CALL_USER_DATA *UserData, BOOLEAN Count, BOOLEAN Emit)
  114. {
  115. COUNT Counter = 0;
  116. ROM_CALL_FUNCTION_DATA *ROMFunctions = UserData->ROMFunctions;
  117. OFFSET CurFunction = UserData->CurFunction;
  118. ROM_CALL *CurROMCall;
  119. if (!Count)
  120. {
  121. // After this enumeration, ROM calls are supported and do not need any further treatment.
  122. SourceSection->ROMCalls.Handled = TRUE;
  123. }
  124. // If no next item is specified yet, this must be the first call to this model
  125. // with this SourceSection and CurFunction. The caller cannot fill *NextItem
  126. // because it does not know how to get the first item.
  127. if (!(*NextItem))
  128. *NextItem = GetFirst (SourceSection->ROMCalls);
  129. // Loop until we are done with counting or can return the next ROM call that is
  130. // important for us.
  131. while ((CurROMCall = *NextItem))
  132. {
  133. *NextItem = GetNext (CurROMCall);
  134. // Returning a location < 0 would be fatal, since it means we are done.
  135. if ((CurROMCall->Location >= 0) && (CurROMCall->Location + CurROMCall->Size <= SourceSection->Size))
  136. {
  137. // Only proceed if we want this ROM call number.
  138. if ((CurFunction < 0) || (CurROMCall->Number == CurFunction))
  139. {
  140. // We can only emit 4-byte ROM calls.
  141. // Everything else would need to be specified in the user data structure.
  142. if (CurROMCall->Size == 4)
  143. {
  144. // When counting, increment the main counter and all counters
  145. // from the user data structure.
  146. if (Count)
  147. {
  148. Counter++;
  149. if (!(ROMFunctions[CurROMCall->Number].RelocCount++))
  150. UserData->ROMFunctionCount++;
  151. }
  152. // Otherwise, return the location.
  153. else
  154. {
  155. // If Emit is true, we must emit the fixed offset of the ROM call
  156. // into the section contents.
  157. if (Emit)
  158. {
  159. // Write our target offset into the section data.
  160. if (SourceSection->Data)
  161. WriteTI4 (*((TI4 *) (SourceSection->Data + CurROMCall->Location)), CurROMCall->FixedOffset);
  162. }
  163. // If we want to get all ROM calls, we need information about
  164. // this ROM call.
  165. // Otherwise, this does not have any effect.
  166. UserData->CurFunction = CurROMCall->Number;
  167. // Return the location.
  168. return CurROMCall->Location;
  169. }
  170. }
  171. // Output an error message only when counting, so we get it only once.
  172. else if (Count)
  173. Error (GetFileName (SourceSection, CurROMCall->Location), "Cannot emit %ld byte ROM call 0x%lX.", (long) CurROMCall->Size, (long) CurROMCall->Number);
  174. }
  175. }
  176. // Output an error message only when counting, so we get it only once.
  177. else if (Count)
  178. Error (SourceSection->FileName, "Ignoring ROM call outside of section.");
  179. }
  180. // We have reached the end of the section.
  181. // Return the number of items when counting.
  182. if (Count)
  183. return Counter;
  184. else
  185. return -1;
  186. }
  187. // A LIST_MODEL for RAM calls. This list model will return all ROM calls
  188. // in SourceSection (of type CurType if it is not RT_ALL_TYPES, that point
  189. // to CurFunction if it is >= 0).
  190. OFFSET RAMCallListModel (SECTION *SourceSection, RAM_CALL **NextItem, RAM_CALL_USER_DATA *UserData, BOOLEAN Count, BOOLEAN Emit)
  191. {
  192. COUNT Counter = 0;
  193. RAM_CALL_TYPE_DATA *RAMTypes = UserData->RAMTypes;
  194. RAM_CALL_TYPE CurType = UserData->CurType;
  195. OFFSET CurFunction = UserData->CurFunction;
  196. RAM_CALL *CurRAMCall;
  197. if (!Count)
  198. {
  199. // After this enumeration, RAM calls are supported and do not need any further treatment.
  200. SourceSection->RAMCalls.Handled = TRUE;
  201. }
  202. // If no next item is specified yet, this must be the first call to this model
  203. // with this SourceSection and CurFunction. The caller cannot fill *NextItem
  204. // because it does not know how to get the first item.
  205. if (!(*NextItem))
  206. *NextItem = GetFirst (SourceSection->RAMCalls);
  207. // Loop until we are done with counting or can return the next RAM call that is
  208. // important for us.
  209. while ((CurRAMCall = *NextItem))
  210. {
  211. *NextItem = GetNext (CurRAMCall);
  212. // Returning a location < 0 would be fatal, since it means we are done.
  213. if ((CurRAMCall->Location >= 0) && (CurRAMCall->Location + CurRAMCall->Size <= SourceSection->Size))
  214. {
  215. // Only proceed if we want this RAM call number.
  216. if ((CurFunction < 0) || (CurRAMCall->Number == CurFunction))
  217. {
  218. // Check if the type is valid.
  219. RAM_CALL_TYPE ThisType = GetRAMCallType (CurRAMCall);
  220. if (ThisType >= 0)
  221. {
  222. // Only proceed if we want this RAM call type.
  223. if ((CurType < 0) || (ThisType == CurType))
  224. {
  225. // When counting, increment the main counter and all counters
  226. // from the user data structure.
  227. if (Count)
  228. {
  229. Counter++;
  230. if (!(RAMTypes[ThisType].Functions[CurRAMCall->Number].RelocCount++))
  231. {
  232. RAMTypes[ThisType].FunctionCount++;
  233. UserData->RAMFunctionCount++;
  234. }
  235. }
  236. // Otherwise, return the location.
  237. else
  238. {
  239. // If Emit is true, we must emit the fixed offset of the RAM call
  240. // into the section contents.
  241. if (Emit)
  242. {
  243. // Write our target offset into the section data.
  244. if (SourceSection->Data)
  245. WriteTI (SourceSection->Data + CurRAMCall->Location, CurRAMCall->Size, CurRAMCall->FixedOffset, TRUE, FALSE);
  246. }
  247. // If we want to get all RAM calls, we need information about
  248. // this RAM call.
  249. // Otherwise, this does not have any effect.
  250. UserData->CurType = ThisType;
  251. UserData->CurFunction = CurRAMCall->Number;
  252. // Return the location.
  253. return CurRAMCall->Location;
  254. }
  255. }
  256. }
  257. // Output an error message only when counting, so we get it only once.
  258. else if (Count)
  259. Error (GetFileName (SourceSection, 0), "Cannot emit %ld byte RAM call 0x%lX.", (long) CurRAMCall->Size, (long) CurRAMCall->Number);
  260. }
  261. }
  262. // Output an error message only when counting, so we get it only once.
  263. else if (Count)
  264. Error (SourceSection->FileName, "Ignoring RAM call outside of section.");
  265. }
  266. // We have reached the end of the section.
  267. // Return the number of items when counting.
  268. if (Count)
  269. return Counter;
  270. else
  271. return -1;
  272. }
  273. // A LIST_MODEL for library calls. This list model will return all library
  274. // calls in SourceSection (that point to CurFunction in CurLib if they are
  275. // >= 0).
  276. OFFSET LibCallListModel (SECTION *SourceSection, LIB_CALL **NextItem, LIB_CALL_USER_DATA *UserData, BOOLEAN Count, BOOLEAN Emit)
  277. {
  278. COUNT Counter = 0;
  279. COUNT LibCount = UserData->LibCount;
  280. LIB_DATA *Libs = UserData->Libs;
  281. OFFSET CurLib = UserData->CurLib;
  282. OFFSET CurFunction = UserData->CurFunction;
  283. LIB_CALL *CurLibCall;
  284. if (!Count)
  285. {
  286. // After this enumeration, library calls are supported and do not need any further treatment.
  287. SourceSection->LibCalls.Handled = TRUE;
  288. }
  289. // If no next item is specified yet, this must be the first call to this model
  290. // with this SourceSection and CurFunction. The caller cannot fill *NextItem
  291. // because it does not know how to get the first item.
  292. if (!(*NextItem))
  293. *NextItem = GetFirst (SourceSection->LibCalls);
  294. // Loop until we are done with counting or can return the next library call that is
  295. // important for us.
  296. while ((CurLibCall = *NextItem))
  297. {
  298. *NextItem = GetNext (CurLibCall);
  299. // Returning a location < 0 would be fatal, since it means we are done.
  300. if ((CurLibCall->Location >= 0) && (CurLibCall->Location + CurLibCall->Size <= SourceSection->Size))
  301. {
  302. // Only proceed if we want this library and export.
  303. if ((CurLib < 0) || ((CurLibCall->Library == Libs[CurLib].Lib) && ((CurFunction < 0) || (CurLibCall->Number == CurFunction))))
  304. {
  305. // We can only emit 4-byte library calls.
  306. // Everything else would need to be specified in the user data structure.
  307. if (CurLibCall->Size == 4)
  308. {
  309. // When counting, increment the main counter and all counters
  310. // from the user data structure.
  311. if (Count)
  312. {
  313. Counter++;
  314. {
  315. OFFSET ThisLib;
  316. // Look for the correct library information.
  317. // If CurLib >= 0, we already know the correct one.
  318. for (ThisLib = (CurLib >= 0 ? CurLib : 0); ThisLib < LibCount; ThisLib++)
  319. {
  320. if (Libs[ThisLib].Lib == CurLibCall->Library)
  321. {
  322. if (!(Libs[ThisLib].Functions[CurLibCall->Number].RelocCount++))
  323. {
  324. UserData->LibFunctionCount++;
  325. if (!(Libs[ThisLib].FunctionCount++))
  326. UserData->UsedLibCount++;
  327. }
  328. break;
  329. }
  330. if (CurLib >= 0)
  331. break;
  332. }
  333. }
  334. }
  335. // Otherwise, return the location.
  336. else
  337. {
  338. // If Emit is true, we must emit the fixed offset of the library call
  339. // into the section contents.
  340. if (Emit)
  341. {
  342. // Write our target offset into the section data.
  343. if (SourceSection->Data)
  344. WriteTI4 (*((TI4 *) (SourceSection->Data + CurLibCall->Location)), CurLibCall->FixedOffset);
  345. }
  346. // If we want to get all library calls, we need information about
  347. // this library call.
  348. // Otherwise, this does not have any effect.
  349. UserData->CurLibrary = CurLibCall->Library;
  350. UserData->CurFunction = CurLibCall->Number;
  351. return CurLibCall->Location;
  352. }
  353. }
  354. // Output an error message only when counting, so we get it only once.
  355. else if (Count)
  356. Error (GetFileName (SourceSection, CurLibCall->Location), "Cannot emit %ld byte library call to `%s', function 0x%lX.", (long) CurLibCall->Size, CurLibCall->Library->Name, (long) CurLibCall->Number);
  357. }
  358. }
  359. // Output an error message only when counting, so we get it only once.
  360. else if (Count)
  361. Error (SourceSection->FileName, "Ignoring library call outside of section.");
  362. }
  363. // We have reached the end of the section.
  364. // Return the number of items when counting.
  365. if (Count)
  366. return Counter;
  367. else
  368. return -1;
  369. }