assemble.pas 65 KB

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