2
0

assemble.pas 68 KB

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