assemble.pas 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005
  1. {
  2. Copyright (c) 1998-2004 by Peter Vreman
  3. This unit handles the assemblerfile write and assembler calls of FPC
  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. {# @abstract(This unit handles the assembler file write and assembler calls of FPC)
  18. Handles the calls to the actual external assemblers, as well as the generation
  19. of object files for smart linking. Also contains the base class for writing
  20. the assembler statements to file.
  21. }
  22. unit assemble;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. SysUtils,
  27. systems,globtype,globals,aasmbase,aasmtai,aasmdata,ogbase,owbase,finput;
  28. const
  29. { maximum of aasmoutput lists there will be }
  30. maxoutputlists = ord(high(tasmlisttype))+1;
  31. { buffer size for writing the .s file }
  32. AsmOutSize=32768*4;
  33. type
  34. TAssembler=class(TObject)
  35. public
  36. {filenames}
  37. path : TPathStr;
  38. name : string;
  39. AsmFileName, { current .s and .o file }
  40. ObjFileName,
  41. ppufilename : TPathStr;
  42. asmprefix : string;
  43. SmartAsm : boolean;
  44. SmartFilesCount,
  45. SmartHeaderCount : longint;
  46. Constructor Create(smart:boolean);virtual;
  47. Destructor Destroy;override;
  48. procedure NextSmartName(place:tcutplace);
  49. procedure MakeObject;virtual;abstract;
  50. end;
  51. {# This is the base class which should be overridden for each each
  52. assembler writer. It is used to actually assembler a file,
  53. and write the output to the assembler file.
  54. }
  55. TExternalAssembler=class(TAssembler)
  56. private
  57. procedure CreateSmartLinkPath(const s:TPathStr);
  58. protected
  59. {outfile}
  60. AsmSize,
  61. AsmStartSize,
  62. outcnt : longint;
  63. outbuf : array[0..AsmOutSize-1] of char;
  64. outfile : file;
  65. ioerror : boolean;
  66. {input source info}
  67. lastfileinfo : tfileposinfo;
  68. infile,
  69. lastinfile : tinputfile;
  70. {last section type written}
  71. lastsectype : TAsmSectionType;
  72. procedure WriteSourceLine(hp: tailineinfo);
  73. procedure WriteTempalloc(hp: tai_tempalloc);
  74. procedure WriteRealConstAsBytes(hp: tai_realconst; const dbdir: string; do_line: boolean);
  75. function single2str(d : single) : string; virtual;
  76. function double2str(d : double) : string; virtual;
  77. function extended2str(e : extended) : string; virtual;
  78. Function DoPipe:boolean;
  79. public
  80. {# Returns the complete path and executable name of the assembler
  81. program.
  82. It first tries looking in the UTIL directory if specified,
  83. otherwise it searches in the free pascal binary directory, in
  84. the current working directory and then in the directories
  85. in the $PATH environment.}
  86. Function FindAssembler:string;
  87. {# Actually does the call to the assembler file. Returns false
  88. if the assembling of the file failed.}
  89. Function CallAssembler(const command:string; const para:TCmdStr):Boolean;
  90. Function DoAssemble:boolean;virtual;
  91. Procedure RemoveAsm;virtual;
  92. Procedure AsmFlush;
  93. Procedure AsmClear;
  94. {# Write a string to the assembler file }
  95. Procedure AsmWrite(const c:char);
  96. Procedure AsmWrite(const s:string);
  97. Procedure AsmWrite(const s:ansistring);
  98. {# Write a string to the assembler file }
  99. Procedure AsmWritePChar(p:pchar);
  100. {# Write a string to the assembler file followed by a new line }
  101. Procedure AsmWriteLn(const c:char);
  102. Procedure AsmWriteLn(const s:string);
  103. Procedure AsmWriteLn(const s:ansistring);
  104. {# Write a new line to the assembler file }
  105. Procedure AsmLn; virtual;
  106. procedure AsmCreate(Aplace:tcutplace);
  107. procedure AsmClose;
  108. {# This routine should be overridden for each assembler, it is used
  109. to actually write the abstract assembler stream to file.}
  110. procedure WriteTree(p:TAsmList);virtual;
  111. {# This routine should be overridden for each assembler, it is used
  112. to actually write all the different abstract assembler streams
  113. by calling for each stream type, the @var(WriteTree) method.}
  114. procedure WriteAsmList;virtual;
  115. {# Constructs the command line for calling the assembler }
  116. function MakeCmdLine: TCmdStr; virtual;
  117. public
  118. Constructor Create(smart:boolean);override;
  119. procedure MakeObject;override;
  120. end;
  121. { TInternalAssembler }
  122. TInternalAssembler=class(TAssembler)
  123. private
  124. FCObjOutput : TObjOutputclass;
  125. FCInternalAr : TObjectWriterClass;
  126. { the aasmoutput lists that need to be processed }
  127. lists : byte;
  128. list : array[1..maxoutputlists] of TAsmList;
  129. { current processing }
  130. currlistidx : byte;
  131. currlist : TAsmList;
  132. procedure WriteStab(p:pchar);
  133. function MaybeNextList(var hp:Tai):boolean;
  134. function SetIndirectToSymbol(hp: Tai; const indirectname: string): Boolean;
  135. function TreePass0(hp:Tai):Tai;
  136. function TreePass1(hp:Tai):Tai;
  137. function TreePass2(hp:Tai):Tai;
  138. procedure writetree;
  139. procedure writetreesmart;
  140. protected
  141. ObjData : TObjData;
  142. ObjOutput : tObjOutput;
  143. property CObjOutput:TObjOutputclass read FCObjOutput write FCObjOutput;
  144. property CInternalAr : TObjectWriterClass read FCInternalAr write FCInternalAr;
  145. public
  146. constructor create(smart:boolean);override;
  147. destructor destroy;override;
  148. procedure MakeObject;override;
  149. end;
  150. TAssemblerClass = class of TAssembler;
  151. Procedure GenerateAsm(smart:boolean);
  152. Procedure OnlyAsm;
  153. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  154. Implementation
  155. uses
  156. {$ifdef hasunix}
  157. unix,
  158. {$endif}
  159. cutils,cfileutl,
  160. {$ifdef memdebug}
  161. cclasses,
  162. {$endif memdebug}
  163. script,fmodule,verbose,
  164. {$if defined(m68k) or defined(arm)}
  165. cpuinfo,
  166. {$endif m68k or arm}
  167. aasmcpu,
  168. owar,owomflib
  169. ;
  170. var
  171. CAssembler : array[tasm] of TAssemblerClass;
  172. function fixline(s:string):string;
  173. {
  174. return s with all leading and ending spaces and tabs removed
  175. }
  176. var
  177. i,j,k : integer;
  178. begin
  179. i:=length(s);
  180. while (i>0) and (s[i] in [#9,' ']) do
  181. dec(i);
  182. j:=1;
  183. while (j<i) and (s[j] in [#9,' ']) do
  184. inc(j);
  185. for k:=j to i do
  186. if s[k] in [#0..#31,#127..#255] then
  187. s[k]:='.';
  188. fixline:=Copy(s,j,i-j+1);
  189. end;
  190. {*****************************************************************************
  191. TAssembler
  192. *****************************************************************************}
  193. Constructor TAssembler.Create(smart:boolean);
  194. begin
  195. { load start values }
  196. AsmFileName:=current_module.AsmFilename;
  197. ObjFileName:=current_module.ObjFileName;
  198. name:=Lower(current_module.modulename^);
  199. path:=current_module.outputpath;
  200. asmprefix := current_module.asmprefix^;
  201. if current_module.outputpath = '' then
  202. ppufilename := ''
  203. else
  204. ppufilename := current_module.ppufilename;
  205. SmartAsm:=smart;
  206. SmartFilesCount:=0;
  207. SmartHeaderCount:=0;
  208. SmartLinkOFiles.Clear;
  209. end;
  210. Destructor TAssembler.Destroy;
  211. begin
  212. end;
  213. procedure TAssembler.NextSmartName(place:tcutplace);
  214. var
  215. s : string;
  216. begin
  217. inc(SmartFilesCount);
  218. if SmartFilesCount>999999 then
  219. Message(asmw_f_too_many_asm_files);
  220. case place of
  221. cut_begin :
  222. begin
  223. inc(SmartHeaderCount);
  224. s:=asmprefix+tostr(SmartHeaderCount)+'h';
  225. end;
  226. cut_normal :
  227. s:=asmprefix+tostr(SmartHeaderCount)+'s';
  228. cut_end :
  229. s:=asmprefix+tostr(SmartHeaderCount)+'t';
  230. end;
  231. AsmFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
  232. ObjFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
  233. { insert in container so it can be cleared after the linking }
  234. SmartLinkOFiles.Insert(ObjFileName);
  235. end;
  236. {*****************************************************************************
  237. TExternalAssembler
  238. *****************************************************************************}
  239. function TExternalAssembler.single2str(d : single) : string;
  240. var
  241. hs : string;
  242. begin
  243. str(d,hs);
  244. { replace space with + }
  245. if hs[1]=' ' then
  246. hs[1]:='+';
  247. single2str:='0d'+hs
  248. end;
  249. function TExternalAssembler.double2str(d : double) : string;
  250. var
  251. hs : string;
  252. begin
  253. str(d,hs);
  254. { replace space with + }
  255. if hs[1]=' ' then
  256. hs[1]:='+';
  257. double2str:='0d'+hs
  258. end;
  259. function TExternalAssembler.extended2str(e : extended) : string;
  260. var
  261. hs : string;
  262. begin
  263. str(e,hs);
  264. { replace space with + }
  265. if hs[1]=' ' then
  266. hs[1]:='+';
  267. extended2str:='0d'+hs
  268. end;
  269. Function TExternalAssembler.DoPipe:boolean;
  270. begin
  271. DoPipe:=(cs_asm_pipe in current_settings.globalswitches) and
  272. (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) and
  273. ((target_asm.id in [as_gas,as_ggas,as_darwin,as_powerpc_xcoff]));
  274. end;
  275. Constructor TExternalAssembler.Create(smart:boolean);
  276. begin
  277. inherited Create(smart);
  278. if SmartAsm then
  279. begin
  280. path:=FixPath(ChangeFileExt(AsmFileName,target_info.smartext),false);
  281. CreateSmartLinkPath(path);
  282. end;
  283. Outcnt:=0;
  284. end;
  285. procedure TExternalAssembler.CreateSmartLinkPath(const s:TPathStr);
  286. procedure DeleteFilesWithExt(const AExt:string);
  287. var
  288. dir : TRawByteSearchRec;
  289. begin
  290. if findfirst(FixPath(s,false)+'*'+AExt,faAnyFile,dir) = 0 then
  291. begin
  292. repeat
  293. DeleteFile(s+source_info.dirsep+dir.name);
  294. until findnext(dir) <> 0;
  295. end;
  296. findclose(dir);
  297. end;
  298. var
  299. hs : TPathStr;
  300. begin
  301. if PathExists(s,false) then
  302. begin
  303. { the path exists, now we clean only all the .o and .s files }
  304. DeleteFilesWithExt(target_info.objext);
  305. DeleteFilesWithExt(target_info.asmext);
  306. end
  307. else
  308. begin
  309. hs:=s;
  310. if hs[length(hs)] in ['/','\'] then
  311. delete(hs,length(hs),1);
  312. {$push} {$I-}
  313. mkdir(hs);
  314. {$pop}
  315. if ioresult<>0 then;
  316. end;
  317. end;
  318. const
  319. lastas : byte=255;
  320. var
  321. LastASBin : TCmdStr;
  322. Function TExternalAssembler.FindAssembler:string;
  323. var
  324. asfound : boolean;
  325. UtilExe : string;
  326. begin
  327. asfound:=false;
  328. if cs_link_on_target in current_settings.globalswitches then
  329. begin
  330. { If linking on target, don't add any path PM }
  331. FindAssembler:=utilsprefix+ChangeFileExt(target_asm.asmbin,target_info.exeext);
  332. exit;
  333. end
  334. else
  335. UtilExe:=utilsprefix+ChangeFileExt(target_asm.asmbin,source_info.exeext);
  336. if lastas<>ord(target_asm.id) then
  337. begin
  338. lastas:=ord(target_asm.id);
  339. { is an assembler passed ? }
  340. if utilsdirectory<>'' then
  341. asfound:=FindFile(UtilExe,utilsdirectory,false,LastASBin);
  342. if not AsFound then
  343. asfound:=FindExe(UtilExe,false,LastASBin);
  344. if (not asfound) and not(cs_asm_extern in current_settings.globalswitches) then
  345. begin
  346. Message1(exec_e_assembler_not_found,LastASBin);
  347. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  348. end;
  349. if asfound then
  350. Message1(exec_t_using_assembler,LastASBin);
  351. end;
  352. FindAssembler:=LastASBin;
  353. end;
  354. Function TExternalAssembler.CallAssembler(const command:string; const para:TCmdStr):Boolean;
  355. var
  356. DosExitCode : Integer;
  357. begin
  358. result:=true;
  359. if (cs_asm_extern in current_settings.globalswitches) then
  360. begin
  361. if SmartAsm then
  362. AsmRes.AddAsmCommand(command,para,Name+'('+TosTr(SmartFilesCount)+')')
  363. else
  364. AsmRes.AddAsmCommand(command,para,name);
  365. exit;
  366. end;
  367. try
  368. FlushOutput;
  369. DosExitCode:=RequotedExecuteProcess(command,para);
  370. if DosExitCode<>0
  371. then begin
  372. Message1(exec_e_error_while_assembling,tostr(dosexitcode));
  373. result:=false;
  374. end;
  375. except on E:EOSError do
  376. begin
  377. Message1(exec_e_cant_call_assembler,tostr(E.ErrorCode));
  378. current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
  379. result:=false;
  380. end;
  381. end;
  382. end;
  383. procedure TExternalAssembler.RemoveAsm;
  384. var
  385. g : file;
  386. begin
  387. if cs_asm_leave in current_settings.globalswitches then
  388. exit;
  389. if cs_asm_extern in current_settings.globalswitches then
  390. AsmRes.AddDeleteCommand(AsmFileName)
  391. else
  392. begin
  393. assign(g,AsmFileName);
  394. {$push} {$I-}
  395. erase(g);
  396. {$pop}
  397. if ioresult<>0 then;
  398. end;
  399. end;
  400. Function TExternalAssembler.DoAssemble:boolean;
  401. begin
  402. DoAssemble:=true;
  403. if DoPipe then
  404. exit;
  405. if not(cs_asm_extern in current_settings.globalswitches) then
  406. begin
  407. if SmartAsm then
  408. begin
  409. if (SmartFilesCount<=1) then
  410. Message1(exec_i_assembling_smart,name);
  411. end
  412. else
  413. Message1(exec_i_assembling,name);
  414. end;
  415. if CallAssembler(FindAssembler,MakeCmdLine) then
  416. RemoveAsm
  417. else
  418. begin
  419. DoAssemble:=false;
  420. GenerateError;
  421. end;
  422. end;
  423. Procedure TExternalAssembler.AsmFlush;
  424. begin
  425. if outcnt>0 then
  426. begin
  427. { suppress i/o error }
  428. {$push} {$I-}
  429. BlockWrite(outfile,outbuf,outcnt);
  430. {$pop}
  431. ioerror:=ioerror or (ioresult<>0);
  432. outcnt:=0;
  433. end;
  434. end;
  435. Procedure TExternalAssembler.AsmClear;
  436. begin
  437. outcnt:=0;
  438. end;
  439. Procedure TExternalAssembler.AsmWrite(const c: char);
  440. begin
  441. if OutCnt+1>=AsmOutSize then
  442. AsmFlush;
  443. OutBuf[OutCnt]:=c;
  444. inc(OutCnt);
  445. inc(AsmSize);
  446. end;
  447. Procedure TExternalAssembler.AsmWrite(const s:string);
  448. begin
  449. if OutCnt+length(s)>=AsmOutSize then
  450. AsmFlush;
  451. Move(s[1],OutBuf[OutCnt],length(s));
  452. inc(OutCnt,length(s));
  453. inc(AsmSize,length(s));
  454. end;
  455. Procedure TExternalAssembler.AsmWrite(const s:ansistring);
  456. var
  457. StartIndex, ToWrite: longint;
  458. begin
  459. if s='' then
  460. exit;
  461. if OutCnt+length(s)>=AsmOutSize then
  462. AsmFlush;
  463. StartIndex:=1;
  464. ToWrite:=length(s);
  465. while ToWrite>AsmOutSize do
  466. begin
  467. Move(s[StartIndex],OutBuf[OutCnt],AsmOutSize);
  468. inc(OutCnt,AsmOutSize);
  469. inc(AsmSize,AsmOutSize);
  470. AsmFlush;
  471. inc(StartIndex,AsmOutSize);
  472. dec(ToWrite,AsmOutSize);
  473. end;
  474. Move(s[StartIndex],OutBuf[OutCnt],ToWrite);
  475. inc(OutCnt,ToWrite);
  476. inc(AsmSize,ToWrite);
  477. end;
  478. procedure TExternalAssembler.AsmWriteLn(const c: char);
  479. begin
  480. AsmWrite(c);
  481. AsmLn;
  482. end;
  483. Procedure TExternalAssembler.AsmWriteLn(const s:string);
  484. begin
  485. AsmWrite(s);
  486. AsmLn;
  487. end;
  488. Procedure TExternalAssembler.AsmWriteLn(const s: ansistring);
  489. begin
  490. AsmWrite(s);
  491. AsmLn;
  492. end;
  493. Procedure TExternalAssembler.AsmWritePChar(p:pchar);
  494. var
  495. i,j : longint;
  496. begin
  497. i:=StrLen(p);
  498. j:=i;
  499. while j>0 do
  500. begin
  501. i:=min(j,AsmOutSize);
  502. if OutCnt+i>=AsmOutSize then
  503. AsmFlush;
  504. Move(p[0],OutBuf[OutCnt],i);
  505. inc(OutCnt,i);
  506. inc(AsmSize,i);
  507. dec(j,i);
  508. p:=pchar(@p[i]);
  509. end;
  510. end;
  511. Procedure TExternalAssembler.AsmLn;
  512. begin
  513. if OutCnt>=AsmOutSize-2 then
  514. AsmFlush;
  515. if (cs_link_on_target in current_settings.globalswitches) then
  516. begin
  517. OutBuf[OutCnt]:=target_info.newline[1];
  518. inc(OutCnt);
  519. inc(AsmSize);
  520. if length(target_info.newline)>1 then
  521. begin
  522. OutBuf[OutCnt]:=target_info.newline[2];
  523. inc(OutCnt);
  524. inc(AsmSize);
  525. end;
  526. end
  527. else
  528. begin
  529. OutBuf[OutCnt]:=source_info.newline[1];
  530. inc(OutCnt);
  531. inc(AsmSize);
  532. if length(source_info.newline)>1 then
  533. begin
  534. OutBuf[OutCnt]:=source_info.newline[2];
  535. inc(OutCnt);
  536. inc(AsmSize);
  537. end;
  538. end;
  539. end;
  540. function TExternalAssembler.MakeCmdLine: TCmdStr;
  541. begin
  542. result:=target_asm.asmcmd;
  543. {$ifdef arm}
  544. if (target_info.system=system_arm_darwin) then
  545. Replace(result,'$ARCH',lower(cputypestr[current_settings.cputype]));
  546. {$endif arm}
  547. if (cs_link_on_target in current_settings.globalswitches) then
  548. begin
  549. Replace(result,'$ASM',maybequoted(ScriptFixFileName(AsmFileName)));
  550. Replace(result,'$OBJ',maybequoted(ScriptFixFileName(ObjFileName)));
  551. end
  552. else
  553. begin
  554. {$ifdef hasunix}
  555. if DoPipe then
  556. Replace(result,'$ASM','')
  557. else
  558. {$endif}
  559. Replace(result,'$ASM',maybequoted(AsmFileName));
  560. Replace(result,'$OBJ',maybequoted(ObjFileName));
  561. end;
  562. if (cs_create_pic in current_settings.moduleswitches) then
  563. Replace(result,'$PIC','-KPIC')
  564. else
  565. Replace(result,'$PIC','');
  566. if (cs_asm_source in current_settings.globalswitches) then
  567. Replace(result,'$NOWARN','')
  568. else
  569. Replace(result,'$NOWARN','-W');
  570. Replace(result,'$EXTRAOPT',asmextraopt);
  571. end;
  572. procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
  573. {$ifdef hasamiga}
  574. var
  575. tempFileName: TPathStr;
  576. {$endif}
  577. begin
  578. if SmartAsm then
  579. NextSmartName(Aplace);
  580. {$ifdef hasamiga}
  581. { on Amiga/MorphOS try to redirect .s files to the T: assign, which is
  582. for temp files, and usually (default setting) located in the RAM: drive.
  583. This highly improves assembling speed for complex projects like the
  584. compiler itself, especially on hardware with slow disk I/O.
  585. Consider this as a poor man's pipe on Amiga, because real pipe handling
  586. would be much more complex and error prone to implement. (KB) }
  587. if (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) then
  588. begin
  589. { try to have an unique name for the .s file }
  590. tempFileName:=HexStr(GetProcessID shr 4,7)+ExtractFileName(AsmFileName);
  591. {$ifndef morphos}
  592. { old Amiga RAM: handler only allows filenames up to 30 char }
  593. if Length(tempFileName) < 30 then
  594. {$endif}
  595. AsmFileName:='T:'+tempFileName;
  596. end;
  597. {$endif}
  598. {$ifdef hasunix}
  599. if DoPipe then
  600. begin
  601. if SmartAsm then
  602. begin
  603. if (SmartFilesCount<=1) then
  604. Message1(exec_i_assembling_smart,name);
  605. end
  606. else
  607. Message1(exec_i_assembling_pipe,AsmFileName);
  608. POpen(outfile,maybequoted(FindAssembler)+' '+MakeCmdLine,'W');
  609. end
  610. else
  611. {$endif}
  612. begin
  613. Assign(outfile,AsmFileName);
  614. {$push} {$I-}
  615. Rewrite(outfile,1);
  616. {$pop}
  617. if ioresult<>0 then
  618. begin
  619. ioerror:=true;
  620. Message1(exec_d_cant_create_asmfile,AsmFileName);
  621. end;
  622. end;
  623. outcnt:=0;
  624. AsmSize:=0;
  625. AsmStartSize:=0;
  626. end;
  627. procedure TExternalAssembler.AsmClose;
  628. var
  629. f : file;
  630. FileAge : longint;
  631. begin
  632. AsmFlush;
  633. {$ifdef hasunix}
  634. if DoPipe then
  635. begin
  636. if PClose(outfile) <> 0 then
  637. GenerateError;
  638. end
  639. else
  640. {$endif}
  641. begin
  642. {Touch Assembler time to ppu time is there is a ppufilename}
  643. if ppufilename<>'' then
  644. begin
  645. Assign(f,ppufilename);
  646. {$push} {$I-}
  647. reset(f,1);
  648. {$pop}
  649. if ioresult=0 then
  650. begin
  651. FileAge := FileGetDate(GetFileHandle(f));
  652. close(f);
  653. reset(outfile,1);
  654. FileSetDate(GetFileHandle(outFile),FileAge);
  655. end;
  656. end;
  657. close(outfile);
  658. end;
  659. end;
  660. procedure TExternalAssembler.WriteSourceLine(hp: tailineinfo);
  661. var
  662. module : tmodule;
  663. begin
  664. { load infile }
  665. if (lastfileinfo.moduleindex<>hp.fileinfo.moduleindex) or
  666. (lastfileinfo.fileindex<>hp.fileinfo.fileindex) then
  667. begin
  668. { in case of a generic the module can be different }
  669. if current_module.unit_index=hp.fileinfo.moduleindex then
  670. module:=current_module
  671. else
  672. module:=get_module(hp.fileinfo.moduleindex);
  673. { during the compilation of the system unit there are cases when
  674. the fileinfo contains just zeros => invalid }
  675. if assigned(module) then
  676. infile:=module.sourcefiles.get_file(hp.fileinfo.fileindex)
  677. else
  678. infile:=nil;
  679. if assigned(infile) then
  680. begin
  681. { open only if needed !! }
  682. if (cs_asm_source in current_settings.globalswitches) then
  683. infile.open;
  684. end;
  685. { avoid unnecessary reopens of the same file !! }
  686. lastfileinfo.fileindex:=hp.fileinfo.fileindex;
  687. lastfileinfo.moduleindex:=hp.fileinfo.moduleindex;
  688. { be sure to change line !! }
  689. lastfileinfo.line:=-1;
  690. end;
  691. { write source }
  692. if (cs_asm_source in current_settings.globalswitches) and
  693. assigned(infile) then
  694. begin
  695. if (infile<>lastinfile) then
  696. begin
  697. AsmWriteLn(target_asm.comment+'['+infile.name+']');
  698. if assigned(lastinfile) then
  699. lastinfile.close;
  700. end;
  701. if (hp.fileinfo.line<>lastfileinfo.line) and
  702. (hp.fileinfo.line<infile.maxlinebuf) then
  703. begin
  704. if (hp.fileinfo.line<>0) and
  705. (infile.linebuf^[hp.fileinfo.line]>=0) then
  706. AsmWriteLn(target_asm.comment+'['+tostr(hp.fileinfo.line)+'] '+
  707. fixline(infile.GetLineStr(hp.fileinfo.line)));
  708. { set it to a negative value !
  709. to make that is has been read already !! PM }
  710. if (infile.linebuf^[hp.fileinfo.line]>=0) then
  711. infile.linebuf^[hp.fileinfo.line]:=-infile.linebuf^[hp.fileinfo.line]-1;
  712. end;
  713. end;
  714. lastfileinfo:=hp.fileinfo;
  715. lastinfile:=infile;
  716. end;
  717. procedure TExternalAssembler.WriteTempalloc(hp: tai_tempalloc);
  718. begin
  719. {$ifdef EXTDEBUG}
  720. if assigned(hp.problem) then
  721. AsmWriteLn(target_asm.comment+'Temp '+tostr(hp.temppos)+','+
  722. tostr(hp.tempsize)+' '+hp.problem^)
  723. else
  724. {$endif EXTDEBUG}
  725. AsmWriteLn(target_asm.comment+'Temp '+tostr(hp.temppos)+','+
  726. tostr(hp.tempsize)+' '+tempallocstr[hp.allocation]);
  727. end;
  728. procedure TExternalAssembler.WriteRealConstAsBytes(hp: tai_realconst; const dbdir: string; do_line: boolean);
  729. var
  730. pdata: pbyte;
  731. index, step, swapmask, count: longint;
  732. ssingle: single;
  733. ddouble: double;
  734. ccomp: comp;
  735. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  736. eextended: extended;
  737. {$endif cpuextended}
  738. begin
  739. if do_line then
  740. begin
  741. case tai_realconst(hp).realtyp of
  742. aitrealconst_s32bit:
  743. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_realconst(hp).value.s32val));
  744. aitrealconst_s64bit:
  745. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_realconst(hp).value.s64val));
  746. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  747. { can't write full 80 bit floating point constants yet on non-x86 }
  748. aitrealconst_s80bit:
  749. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_realconst(hp).value.s80val));
  750. {$endif cpuextended}
  751. aitrealconst_s64comp:
  752. AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_realconst(hp).value.s64compval));
  753. else
  754. internalerror(2014050604);
  755. end;
  756. end;
  757. AsmWrite(dbdir);
  758. { generic float writing code: get start address of value, then write
  759. byte by byte. Can't use fields directly, because e.g ts64comp is
  760. defined as extended on x86 }
  761. case tai_realconst(hp).realtyp of
  762. aitrealconst_s32bit:
  763. begin
  764. ssingle:=single(tai_realconst(hp).value.s32val);
  765. pdata:=@ssingle;
  766. end;
  767. aitrealconst_s64bit:
  768. begin
  769. ddouble:=double(tai_realconst(hp).value.s64val);
  770. pdata:=@ddouble;
  771. end;
  772. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  773. { can't write full 80 bit floating point constants yet on non-x86 }
  774. aitrealconst_s80bit:
  775. begin
  776. eextended:=extended(tai_realconst(hp).value.s80val);
  777. pdata:=@eextended;
  778. end;
  779. {$endif cpuextended}
  780. aitrealconst_s64comp:
  781. begin
  782. ccomp:=comp(tai_realconst(hp).value.s64compval);
  783. pdata:=@ccomp;
  784. end;
  785. else
  786. internalerror(2014051001);
  787. end;
  788. count:=tai_realconst(hp).datasize;
  789. { write bytes in inverse order if source and target endianess don't
  790. match }
  791. if source_info.endian<>target_info.endian then
  792. begin
  793. { go from back to front }
  794. index:=count-1;
  795. step:=-1;
  796. end
  797. else
  798. begin
  799. index:=0;
  800. step:=1;
  801. end;
  802. {$ifdef ARM}
  803. { ARM-specific: low and high dwords of a double may be swapped }
  804. if tai_realconst(hp).formatoptions=fo_hiloswapped then
  805. begin
  806. { only supported for double }
  807. if tai_realconst(hp).datasize<>8 then
  808. internalerror(2014050605);
  809. { switch bit of the index so that the words are written in
  810. the opposite order }
  811. swapmask:=4;
  812. end
  813. else
  814. {$endif ARM}
  815. swapmask:=0;
  816. repeat
  817. AsmWrite(tostr(pdata[index xor swapmask]));
  818. inc(index,step);
  819. dec(count);
  820. if count<>0 then
  821. AsmWrite(',');
  822. until count=0;
  823. { padding }
  824. for count:=tai_realconst(hp).datasize+1 to tai_realconst(hp).savesize do
  825. AsmWrite(',0');
  826. AsmLn;
  827. end;
  828. procedure TExternalAssembler.WriteTree(p:TAsmList);
  829. begin
  830. end;
  831. procedure TExternalAssembler.WriteAsmList;
  832. begin
  833. end;
  834. procedure TExternalAssembler.MakeObject;
  835. begin
  836. AsmCreate(cut_normal);
  837. FillChar(lastfileinfo, sizeof(lastfileinfo), 0);
  838. lastfileinfo.line := -1;
  839. lastinfile := nil;
  840. lastsectype := sec_none;
  841. WriteAsmList;
  842. AsmClose;
  843. if not(ioerror) then
  844. DoAssemble;
  845. end;
  846. {*****************************************************************************
  847. TInternalAssembler
  848. *****************************************************************************}
  849. constructor TInternalAssembler.create(smart:boolean);
  850. begin
  851. inherited create(smart);
  852. ObjOutput:=nil;
  853. ObjData:=nil;
  854. SmartAsm:=smart;
  855. end;
  856. destructor TInternalAssembler.destroy;
  857. begin
  858. if assigned(ObjData) then
  859. ObjData.free;
  860. if assigned(ObjOutput) then
  861. ObjOutput.free;
  862. end;
  863. procedure TInternalAssembler.WriteStab(p:pchar);
  864. function consumecomma(var p:pchar):boolean;
  865. begin
  866. while (p^=' ') do
  867. inc(p);
  868. result:=(p^=',');
  869. inc(p);
  870. end;
  871. function consumenumber(var p:pchar;out value:longint):boolean;
  872. var
  873. hs : string;
  874. len,
  875. code : integer;
  876. begin
  877. value:=0;
  878. while (p^=' ') do
  879. inc(p);
  880. len:=0;
  881. while (p^ in ['0'..'9']) do
  882. begin
  883. inc(len);
  884. hs[len]:=p^;
  885. inc(p);
  886. end;
  887. if len>0 then
  888. begin
  889. hs[0]:=chr(len);
  890. val(hs,value,code);
  891. end
  892. else
  893. code:=-1;
  894. result:=(code=0);
  895. end;
  896. function consumeoffset(var p:pchar;out relocsym:tobjsymbol;out value:longint):boolean;
  897. var
  898. hs : string;
  899. len,
  900. code : integer;
  901. pstart : pchar;
  902. sym : tobjsymbol;
  903. exprvalue : longint;
  904. gotmin,
  905. have_first_symbol,
  906. have_second_symbol,
  907. dosub : boolean;
  908. begin
  909. result:=false;
  910. value:=0;
  911. relocsym:=nil;
  912. gotmin:=false;
  913. have_first_symbol:=false;
  914. have_second_symbol:=false;
  915. repeat
  916. dosub:=false;
  917. exprvalue:=0;
  918. if gotmin then
  919. begin
  920. dosub:=true;
  921. gotmin:=false;
  922. end;
  923. while (p^=' ') do
  924. inc(p);
  925. case p^ of
  926. #0 :
  927. break;
  928. ' ' :
  929. inc(p);
  930. '0'..'9' :
  931. begin
  932. len:=0;
  933. while (p^ in ['0'..'9']) do
  934. begin
  935. inc(len);
  936. hs[len]:=p^;
  937. inc(p);
  938. end;
  939. hs[0]:=chr(len);
  940. val(hs,exprvalue,code);
  941. if code<>0 then
  942. internalerror(200702251);
  943. end;
  944. '.','_',
  945. 'A'..'Z',
  946. 'a'..'z' :
  947. begin
  948. pstart:=p;
  949. while not(p^ in [#0,' ','-','+']) do
  950. inc(p);
  951. len:=p-pstart;
  952. if len>255 then
  953. internalerror(200509187);
  954. move(pstart^,hs[1],len);
  955. hs[0]:=chr(len);
  956. sym:=objdata.symbolref(hs);
  957. { Second symbol? }
  958. if assigned(relocsym) then
  959. begin
  960. if have_second_symbol then
  961. internalerror(2007032201);
  962. have_second_symbol:=true;
  963. if not have_first_symbol then
  964. internalerror(2007032202);
  965. { second symbol should substracted to first }
  966. if not dosub then
  967. internalerror(2007032203);
  968. if (relocsym.objsection<>sym.objsection) then
  969. internalerror(2005091810);
  970. exprvalue:=relocsym.address-sym.address;
  971. relocsym:=nil;
  972. dosub:=false;
  973. end
  974. else
  975. begin
  976. relocsym:=sym;
  977. if assigned(sym.objsection) then
  978. begin
  979. { first symbol should be + }
  980. if not have_first_symbol and dosub then
  981. internalerror(2007032204);
  982. have_first_symbol:=true;
  983. end;
  984. end;
  985. end;
  986. '+' :
  987. begin
  988. { nothing, by default addition is done }
  989. inc(p);
  990. end;
  991. '-' :
  992. begin
  993. gotmin:=true;
  994. inc(p);
  995. end;
  996. else
  997. internalerror(200509189);
  998. end;
  999. if dosub then
  1000. dec(value,exprvalue)
  1001. else
  1002. inc(value,exprvalue);
  1003. until false;
  1004. result:=true;
  1005. end;
  1006. var
  1007. stabstrlen,
  1008. ofs,
  1009. nline,
  1010. nidx,
  1011. nother,
  1012. i : longint;
  1013. stab : TObjStabEntry;
  1014. relocsym : TObjSymbol;
  1015. pstr,
  1016. pcurr,
  1017. pendquote : pchar;
  1018. oldsec : TObjSection;
  1019. begin
  1020. pcurr:=nil;
  1021. pstr:=nil;
  1022. pendquote:=nil;
  1023. relocsym:=nil;
  1024. ofs:=0;
  1025. { Parse string part }
  1026. if (p[0]='"') then
  1027. begin
  1028. pstr:=@p[1];
  1029. { Ignore \" inside the string }
  1030. i:=1;
  1031. while not((p[i]='"') and (p[i-1]<>'\')) and
  1032. (p[i]<>#0) do
  1033. inc(i);
  1034. pendquote:=@p[i];
  1035. pendquote^:=#0;
  1036. pcurr:=@p[i+1];
  1037. if not consumecomma(pcurr) then
  1038. internalerror(200509181);
  1039. end
  1040. else
  1041. pcurr:=p;
  1042. { When in pass 1 then only alloc and leave }
  1043. if ObjData.currpass=1 then
  1044. begin
  1045. ObjData.StabsSec.Alloc(sizeof(TObjStabEntry));
  1046. if assigned(pstr) and (pstr[0]<>#0) then
  1047. ObjData.StabStrSec.Alloc(strlen(pstr)+1);
  1048. end
  1049. else
  1050. begin
  1051. { Stabs format: nidx,nother,nline[,offset] }
  1052. if not consumenumber(pcurr,nidx) then
  1053. internalerror(200509182);
  1054. if not consumecomma(pcurr) then
  1055. internalerror(200509183);
  1056. if not consumenumber(pcurr,nother) then
  1057. internalerror(200509184);
  1058. if not consumecomma(pcurr) then
  1059. internalerror(200509185);
  1060. if not consumenumber(pcurr,nline) then
  1061. internalerror(200509186);
  1062. if consumecomma(pcurr) then
  1063. consumeoffset(pcurr,relocsym,ofs);
  1064. { Generate stab entry }
  1065. if assigned(pstr) and (pstr[0]<>#0) then
  1066. begin
  1067. stabstrlen:=strlen(pstr);
  1068. {$ifdef optimizestabs}
  1069. StabStrEntry:=nil;
  1070. if (nidx=N_SourceFile) or (nidx=N_IncludeFile) then
  1071. begin
  1072. hs:=strpas(pstr);
  1073. StabstrEntry:=StabStrDict.Find(hs);
  1074. if not assigned(StabstrEntry) then
  1075. begin
  1076. StabstrEntry:=TStabStrEntry.Create(hs);
  1077. StabstrEntry:=StabStrSec.Size;
  1078. StabStrDict.Insert(StabstrEntry);
  1079. { generate new stab }
  1080. StabstrEntry:=nil;
  1081. end;
  1082. end;
  1083. if assigned(StabstrEntry) then
  1084. stab.strpos:=StabstrEntry.strpos
  1085. else
  1086. {$endif optimizestabs}
  1087. begin
  1088. stab.strpos:=ObjData.StabStrSec.Size;
  1089. ObjData.StabStrSec.write(pstr^,stabstrlen+1);
  1090. end;
  1091. end
  1092. else
  1093. stab.strpos:=0;
  1094. stab.ntype:=byte(nidx);
  1095. stab.ndesc:=word(nline);
  1096. stab.nother:=byte(nother);
  1097. stab.nvalue:=ofs;
  1098. { Write the stab first without the value field. Then
  1099. write a the value field with relocation }
  1100. oldsec:=ObjData.CurrObjSec;
  1101. ObjData.SetSection(ObjData.StabsSec);
  1102. ObjData.Writebytes(stab,sizeof(TObjStabEntry)-4);
  1103. ObjData.Writereloc(stab.nvalue,4,relocsym,RELOC_ABSOLUTE32);
  1104. ObjData.setsection(oldsec);
  1105. end;
  1106. if assigned(pendquote) then
  1107. pendquote^:='"';
  1108. end;
  1109. function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
  1110. begin
  1111. { maybe end of list }
  1112. while not assigned(hp) do
  1113. begin
  1114. if currlistidx<lists then
  1115. begin
  1116. inc(currlistidx);
  1117. currlist:=list[currlistidx];
  1118. hp:=Tai(currList.first);
  1119. end
  1120. else
  1121. begin
  1122. MaybeNextList:=false;
  1123. exit;
  1124. end;
  1125. end;
  1126. MaybeNextList:=true;
  1127. end;
  1128. function TInternalAssembler.SetIndirectToSymbol(hp: Tai; const indirectname: string): Boolean;
  1129. var
  1130. objsym : TObjSymbol;
  1131. indsym : TObjSymbol;
  1132. begin
  1133. Result:=
  1134. Assigned(hp) and
  1135. (hp.typ=ait_symbol);
  1136. if not Result then
  1137. Exit;
  1138. objsym:=Objdata.SymbolRef(tai_symbol(hp).sym);
  1139. objsym.size:=0;
  1140. indsym := TObjSymbol(ObjData.ObjSymbolList.Find(indirectname));
  1141. if not Assigned(indsym) then
  1142. begin
  1143. { it's possible that indirect symbol is not present in the list,
  1144. so we must create it as undefined }
  1145. indsym:=TObjSymbol.Create(ObjData.ObjSymbolList, indirectname);
  1146. indsym.typ:=AT_NONE;
  1147. indsym.bind:=AB_NONE;
  1148. end;
  1149. objsym.indsymbol:=indsym;
  1150. Result:=true;
  1151. end;
  1152. function TInternalAssembler.TreePass0(hp:Tai):Tai;
  1153. var
  1154. objsym,
  1155. objsymend : TObjSymbol;
  1156. begin
  1157. while assigned(hp) do
  1158. begin
  1159. case hp.typ of
  1160. ait_align :
  1161. begin
  1162. if tai_align_abstract(hp).aligntype>1 then
  1163. begin
  1164. { always use the maximum fillsize in this pass to avoid possible
  1165. short jumps to become out of range }
  1166. Tai_align_abstract(hp).fillsize:=Tai_align_abstract(hp).aligntype;
  1167. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1168. { may need to increase alignment of section }
  1169. if tai_align_abstract(hp).aligntype>ObjData.CurrObjSec.secalign then
  1170. ObjData.CurrObjSec.secalign:=tai_align_abstract(hp).aligntype;
  1171. end
  1172. else
  1173. Tai_align_abstract(hp).fillsize:=0;
  1174. end;
  1175. ait_datablock :
  1176. begin
  1177. {$ifdef USE_COMM_IN_BSS}
  1178. if writingpackages and
  1179. Tai_datablock(hp).is_global then
  1180. ObjData.SymbolDefine(Tai_datablock(hp).sym)
  1181. else
  1182. {$endif USE_COMM_IN_BSS}
  1183. begin
  1184. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1185. ObjData.SymbolDefine(Tai_datablock(hp).sym);
  1186. ObjData.alloc(Tai_datablock(hp).size);
  1187. end;
  1188. end;
  1189. ait_realconst:
  1190. ObjData.alloc(tai_realconst(hp).savesize);
  1191. ait_const:
  1192. begin
  1193. { if symbols are provided we can calculate the value for relative symbols.
  1194. This is required for length calculation of leb128 constants }
  1195. if assigned(tai_const(hp).sym) then
  1196. begin
  1197. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1198. { objsym already defined and there is endsym? }
  1199. if assigned(objsym.objsection) and assigned(tai_const(hp).endsym) then
  1200. begin
  1201. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1202. { objsymend already defined? }
  1203. if assigned(objsymend.objsection) then
  1204. begin
  1205. if objsymend.objsection<>objsym.objsection then
  1206. begin
  1207. { leb128 relative constants are not relocatable, but other types are,
  1208. given that objsym belongs to the current section. }
  1209. if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
  1210. (objsym.objsection<>ObjData.CurrObjSec) then
  1211. InternalError(200404124);
  1212. end
  1213. else
  1214. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1215. end;
  1216. end;
  1217. end;
  1218. ObjData.alloc(tai_const(hp).size);
  1219. end;
  1220. ait_directive:
  1221. begin
  1222. case tai_directive(hp).directive of
  1223. asd_indirect_symbol:
  1224. { handled in TreePass1 }
  1225. ;
  1226. asd_lazy_reference:
  1227. begin
  1228. if tai_directive(hp).name='' then
  1229. Internalerror(2009112101);
  1230. objsym:=ObjData.symbolref(tai_directive(hp).name);
  1231. objsym.bind:=AB_LAZY;
  1232. end;
  1233. asd_reference:
  1234. { ignore for now, but should be added}
  1235. ;
  1236. {$ifdef ARM}
  1237. asd_thumb_func:
  1238. ObjData.ThumbFunc:=true;
  1239. {$endif ARM}
  1240. else
  1241. internalerror(2010011101);
  1242. end;
  1243. end;
  1244. ait_section:
  1245. begin
  1246. ObjData.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secorder);
  1247. Tai_section(hp).sec:=ObjData.CurrObjSec;
  1248. end;
  1249. ait_symbol :
  1250. begin
  1251. { needs extra support in the internal assembler }
  1252. { the value is just ignored }
  1253. {if tai_symbol(hp).has_value then
  1254. internalerror(2009090804); ;}
  1255. ObjData.SymbolDefine(Tai_symbol(hp).sym);
  1256. end;
  1257. ait_label :
  1258. ObjData.SymbolDefine(Tai_label(hp).labsym);
  1259. ait_string :
  1260. ObjData.alloc(Tai_string(hp).len);
  1261. ait_instruction :
  1262. begin
  1263. { reset instructions which could change in pass 2 }
  1264. Taicpu(hp).resetpass2;
  1265. ObjData.alloc(Taicpu(hp).Pass1(ObjData));
  1266. end;
  1267. ait_cutobject :
  1268. if SmartAsm then
  1269. break;
  1270. end;
  1271. hp:=Tai(hp.next);
  1272. end;
  1273. TreePass0:=hp;
  1274. end;
  1275. function TInternalAssembler.TreePass1(hp:Tai):Tai;
  1276. var
  1277. objsym,
  1278. objsymend : TObjSymbol;
  1279. begin
  1280. while assigned(hp) do
  1281. begin
  1282. case hp.typ of
  1283. ait_align :
  1284. begin
  1285. if tai_align_abstract(hp).aligntype>1 then
  1286. begin
  1287. { here we must determine the fillsize which is used in pass2 }
  1288. Tai_align_abstract(hp).fillsize:=align(ObjData.CurrObjSec.Size,Tai_align_abstract(hp).aligntype)-
  1289. ObjData.CurrObjSec.Size;
  1290. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1291. end;
  1292. end;
  1293. ait_datablock :
  1294. begin
  1295. if (oso_data in ObjData.CurrObjSec.secoptions) then
  1296. Message(asmw_e_alloc_data_only_in_bss);
  1297. {$ifdef USE_COMM_IN_BSS}
  1298. if writingpackages and
  1299. Tai_datablock(hp).is_global then
  1300. begin
  1301. objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
  1302. objsym.size:=Tai_datablock(hp).size;
  1303. objsym.bind:=AB_COMMON;
  1304. objsym.alignment:=needtowritealignmentalsoforELF;
  1305. end
  1306. else
  1307. {$endif USE_COMM_IN_BSS}
  1308. begin
  1309. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1310. objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
  1311. objsym.size:=Tai_datablock(hp).size;
  1312. ObjData.alloc(Tai_datablock(hp).size);
  1313. end;
  1314. end;
  1315. ait_realconst:
  1316. ObjData.alloc(tai_realconst(hp).savesize);
  1317. ait_const:
  1318. begin
  1319. { Recalculate relative symbols }
  1320. if assigned(tai_const(hp).sym) and
  1321. assigned(tai_const(hp).endsym) then
  1322. begin
  1323. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1324. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1325. if objsymend.objsection<>objsym.objsection then
  1326. begin
  1327. if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
  1328. (objsym.objsection<>ObjData.CurrObjSec) then
  1329. internalerror(200905042);
  1330. end
  1331. else
  1332. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1333. end;
  1334. ObjData.alloc(tai_const(hp).size);
  1335. end;
  1336. ait_section:
  1337. begin
  1338. { use cached value }
  1339. ObjData.setsection(Tai_section(hp).sec);
  1340. end;
  1341. ait_stab :
  1342. begin
  1343. if assigned(Tai_stab(hp).str) then
  1344. WriteStab(Tai_stab(hp).str);
  1345. end;
  1346. ait_symbol :
  1347. ObjData.SymbolDefine(Tai_symbol(hp).sym);
  1348. ait_symbol_end :
  1349. begin
  1350. objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
  1351. objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
  1352. end;
  1353. ait_label :
  1354. ObjData.SymbolDefine(Tai_label(hp).labsym);
  1355. ait_string :
  1356. ObjData.alloc(Tai_string(hp).len);
  1357. ait_instruction :
  1358. ObjData.alloc(Taicpu(hp).Pass1(ObjData));
  1359. ait_cutobject :
  1360. if SmartAsm then
  1361. break;
  1362. ait_directive :
  1363. begin
  1364. case tai_directive(hp).directive of
  1365. asd_indirect_symbol:
  1366. if tai_directive(hp).name='' then
  1367. Internalerror(2009101103)
  1368. else if not SetIndirectToSymbol(Tai(hp.Previous), tai_directive(hp).name) then
  1369. Internalerror(2009101102);
  1370. asd_lazy_reference:
  1371. { handled in TreePass0 }
  1372. ;
  1373. asd_reference:
  1374. { ignore for now, but should be added}
  1375. ;
  1376. asd_thumb_func:
  1377. { ignore for now, but should be added}
  1378. ;
  1379. else
  1380. internalerror(2010011102);
  1381. end;
  1382. end;
  1383. end;
  1384. hp:=Tai(hp.next);
  1385. end;
  1386. TreePass1:=hp;
  1387. end;
  1388. function TInternalAssembler.TreePass2(hp:Tai):Tai;
  1389. var
  1390. fillbuffer : tfillbuffer;
  1391. leblen : byte;
  1392. lebbuf : array[0..63] of byte;
  1393. objsym,
  1394. ref,
  1395. objsymend : TObjSymbol;
  1396. zerobuf : array[0..63] of byte;
  1397. relative_reloc: boolean;
  1398. pdata : pointer;
  1399. ssingle : single;
  1400. ddouble : double;
  1401. eextended : extended;
  1402. ccomp : comp;
  1403. tmp : word;
  1404. begin
  1405. fillchar(zerobuf,sizeof(zerobuf),0);
  1406. fillchar(objsym,sizeof(objsym),0);
  1407. fillchar(objsymend,sizeof(objsymend),0);
  1408. { main loop }
  1409. while assigned(hp) do
  1410. begin
  1411. case hp.typ of
  1412. ait_align :
  1413. begin
  1414. if tai_align_abstract(hp).aligntype>ObjData.CurrObjSec.secalign then
  1415. InternalError(2012072301);
  1416. if oso_data in ObjData.CurrObjSec.secoptions then
  1417. ObjData.writebytes(Tai_align_abstract(hp).calculatefillbuf(fillbuffer,oso_executable in ObjData.CurrObjSec.secoptions)^,
  1418. Tai_align_abstract(hp).fillsize)
  1419. else
  1420. ObjData.alloc(Tai_align_abstract(hp).fillsize);
  1421. end;
  1422. ait_section :
  1423. begin
  1424. { use cached value }
  1425. ObjData.setsection(Tai_section(hp).sec);
  1426. end;
  1427. ait_symbol :
  1428. begin
  1429. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_symbol(hp).sym));
  1430. end;
  1431. ait_symbol_end :
  1432. begin
  1433. { recalculate size, as some preceding instructions
  1434. could have been changed to smaller size }
  1435. objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
  1436. objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
  1437. end;
  1438. ait_datablock :
  1439. begin
  1440. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_datablock(hp).sym));
  1441. {$ifdef USE_COMM_IN_BSS}
  1442. if not(writingpackages and
  1443. Tai_datablock(hp).is_global) then
  1444. {$endif USE_COMM_IN_BSS}
  1445. begin
  1446. ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
  1447. ObjData.alloc(Tai_datablock(hp).size);
  1448. end;
  1449. end;
  1450. ait_realconst:
  1451. begin
  1452. case tai_realconst(hp).realtyp of
  1453. aitrealconst_s32bit:
  1454. begin
  1455. ssingle:=single(tai_realconst(hp).value.s32val);
  1456. pdata:=@ssingle;
  1457. end;
  1458. aitrealconst_s64bit:
  1459. begin
  1460. ddouble:=double(tai_realconst(hp).value.s64val);
  1461. pdata:=@ddouble;
  1462. end;
  1463. {$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
  1464. { can't write full 80 bit floating point constants yet on non-x86 }
  1465. aitrealconst_s80bit:
  1466. begin
  1467. eextended:=extended(tai_realconst(hp).value.s80val);
  1468. pdata:=@eextended;
  1469. end;
  1470. {$endif cpuextended}
  1471. aitrealconst_s64comp:
  1472. begin
  1473. ccomp:=comp(tai_realconst(hp).value.s64compval);
  1474. pdata:=@ccomp;
  1475. end;
  1476. else
  1477. internalerror(2015030501);
  1478. end;
  1479. ObjData.writebytes(pdata^,tai_realconst(hp).datasize);
  1480. ObjData.writebytes(zerobuf,tai_realconst(hp).savesize-tai_realconst(hp).datasize);
  1481. end;
  1482. ait_string :
  1483. ObjData.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
  1484. ait_const :
  1485. begin
  1486. { Recalculate relative symbols, addresses of forward references
  1487. can be changed in treepass1 }
  1488. relative_reloc:=false;
  1489. if assigned(tai_const(hp).sym) and
  1490. assigned(tai_const(hp).endsym) then
  1491. begin
  1492. objsym:=Objdata.SymbolRef(tai_const(hp).sym);
  1493. objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
  1494. relative_reloc:=(objsym.objsection<>objsymend.objsection);
  1495. Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
  1496. end;
  1497. case tai_const(hp).consttype of
  1498. aitconst_64bit,
  1499. aitconst_32bit,
  1500. aitconst_16bit,
  1501. aitconst_64bit_unaligned,
  1502. aitconst_32bit_unaligned,
  1503. aitconst_16bit_unaligned,
  1504. aitconst_8bit :
  1505. begin
  1506. if assigned(tai_const(hp).sym) and
  1507. not assigned(tai_const(hp).endsym) then
  1508. ObjData.writereloc(Tai_const(hp).symofs,tai_const(hp).size,Objdata.SymbolRef(tai_const(hp).sym),RELOC_ABSOLUTE)
  1509. else if relative_reloc then
  1510. ObjData.writereloc(ObjData.CurrObjSec.size+tai_const(hp).size-objsym.address+tai_const(hp).symofs,tai_const(hp).size,objsymend,RELOC_RELATIVE)
  1511. else
  1512. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1513. end;
  1514. aitconst_rva_symbol :
  1515. begin
  1516. { PE32+? }
  1517. if target_info.system=system_x86_64_win64 then
  1518. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA)
  1519. else
  1520. ObjData.writereloc(Tai_const(hp).symofs,sizeof(pint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA);
  1521. end;
  1522. aitconst_secrel32_symbol :
  1523. begin
  1524. { Required for DWARF2 support under Windows }
  1525. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_SECREL32);
  1526. end;
  1527. {$ifdef i8086}
  1528. aitconst_farptr :
  1529. if assigned(tai_const(hp).sym) and
  1530. not assigned(tai_const(hp).endsym) then
  1531. ObjData.writereloc(Tai_const(hp).symofs,tai_const(hp).size,Objdata.SymbolRef(tai_const(hp).sym),RELOC_FARPTR)
  1532. else if relative_reloc then
  1533. internalerror(2015040601)
  1534. else
  1535. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1536. {$endif i8086}
  1537. {$ifdef arm}
  1538. aitconst_got:
  1539. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOT32);
  1540. {$endif arm}
  1541. aitconst_gotoff_symbol:
  1542. ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF);
  1543. aitconst_uleb128bit,
  1544. aitconst_sleb128bit :
  1545. begin
  1546. if tai_const(hp).consttype=aitconst_uleb128bit then
  1547. leblen:=EncodeUleb128(qword(Tai_const(hp).value),lebbuf)
  1548. else
  1549. leblen:=EncodeSleb128(Tai_const(hp).value,lebbuf);
  1550. if leblen<>tai_const(hp).size then
  1551. internalerror(200709271);
  1552. ObjData.writebytes(lebbuf,leblen);
  1553. end;
  1554. aitconst_darwin_dwarf_delta32,
  1555. aitconst_darwin_dwarf_delta64:
  1556. ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
  1557. aitconst_half16bit,
  1558. aitconst_gs:
  1559. begin
  1560. tmp:=Tai_const(hp).value div 2;
  1561. ObjData.writebytes(tmp,2);
  1562. end;
  1563. else
  1564. internalerror(200603254);
  1565. end;
  1566. end;
  1567. ait_label :
  1568. begin
  1569. { exporting shouldn't be necessary as labels are local,
  1570. but it's better to be on the safe side (PFV) }
  1571. ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_label(hp).labsym));
  1572. end;
  1573. ait_instruction :
  1574. Taicpu(hp).Pass2(ObjData);
  1575. ait_stab :
  1576. WriteStab(Tai_stab(hp).str);
  1577. ait_function_name,
  1578. ait_force_line : ;
  1579. ait_cutobject :
  1580. if SmartAsm then
  1581. break;
  1582. ait_weak:
  1583. begin
  1584. objsym:=ObjData.symbolref(tai_weak(hp).sym^);
  1585. objsym.bind:=AB_WEAK_EXTERNAL;
  1586. end;
  1587. ait_symbolpair:
  1588. begin
  1589. if tai_symbolpair(hp).kind=spk_set then
  1590. begin
  1591. objsym:=ObjData.symbolref(tai_symbolpair(hp).sym^);
  1592. ref:=objdata.symbolref(tai_symbolpair(hp).value^);
  1593. objsym.offset:=ref.offset;
  1594. objsym.objsection:=ref.objsection;
  1595. {$ifdef arm}
  1596. objsym.ThumbFunc:=ref.ThumbFunc;
  1597. {$endif arm}
  1598. end;
  1599. end;
  1600. {$ifndef DISABLE_WIN64_SEH}
  1601. ait_seh_directive :
  1602. tai_seh_directive(hp).generate_code(objdata);
  1603. {$endif DISABLE_WIN64_SEH}
  1604. end;
  1605. hp:=Tai(hp.next);
  1606. end;
  1607. TreePass2:=hp;
  1608. end;
  1609. procedure TInternalAssembler.writetree;
  1610. label
  1611. doexit;
  1612. var
  1613. hp : Tai;
  1614. ObjWriter : TObjectWriter;
  1615. begin
  1616. ObjWriter:=TObjectwriter.create;
  1617. ObjOutput:=CObjOutput.Create(ObjWriter);
  1618. ObjData:=ObjOutput.newObjData(ObjFileName);
  1619. { Pass 0 }
  1620. ObjData.currpass:=0;
  1621. ObjData.createsection(sec_code);
  1622. ObjData.beforealloc;
  1623. { start with list 1 }
  1624. currlistidx:=1;
  1625. currlist:=list[currlistidx];
  1626. hp:=Tai(currList.first);
  1627. while assigned(hp) do
  1628. begin
  1629. hp:=TreePass0(hp);
  1630. MaybeNextList(hp);
  1631. end;
  1632. ObjData.afteralloc;
  1633. { leave if errors have occured }
  1634. if errorcount>0 then
  1635. goto doexit;
  1636. { Pass 1 }
  1637. ObjData.currpass:=1;
  1638. ObjData.resetsections;
  1639. ObjData.beforealloc;
  1640. ObjData.createsection(sec_code);
  1641. { start with list 1 }
  1642. currlistidx:=1;
  1643. currlist:=list[currlistidx];
  1644. hp:=Tai(currList.first);
  1645. while assigned(hp) do
  1646. begin
  1647. hp:=TreePass1(hp);
  1648. MaybeNextList(hp);
  1649. end;
  1650. ObjData.createsection(sec_code);
  1651. ObjData.afteralloc;
  1652. { leave if errors have occured }
  1653. if errorcount>0 then
  1654. goto doexit;
  1655. { Pass 2 }
  1656. ObjData.currpass:=2;
  1657. ObjData.resetsections;
  1658. ObjData.beforewrite;
  1659. ObjData.createsection(sec_code);
  1660. { start with list 1 }
  1661. currlistidx:=1;
  1662. currlist:=list[currlistidx];
  1663. hp:=Tai(currList.first);
  1664. while assigned(hp) do
  1665. begin
  1666. hp:=TreePass2(hp);
  1667. MaybeNextList(hp);
  1668. end;
  1669. ObjData.createsection(sec_code);
  1670. ObjData.afterwrite;
  1671. { don't write the .o file if errors have occured }
  1672. if errorcount=0 then
  1673. begin
  1674. { write objectfile }
  1675. ObjOutput.startobjectfile(ObjFileName);
  1676. ObjOutput.writeobjectfile(ObjData);
  1677. end;
  1678. doexit:
  1679. { Cleanup }
  1680. ObjData.free;
  1681. ObjData:=nil;
  1682. ObjWriter.free;
  1683. end;
  1684. procedure TInternalAssembler.writetreesmart;
  1685. var
  1686. hp : Tai;
  1687. startsectype : TAsmSectiontype;
  1688. place: tcutplace;
  1689. ObjWriter : TObjectWriter;
  1690. startsecname: String;
  1691. startsecorder: TAsmSectionOrder;
  1692. begin
  1693. if not(cs_asm_leave in current_settings.globalswitches) and
  1694. not(af_needar in target_asm.flags) then
  1695. ObjWriter:=CInternalAr.CreateAr(current_module.staticlibfilename)
  1696. else
  1697. ObjWriter:=TObjectwriter.create;
  1698. NextSmartName(cut_normal);
  1699. ObjOutput:=CObjOutput.Create(ObjWriter);
  1700. startsectype:=sec_none;
  1701. startsecname:='';
  1702. startsecorder:=secorder_default;
  1703. { start with list 1 }
  1704. currlistidx:=1;
  1705. currlist:=list[currlistidx];
  1706. hp:=Tai(currList.first);
  1707. while assigned(hp) do
  1708. begin
  1709. ObjData:=ObjOutput.newObjData(ObjFileName);
  1710. { Pass 0 }
  1711. ObjData.currpass:=0;
  1712. ObjData.resetsections;
  1713. ObjData.beforealloc;
  1714. if startsectype<>sec_none then
  1715. ObjData.CreateSection(startsectype,startsecname,startsecorder);
  1716. TreePass0(hp);
  1717. ObjData.afteralloc;
  1718. { leave if errors have occured }
  1719. if errorcount>0 then
  1720. break;
  1721. { Pass 1 }
  1722. ObjData.currpass:=1;
  1723. ObjData.resetsections;
  1724. ObjData.beforealloc;
  1725. if startsectype<>sec_none then
  1726. ObjData.CreateSection(startsectype,startsecname,startsecorder);
  1727. TreePass1(hp);
  1728. ObjData.afteralloc;
  1729. { leave if errors have occured }
  1730. if errorcount>0 then
  1731. break;
  1732. { Pass 2 }
  1733. ObjData.currpass:=2;
  1734. ObjOutput.startobjectfile(ObjFileName);
  1735. ObjData.resetsections;
  1736. ObjData.beforewrite;
  1737. if startsectype<>sec_none then
  1738. ObjData.CreateSection(startsectype,startsecname,startsecorder);
  1739. hp:=TreePass2(hp);
  1740. ObjData.afterwrite;
  1741. { leave if errors have occured }
  1742. if errorcount>0 then
  1743. break;
  1744. { write the current objectfile }
  1745. ObjOutput.writeobjectfile(ObjData);
  1746. ObjData.free;
  1747. ObjData:=nil;
  1748. { end of lists? }
  1749. if not MaybeNextList(hp) then
  1750. break;
  1751. { we will start a new objectfile so reset everything }
  1752. { The place can still change in the next while loop, so don't init }
  1753. { the writer yet (JM) }
  1754. if (hp.typ=ait_cutobject) then
  1755. place := Tai_cutobject(hp).place
  1756. else
  1757. place := cut_normal;
  1758. { avoid empty files }
  1759. startsectype:=sec_none;
  1760. startsecname:='';
  1761. startsecorder:=secorder_default;
  1762. while assigned(hp) and
  1763. (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
  1764. begin
  1765. if Tai(hp).typ=ait_section then
  1766. begin
  1767. startsectype:=Tai_section(hp).sectype;
  1768. startsecname:=Tai_section(hp).name^;
  1769. startsecorder:=Tai_section(hp).secorder;
  1770. end;
  1771. if (Tai(hp).typ=ait_cutobject) then
  1772. place:=Tai_cutobject(hp).place;
  1773. hp:=Tai(hp.next);
  1774. end;
  1775. if not MaybeNextList(hp) then
  1776. break;
  1777. { start next objectfile }
  1778. NextSmartName(place);
  1779. end;
  1780. ObjData.free;
  1781. ObjData:=nil;
  1782. ObjWriter.free;
  1783. end;
  1784. procedure TInternalAssembler.MakeObject;
  1785. var to_do:set of TasmlistType;
  1786. i:TasmlistType;
  1787. procedure addlist(p:TAsmList);
  1788. begin
  1789. inc(lists);
  1790. list[lists]:=p;
  1791. end;
  1792. begin
  1793. to_do:=[low(Tasmlisttype)..high(Tasmlisttype)];
  1794. if usedeffileforexports then
  1795. exclude(to_do,al_exports);
  1796. if not(tf_section_threadvars in target_info.flags) then
  1797. exclude(to_do,al_threadvars);
  1798. for i:=low(TasmlistType) to high(TasmlistType) do
  1799. if (i in to_do) and (current_asmdata.asmlists[i]<>nil) and
  1800. (not current_asmdata.asmlists[i].empty) then
  1801. addlist(current_asmdata.asmlists[i]);
  1802. if SmartAsm then
  1803. writetreesmart
  1804. else
  1805. writetree;
  1806. end;
  1807. {*****************************************************************************
  1808. Generate Assembler Files Main Procedure
  1809. *****************************************************************************}
  1810. Procedure GenerateAsm(smart:boolean);
  1811. var
  1812. a : TAssembler;
  1813. begin
  1814. if not assigned(CAssembler[target_asm.id]) then
  1815. Message(asmw_f_assembler_output_not_supported);
  1816. a:=CAssembler[target_asm.id].Create(smart);
  1817. a.MakeObject;
  1818. a.Free;
  1819. end;
  1820. Procedure OnlyAsm;
  1821. var
  1822. a : TExternalAssembler;
  1823. begin
  1824. a:=TExternalAssembler.Create(false);
  1825. a.DoAssemble;
  1826. a.Free;
  1827. end;
  1828. {*****************************************************************************
  1829. Init/Done
  1830. *****************************************************************************}
  1831. procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
  1832. var
  1833. t : tasm;
  1834. begin
  1835. t:=r.id;
  1836. if assigned(asminfos[t]) then
  1837. writeln('Warning: Assembler is already registered!')
  1838. else
  1839. Getmem(asminfos[t],sizeof(tasminfo));
  1840. asminfos[t]^:=r;
  1841. CAssembler[t]:=c;
  1842. end;
  1843. end.