FoxBinaryObjectFile.Mod 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278
  1. MODULE FoxBinaryObjectFile; (** AUTHOR "fof"; PURPOSE "Oberon Compiler Object File Writer"; *)
  2. IMPORT
  3. Scanner := FoxScanner, Basic := FoxBasic, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal, SemanticChecker := FoxSemanticChecker, FingerPrinter := FoxFingerPrinter, Sections := FoxSections,
  4. Streams, D := Debugging, Files, SYSTEM,Strings, BinaryCode := FoxBinaryCode, Log := KernelLog, Diagnostics, SymbolFileFormat := FoxBinarySymbolFile, Options,
  5. Formats := FoxFormats, IntermediateCode := FoxIntermediateCode, Machine
  6. ;
  7. (** Object File Format
  8. ObjectFile = ofFileTag ofNoZeroCompression ofFileVersion
  9. symbolFileSize:RawLInt SymbolFile
  10. Header Entries Commands Pointers Imports VarConstLinks
  11. Links Constants Exports Code Use Types
  12. ExceptionTable PtrsInProcBlock References.
  13. SymbolFile = {Char}:symbolFileSize
  14. Header = refSize:RawLInt numberEntries:RawLInt numberCommands:RawLInt
  15. numberPointers:RawLInt numberTypes:RawLInt numberImports:RawLInt
  16. numberVarConstLinks:RawLInt numberLinks:RawLInt dataSize:RawLInt
  17. constSize:RawLInt codeSize:RawLInt exTableLen:RawLInt numberProcs:RawLInt
  18. maxPtrs:RawLInt typeDescSize:RawLInt crc:RawLInt moduleName:RawString
  19. Entries = 82X:Char { entryOffset:RawNum }:numberEntries
  20. Commands = 83X:Char { firstParTypeOfs:RawNum returnTypeOfs:RawNum
  21. commandName:RawString cmdOffset:RawNum }:numberCommands
  22. Pointers = 84X {pointerOffset:RawNum}:numberPointers
  23. Imports = 85X { moduleName:String }:numberImports
  24. VarConstLinks = 8DX { VarConstLinkEntry }:numberVarConstLinks
  25. VarConstLinkEntry = modNumber:Char entry:RawNum
  26. fixupCount:RawLInt { offset:RawNum }:fixupCount
  27. Links = 86X {LinkEntry}:numberLinks {fixupCount:RawNum}:numberEntries
  28. caseTableSize:RawNum
  29. LinkEntry = moduleNumber:Char entryNumber:Char offset:RawNum
  30. Constants = 87X {character:Char}:constSize
  31. Exports = 88X numberExports:RawLInt {ExportEntry}:numberExpor
  32. ExportEntry = fingerPrint:RawNum offset:RawNum [1X ExportType]
  33. ExportType = reference<0:RawNum
  34. | typeDescriptorOffset:RawNum numberEntries:RawLInt [1X ExportType]
  35. {fingerPrint:RawNum [1X ExportType]}:numberEntries 0X
  36. Code = 89X {character:Char}:codeSize
  37. Use = 08AX {UsedModules} 0X
  38. UsedModules = moduleName:RawString {UsedEntry} 0X
  39. UsedEntry = fingerPrint:RawNum name:RawString number:RawNum [1X UsedType]
  40. UsedType = typeDescOfs:RawNum [fingerPrint:RawNum "@"] 0X
  41. Types = 08BX {TypeEntry}:numberTypes
  42. TypeEntry = recordSize:RawNum entry:RawNum
  43. baseModule:RawNum baseEntry:RawNum
  44. methods:RawNum inheritedMethods:RawNum newMethods:RawNum
  45. pointers:RawNum name:RawString typeDescriptorSize:RawLInt
  46. {method:RawNum entry:RawNum}:newMethods
  47. {offset:RawNum}:pointers
  48. ExceptionTable = 08EX { ExTableEntry }:exTableLength
  49. ExTableEntry = 0FEX pcFrom:RawNum pcTo:RawNum pcHandler:RawNum
  50. PtrsInProcs = 08FX {ProcEntry}:numberProcs
  51. ProcEntry = codeOfs:RawNum beginOfs:RawNum endOfs:RawNum
  52. numberPointers:RawLInt {pointer:RawNum}:numberPointers
  53. References = 08CX RSScope { RSProcedure }
  54. Scope = 0F8X codeOffset:RawNum "$$" {Variable}
  55. Procedure = 0F9X codeOffset:RawNum numberParameters:RawNum ReturnType
  56. level:RawNum 0X name:RawString {Parameter} {Variable}
  57. ReturnType = 0X | BaseType | rfStaticArray | rfDynamicArray | rfOpenArray | rfRecord
  58. Parameter = Variable
  59. Variable = VariableMode Type variableOffset:RawNum variableName:RawString
  60. VariableMode = rfIndirect | rfDirect
  61. Type = BaseType | ArrayType | RecordType
  62. BaseType = rfByte | rfSet | rfAny
  63. | rfBoolean | rfChar8 | rfChar16 | rfChar32
  64. | rfShortint | rfInteger | rfLongint | rfHugeint
  65. | rfReal | rfLongreal |
  66. | rfString | rfPointer | rfAll | rfSame | rfRange
  67. | rfComplex | rfLongcomplex
  68. ArrayType = 80H+BaseType:RawNum dim:RawNum
  69. RecordType = (rfRecord | rfRecordPointer) tdAdr:RawNum
  70. **)
  71. CONST
  72. ofFileTag = 0BBX; (* same constants are defined in Linker and Loader *)
  73. ofNoZeroCompress = 0ADX; (* do. *)
  74. ofFileVersion = SymbolFileFormat.FileVersionCurrent; (* do. *)
  75. ofEUEnd = 0X;
  76. ofEURecord = 1X;
  77. ofEUProcFlag = LONGINT(080000000H);
  78. (** system calls *)
  79. DefaultNofSysCalls = 12;
  80. NewRec = 0; NewArr = 1; NewSys = 2; CaseTable = 3; ProcAddr = 4;
  81. Lock = 5; Unlock = 6; Start = 7; Await = 8; InterfaceLookup = 9;
  82. RegisterInterface = 10; GetProcedure = 11;
  83. Trace = FALSE;
  84. TYPE Name=ARRAY 256 OF CHAR;
  85. ByteArray = POINTER TO ARRAY OF CHAR;
  86. TYPE
  87. ObjectFileFormat*= OBJECT (Formats.ObjectFileFormat)
  88. PROCEDURE & InitObjectFileFormat;
  89. BEGIN
  90. Init; SetExtension(Machine.DefaultObjectFileExtension);
  91. END InitObjectFileFormat;
  92. PROCEDURE Export*(module: Formats.GeneratedModule; symbolFileFormat: Formats.SymbolFileFormat): BOOLEAN;
  93. VAR symbolFile: Files.File; moduleName: SyntaxTree.IdentifierString; fileName: Files.FileName; f: Files.File; w: Files.Writer;
  94. VAR constSize, varSize, codeSize, caseTableSize: LONGINT; VAR const, code: ByteArray;
  95. BEGIN
  96. Global.ModuleFileName(module.module.name,module.module.context,moduleName);
  97. Basic.Concat(fileName,path,moduleName,extension);
  98. IF Trace THEN D.Str("FoxBinaryObjectFile.ObjectFileFormat.Export "); D.Str(moduleName); D.Ln; END;
  99. IF ~(module IS Sections.Module) THEN
  100. diagnostics.Error(module.module.sourceName,Diagnostics.Invalid,Diagnostics.Invalid,"generated module format does not match object file format");
  101. RETURN FALSE;
  102. ELSIF module.findPC # MAX(LONGINT) THEN
  103. MakeSectionOffsets(module(Sections.Module),constSize, varSize, codeSize, caseTableSize,const,code);
  104. RETURN FindPC(module.findPC,module(Sections.Module),diagnostics);
  105. ELSE
  106. WITH module: Sections.Module DO
  107. IF (symbolFileFormat # NIL) & (symbolFileFormat IS SymbolFileFormat.BinarySymbolFile) THEN
  108. symbolFile := symbolFileFormat(SymbolFileFormat.BinarySymbolFile).file;
  109. ELSE
  110. symbolFile := NIL
  111. END;
  112. f := Files.New(fileName);
  113. ASSERT(f # NIL);
  114. (*
  115. IF dump # NIL THEN
  116. dump.String("generated file "); dump.String(fileName); dump.Ln; dump.Update;
  117. END;
  118. *)
  119. NEW(w,f,0);
  120. WriteObjectFile(w,module,symbolFile);
  121. w.Update;
  122. Files.Register(f);
  123. RETURN TRUE
  124. END;
  125. END;
  126. END Export;
  127. PROCEDURE DefineOptions*(options: Options.Options);
  128. BEGIN
  129. options.Add(0X,"objectFileExtension",Options.String);
  130. END DefineOptions;
  131. PROCEDURE GetOptions*(options: Options.Options);
  132. VAR extension: Files.FileName;
  133. BEGIN
  134. IF options.GetString("objectFileExtension",extension) THEN
  135. SetExtension(extension);
  136. END;
  137. END GetOptions;
  138. PROCEDURE DefaultSymbolFileFormat(): Formats.SymbolFileFormat;
  139. BEGIN RETURN SymbolFileFormat.Get();
  140. END DefaultSymbolFileFormat;
  141. PROCEDURE ForceModuleBodies(): BOOLEAN; (* necessary in binary object file format as bodies not recognizable later on *)
  142. BEGIN RETURN TRUE
  143. END ForceModuleBodies;
  144. END ObjectFileFormat;
  145. Fixup = OBJECT
  146. VAR
  147. nextFixup: Fixup;
  148. fixup: BinaryCode.Fixup;
  149. fixupSection: Sections.Section;
  150. END Fixup;
  151. Section=OBJECT (* proprietary format for this object file format *)
  152. VAR
  153. name: Basic.SegmentedName;
  154. symbol: SyntaxTree.Symbol;
  155. entryNumber: LONGINT;
  156. offset: LONGINT;
  157. fixups: Fixup; (* fixups other way round: who references to this section *)
  158. numberFixups: LONGINT;
  159. type: LONGINT;
  160. resolved: BinaryCode.Section;
  161. isCaseTable: BOOLEAN;
  162. referenced: BOOLEAN;
  163. PROCEDURE SetEntryNumber(num: LONGINT);
  164. BEGIN
  165. entryNumber := num
  166. END SetEntryNumber;
  167. PROCEDURE SetSymbol(s: SyntaxTree.Symbol);
  168. BEGIN
  169. symbol := s;
  170. END SetSymbol;
  171. PROCEDURE &Init(CONST name: Basic.SegmentedName);
  172. BEGIN SELF.name := name; fixups := NIL; symbol := NIL; entryNumber := 0; numberFixups := 0;
  173. END Init;
  174. PROCEDURE AddFixup(fixup: BinaryCode.Fixup; fixupSection: Sections.Section);
  175. VAR next: Fixup;
  176. BEGIN
  177. NEW(next);
  178. next.fixup := fixup;
  179. next.fixupSection := fixupSection;
  180. next.nextFixup := fixups;
  181. fixups := next;
  182. INC(numberFixups);
  183. END AddFixup;
  184. PROCEDURE Dump(w: Streams.Writer);
  185. VAR fixup: Fixup; n: Basic.SegmentedName;
  186. BEGIN
  187. Basic.WriteSegmentedName(w,name);
  188. w.String(" : ");
  189. IF symbol = NIL THEN w.String("NIL")
  190. ELSE Global.GetSymbolSegmentedName(symbol, n); Basic.WriteSegmentedName(w,n);
  191. END;
  192. IF referenced THEN w.String("(referenced)") END;
  193. w.Ln;
  194. w.String("no fixups:"); w.Int(numberFixups,1); w.Ln;
  195. fixup := fixups;
  196. WHILE fixup # NIL DO
  197. w.String("fixup in "); Basic.WriteSegmentedName(w,fixups.fixupSection.name); w.String(" "); fixup.fixup.Dump(w); w.Ln;
  198. fixup := fixup.nextFixup;
  199. END;
  200. END Dump;
  201. END Section;
  202. SectionNameLookup = OBJECT(Basic.HashTableSegmentedName); (* SyntaxTree.Symbol _> Symbol *)
  203. PROCEDURE GetSection(CONST name: Basic.SegmentedName):Section;
  204. VAR p: ANY;
  205. BEGIN
  206. p := Get(name);
  207. IF p # NIL THEN RETURN p(Section) ELSE RETURN NIL END;
  208. END GetSection;
  209. PROCEDURE PutSection(CONST name:Basic.SegmentedName; section: Section);
  210. BEGIN
  211. Put(name, section);
  212. END PutSection;
  213. END SectionNameLookup;
  214. SymbolLookup = OBJECT(Basic.HashTable); (* SyntaxTree.Symbol _> Symbol *)
  215. PROCEDURE GetSection(s: SyntaxTree.Symbol):Section;
  216. VAR p: ANY;
  217. BEGIN
  218. p := Get(s);
  219. IF p # NIL THEN RETURN p(Section) ELSE RETURN NIL END;
  220. END GetSection;
  221. PROCEDURE PutSection(symbol: SyntaxTree.Symbol; section: Section);
  222. BEGIN
  223. Put(symbol, section);
  224. END PutSection;
  225. END SymbolLookup;
  226. SectionList= OBJECT (Basic.List)
  227. VAR
  228. lookup: SectionNameLookup;
  229. symbolLookup: SymbolLookup;
  230. PROCEDURE &Init;
  231. BEGIN
  232. InitList(16);
  233. NEW(lookup,16);
  234. NEW(symbolLookup, 16);
  235. END Init;
  236. PROCEDURE AddSection(name: Basic.SegmentedName): Section;
  237. VAR section: Section;
  238. BEGIN
  239. section := lookup.GetSection(name);
  240. IF section = NIL THEN
  241. NEW(section, name);
  242. lookup.Put(name, section);
  243. Add(section);
  244. END;
  245. RETURN section
  246. END AddSection;
  247. PROCEDURE BySymbol(symbol: SyntaxTree.Symbol): Section;
  248. VAR name: Basic.SegmentedName;
  249. BEGIN
  250. RETURN symbolLookup.GetSection(symbol);
  251. END BySymbol;
  252. PROCEDURE GetSection(i: LONGINT): Section;
  253. VAR any: ANY;
  254. BEGIN
  255. any := Get(i);
  256. RETURN any(Section)
  257. END GetSection;
  258. PROCEDURE Dump(w: Streams.Writer);
  259. VAR section: Section; i: LONGINT;
  260. BEGIN
  261. FOR i := 0 TO Length()-1 DO
  262. section := GetSection(i); section.Dump(w);
  263. END;
  264. END Dump;
  265. END SectionList;
  266. VAR SysCallMap : ARRAY DefaultNofSysCalls OF CHAR;
  267. (*
  268. PROCEDURE GetFixups(module: Sections.Module; symbol: Sections.Section; VAR first: Fixup): LONGINT;
  269. VAR temp: Fixup; fixup: BinaryCode.Fixup; nr :LONGINT;
  270. (* only regular sections *)
  271. PROCEDURE DoSections(sectionList: Sections.SectionList);
  272. VAR
  273. i: LONGINT;
  274. section: Sections.Section;
  275. BEGIN
  276. FOR i := 0 TO sectionList.Length() - 1 DO
  277. section := sectionList.GetSection(i);
  278. IF (section.type # Sections.InlineCodeSection) & (section.type # Sections.InitCodeSection) THEN
  279. fixup := section(IntermediateCode.Section).resolved.fixupList.firstFixup;
  280. WHILE (fixup # NIL) DO
  281. IF (fixup.symbol = symbol.name) THEN
  282. INC(nr);
  283. NEW(temp);
  284. temp.fixup := fixup;
  285. temp.fixupSection := section;
  286. temp.nextFixup := first;
  287. first := temp;
  288. END;
  289. fixup := fixup.nextFixup;
  290. END
  291. END
  292. END;
  293. END DoSections;
  294. BEGIN
  295. first := NIL; nr := 0;
  296. DoSections(module.allSections); (* only regular sections *)
  297. (* Sections(module.caseTables.first); *)
  298. RETURN nr
  299. END GetFixups;
  300. *)
  301. PROCEDURE FindPC(pc: LONGINT; module: Sections.Module; diagnostics: Diagnostics.Diagnostics): BOOLEAN;
  302. VAR
  303. section:Sections.Section; binarySection: BinaryCode.Section; label: BinaryCode.LabelList;
  304. i: LONGINT;
  305. BEGIN
  306. FOR i := 0 TO module.allSections.Length() - 1 DO
  307. section := module.allSections.GetSection(i);
  308. binarySection := section(IntermediateCode.Section).resolved;
  309. IF ((section.offset ) <= pc) & (pc < (section.offset +binarySection.pc )) THEN
  310. label := binarySection.labels;
  311. WHILE (label # NIL) & ((label.offset + section.offset ) > pc) DO
  312. label := label.prev;
  313. END;
  314. IF label # NIL THEN
  315. diagnostics.Information(module.module.sourceName,label.position,Diagnostics.Invalid," pc position");
  316. RETURN TRUE
  317. END;
  318. END
  319. END;
  320. diagnostics.Error(module.module.sourceName,Diagnostics.Invalid,Diagnostics.Invalid," could not locate pc");
  321. RETURN FALSE
  322. END FindPC;
  323. PROCEDURE MakeSectionOffsets(module: Sections.Module; VAR constSize, varSize, codeSize, caseTableSize: LONGINT; VAR const, code: ByteArray);
  324. VAR symbolName: SyntaxTree.IdentifierString; symbol: SyntaxTree.Symbol; binarySection: BinaryCode.Section;
  325. pc: LONGINT;
  326. (*
  327. PROCEDURE InModule(s: Sections.Section):BOOLEAN;
  328. VAR
  329. section: Sections.Section;
  330. i: LONGINT;
  331. BEGIN
  332. FOR i := 0 TO module.allSections.Length() - 1 DO
  333. section := module.allSections.GetSection(i);
  334. IF section = s THEN RETURN TRUE END
  335. END;
  336. RETURN FALSE
  337. END InModule;
  338. *)
  339. PROCEDURE FixupSections;
  340. VAR
  341. section: Sections.Section; dest, i: LONGINT; fixup,next: BinaryCode.Fixup; symbol: Sections.Section;
  342. BEGIN
  343. FOR i := 0 TO module.allSections.Length() - 1 DO
  344. section := module.allSections.GetSection(i);
  345. binarySection := section(IntermediateCode.Section).resolved;
  346. fixup := binarySection.fixupList.firstFixup;
  347. binarySection.fixupList.InitFixupList; (* remove all fixups from list *)
  348. WHILE fixup # NIL DO
  349. next := fixup.nextFixup;
  350. symbol := module.allSections.FindByName(fixup.symbol.name);
  351. IF symbol # NIL THEN
  352. symbol.SetReferenced(TRUE);
  353. ELSIF Trace THEN
  354. D.String("fixup symbol not found: "); Basic.WriteSegmentedName(D.Log, fixup.symbol.name); D.Ln;
  355. END;
  356. IF (fixup.mode = BinaryCode.Relative) & (symbol # NIL) THEN (* relative offset within module *)
  357. dest := (symbol.offset + fixup.displacement) - (section.offset + fixup.offset);
  358. ASSERT(fixup.symbolOffset = 0);
  359. binarySection.PutDWordAt(fixup.offset, dest);
  360. (* fixup done, does not need to be put back to list *)
  361. ELSIF (fixup.mode = BinaryCode.Absolute) & (symbol # NIL) THEN (* absolute offset within module *)
  362. dest := symbol.offset + fixup.displacement;
  363. binarySection.PutDWordAt(fixup.offset, dest);
  364. binarySection.fixupList.AddFixup(fixup); (* (re-)insert fixup into fixup list *)
  365. ELSIF (fixup.mode = BinaryCode.Absolute) THEN (* absolute fixup on imported symbol *)
  366. dest := fixup.displacement;
  367. binarySection.PutDWordAt(fixup.offset, dest);
  368. binarySection.fixupList.AddFixup(fixup); (* (re-)insert fixup into fixup list *)
  369. ELSE binarySection.fixupList.AddFixup(fixup); (* keep fixup as is: relative fixup on imported symbol *)
  370. END;
  371. fixup := next;
  372. END
  373. END;
  374. END FixupSections;
  375. PROCEDURE Copy(section: BinaryCode.Section; to: ByteArray; offset: LONGINT);
  376. VAR i,ofs: LONGINT;
  377. BEGIN
  378. ofs := (offset );
  379. FOR i := 0 TO ((section.pc-1) ) DO
  380. to[i+ofs] := CHR(section.os.bits.GetBits(i*8,8));
  381. END;
  382. END Copy;
  383. (* only regular sections *)
  384. PROCEDURE FirstOffsets(sectionList: Sections.SectionList);
  385. VAR
  386. section: Sections.Section;
  387. i: LONGINT;
  388. BEGIN
  389. FOR i := 0 TO sectionList.Length() - 1 DO
  390. section := sectionList.GetSection(i);
  391. binarySection := section(IntermediateCode.Section).resolved;
  392. symbol := section.symbol;
  393. IF symbol # NIL THEN
  394. symbol.GetName(symbolName);
  395. IF section.symbol = module.module.moduleScope.bodyProcedure THEN
  396. section.SetOffset(0); INC(codeSize,binarySection.pc);
  397. ELSIF symbolName = "@moduleSelf" THEN
  398. section.SetOffset(0); INC(constSize,binarySection.pc);
  399. END;
  400. END
  401. END;
  402. END FirstOffsets;
  403. (* note: if 'caseSections' is TRUE, only case table sections are processed, otherwise only regular sections (imported symbol/system call sections are never processed) *)
  404. PROCEDURE SetOffsets(sectionList: Sections.SectionList; caseTables: BOOLEAN);
  405. VAR
  406. section: Sections.Section;
  407. i: LONGINT;
  408. BEGIN
  409. FOR i := 0 TO sectionList.Length() - 1 DO
  410. section := sectionList.GetSection(i);
  411. IF section.isCaseTable = caseTables THEN
  412. binarySection := section(IntermediateCode.Section).resolved;
  413. symbol := section.symbol;
  414. IF symbol # NIL THEN
  415. symbol.GetName(symbolName);
  416. ELSE symbolName := "";
  417. END;
  418. IF section.symbol = module.module.moduleScope.bodyProcedure THEN
  419. ELSIF symbolName = "@moduleSelf" THEN
  420. ELSIF section.type = Sections.ConstSection THEN
  421. IF binarySection.os.alignment # 0 THEN
  422. INC(constSize,(-constSize) MOD binarySection.os.alignment);
  423. END;
  424. section.SetOffset(constSize); INC(constSize,binarySection.pc); (* global constants: positive offset *)
  425. ELSIF (section.type = Sections.CodeSection) OR (section.type = Sections.BodyCodeSection) THEN
  426. section.SetOffset(codeSize); INC(codeSize, binarySection.pc);
  427. ELSIF section.type = Sections.VarSection THEN
  428. INC(varSize, binarySection.pc);
  429. IF binarySection.os.alignment # 0 THEN
  430. INC(varSize,(-varSize) MOD binarySection.os.alignment);
  431. END;
  432. section.SetOffset(-varSize); (* global variables: negative offset *)
  433. END
  434. END;
  435. END;
  436. END SetOffsets;
  437. (* note: if 'caseSections' is TRUE, only case table sections are processed, otherwise only regular sections (imported symbol/system call sections are never processed) *)
  438. PROCEDURE CopySections(sectionList: Sections.SectionList);
  439. VAR
  440. section: Sections.Section;
  441. i: LONGINT;
  442. BEGIN
  443. FOR i := 0 TO sectionList.Length() - 1 DO
  444. section := sectionList.GetSection(i);
  445. binarySection := section(IntermediateCode.Section).resolved;
  446. IF section.type = Sections.ConstSection THEN
  447. Copy(binarySection,const,section.offset);
  448. ELSIF (section.type = Sections.CodeSection) OR (section.type = Sections.BodyCodeSection) THEN
  449. Copy(binarySection,code,section.offset);
  450. END
  451. END;
  452. END CopySections;
  453. BEGIN
  454. FirstOffsets(module.allSections); (* regular sections *)
  455. SetOffsets(module.allSections,FALSE); (* regular sections *)
  456. pc := constSize;
  457. SetOffsets(module.allSections, TRUE); (* case table sections *)
  458. caseTableSize := (constSize -pc) DIV 4 ;
  459. FixupSections;
  460. NEW(const,constSize ); NEW(code,codeSize );
  461. CopySections(module.allSections); (* regular sections *)
  462. END MakeSectionOffsets;
  463. PROCEDURE WriteObjectFile*(w:Streams.Writer; module: Sections.Module; symbolFile: Files.File);
  464. VAR moduleName: Name; refSize, numberEntries,numberCommands,numberPointers,numberTypes,numberImports,
  465. numberVarConstLinks,numberLinks: LONGINT;
  466. dataSize,constSize,codeSize,caseTableSize: LONGINT;
  467. exTableLen,numberProcs,maxPtrs,typeDescSize: LONGINT; headerPos,endPos: LONGINT;
  468. moduleScope: SyntaxTree.ModuleScope; fingerprinter: FingerPrinter.FingerPrinter;
  469. const, code: ByteArray; procedureFixupOffset : LONGINT;
  470. crc: LONGINT; crc32: Basic.CRC32Stream;
  471. symbols, importedSymbols: SectionList; (* list of sections with fixups in the other direction, needed for this particular object file format *)
  472. PROCEDURE RawLIntAt(at: LONGINT; val: LONGINT);
  473. VAR pos: LONGINT;
  474. BEGIN
  475. pos := w.Pos(); w.SetPos(at); w.RawLInt(val); w.SetPos(pos);
  476. END RawLIntAt;
  477. PROCEDURE AppendFile(f: Files.File; to: Streams.Writer);
  478. VAR buffer: ARRAY 1024 OF CHAR; r: Files.Reader; read: LONGINT;
  479. BEGIN
  480. Files.OpenReader(r, f, 0);
  481. REPEAT
  482. r.Bytes(buffer, 0, 1024, read);
  483. to.Bytes(buffer, 0, read)
  484. UNTIL read # 1024
  485. END AppendFile;
  486. PROCEDURE SymbolFile; (* write symbol file *)
  487. BEGIN
  488. IF Trace THEN D.Str("FoxObjectFile.SymbolFile Length at pos "); D.Int(w.Pos(),1); D.Ln END;
  489. IF symbolFile # NIL THEN
  490. w.RawLInt(symbolFile.Length()); (* could also be patched later, if length was not known here *)
  491. IF Trace THEN D.Str("FoxObjectFile.SymbolFile at pos "); D.Int(w.Pos(),1); D.Ln END;
  492. AppendFile(symbolFile,w);
  493. ELSE
  494. IF Trace THEN D.Str("FoxObjectFile.SymbolFile: no symbol file!"); D.Ln END;
  495. w.RawLInt(0);
  496. END;
  497. END SymbolFile;
  498. (* Header =
  499. refSize:4 numberEntries:4 numberCommands:4 numberPointers:4
  500. numberTypes:4 numberImports:4 numberVarConstLinks:4 numberLinks:4
  501. dataSize:4 constSize:4 codeSize:4 exTableLen:4 numberProcs:4 maxPtrs:4
  502. typeDescSize:4 crc:4 moduleName:String
  503. *)
  504. PROCEDURE Header;
  505. BEGIN
  506. headerPos := w.Pos();
  507. w.RawLInt(refSize);
  508. w.RawLInt(numberEntries);
  509. w.RawLInt(numberCommands);
  510. w.RawLInt(numberPointers);
  511. w.RawLInt(numberTypes);
  512. w.RawLInt(numberImports);
  513. w.RawLInt(numberVarConstLinks);
  514. w.RawLInt(numberLinks);
  515. w.RawLInt((dataSize )); ASSERT(dataSize >= 0);
  516. w.RawLInt((constSize ));
  517. w.RawLInt((codeSize ));
  518. w.RawLInt(exTableLen);
  519. w.RawLInt(numberProcs);
  520. w.RawLInt(maxPtrs);
  521. w.RawLInt(typeDescSize);
  522. w.RawLInt(crc);
  523. IF Trace THEN D.Str("moduleName:"); D.Str(moduleName); D.Ln; END;
  524. w.RawString(moduleName);
  525. END Header;
  526. (* Entries = 82X {entryOffset}:numberEntries *)
  527. PROCEDURE Entries;
  528. VAR
  529. p: Section; procedure: SyntaxTree.Procedure; procedureType : SyntaxTree.ProcedureType;
  530. prev,tail: Fixup; firstOffset: LONGINT; name: SyntaxTree.IdentifierString; fixups, i: LONGINT; fixup: Fixup;
  531. CONST
  532. FixupSentinel = LONGINT(0FFFFFFFFH);
  533. PROCEDURE FixupList(l,prev: Fixup; VAR tail: Fixup);
  534. (* Insert fixup list into code *)
  535. VAR offset: LONGINT;
  536. PROCEDURE Put32(offset: LONGINT; number: LONGINT);
  537. BEGIN
  538. code[offset] := CHR(number MOD 256);
  539. INC(offset); number := number DIV 256;
  540. code[offset] := CHR(number MOD 256);
  541. INC(offset); number := number DIV 256;
  542. code[offset] := CHR(number MOD 256);
  543. INC(offset); number := number DIV 256;
  544. code[offset] := CHR(number MOD 256);
  545. END Put32;
  546. BEGIN
  547. tail := NIL;
  548. IF l # NIL THEN
  549. IF prev # NIL THEN
  550. Put32((prev.fixupSection.offset +prev.fixup.offset ),(l.fixupSection.offset + l.fixup.offset ));
  551. END;
  552. offset := (l.fixupSection.offset + l.fixup.offset );
  553. tail := l;
  554. l := l.nextFixup;
  555. WHILE (l# NIL) DO
  556. Put32(offset,(l.fixupSection.offset + l.fixup.offset ));
  557. offset := (l.fixupSection.offset + l.fixup.offset );
  558. tail := l;
  559. l := l.nextFixup;
  560. END;
  561. Put32(offset,FixupSentinel);
  562. END;
  563. END FixupList;
  564. BEGIN
  565. w.Char(82X);
  566. numberEntries := 0; tail := NIL; prev := NIL; firstOffset := -1;
  567. FOR i := 0 TO symbols.Length() - 1 DO
  568. p := symbols.GetSection(i);
  569. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) & ~p.symbol(SyntaxTree.Procedure).isInline THEN
  570. fixup := p.fixups;
  571. p.symbol.GetName(name); (*debugging*)
  572. procedure := p.symbol(SyntaxTree.Procedure);
  573. procedureType := procedure.type(SyntaxTree.ProcedureType);
  574. (* entry for public procedures and all methods *)
  575. IF (procedure.access*SyntaxTree.Public # {}) OR (procedureType.isDelegate) OR (fixup # NIL) THEN
  576. p.SetEntryNumber(numberEntries);
  577. w.RawNum((p.offset )); INC(numberEntries);
  578. FixupList(fixup, prev, tail); (* absolute fixups, relative procedure fixups have already been done during code generation *)
  579. IF tail # NIL THEN
  580. prev := tail
  581. END;
  582. IF (fixup # NIL) & (firstOffset = -1) THEN
  583. firstOffset := (fixup.fixupSection.offset + fixup.fixup.offset );
  584. END
  585. END
  586. END
  587. END;
  588. procedureFixupOffset := firstOffset;
  589. END Entries;
  590. (* Commands =
  591. 83X {firstParTypeOffset:Num returnParTypeOffset:Num cmdName:String cmdOffset:Num}:numberCommands
  592. *)
  593. PROCEDURE Commands;
  594. VAR
  595. procedure : SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  596. p: Section; name: Name; numberParameters, i: LONGINT;
  597. (* Returns TRUE if the built-in function GETPROCEDURE can be used with this procedure type *)
  598. PROCEDURE GetProcedureAllowed() : BOOLEAN;
  599. PROCEDURE TypeAllowed(type : SyntaxTree.Type) : BOOLEAN;
  600. BEGIN
  601. RETURN
  602. (type = NIL) OR
  603. (type.resolved IS SyntaxTree.RecordType) OR
  604. (type.resolved IS SyntaxTree.PointerType) & (type.resolved(SyntaxTree.PointerType).pointerBase.resolved IS SyntaxTree.RecordType);
  605. END TypeAllowed;
  606. BEGIN
  607. numberParameters := procedureType.numberParameters;
  608. RETURN
  609. (numberParameters = 0) & TypeAllowed(procedureType.returnType) OR
  610. (numberParameters = 1) & TypeAllowed(procedureType.firstParameter.type) & TypeAllowed(procedureType.returnType) OR
  611. (numberParameters = 1) & (procedureType.firstParameter.type.resolved IS SyntaxTree.AnyType) & (procedureType.returnType # NIL) & (procedureType.returnType.resolved IS SyntaxTree.AnyType);
  612. END GetProcedureAllowed;
  613. PROCEDURE WriteType(type : SyntaxTree.Type);
  614. VAR typeDeclaration: SyntaxTree.TypeDeclaration; section: Section;
  615. name: SyntaxTree.IdentifierString;
  616. BEGIN
  617. IF type = NIL THEN
  618. w.RawNum(0);
  619. IF Trace THEN
  620. D.String(", t="); D.Int(0,1);
  621. END;
  622. ELSIF (type.resolved IS SyntaxTree.AnyType) OR (type.resolved IS SyntaxTree.ObjectType) THEN
  623. w.RawNum(1);
  624. IF Trace THEN
  625. D.String(", t="); D.Int(1,1);
  626. END;
  627. ELSE
  628. type := type.resolved;
  629. IF type IS SyntaxTree.PointerType THEN
  630. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  631. END;
  632. typeDeclaration := type.typeDeclaration; (* must be non-nil *)
  633. typeDeclaration.GetName(name);
  634. section := symbols.BySymbol(type.typeDeclaration);
  635. ASSERT(section # NIL);
  636. w.RawNum((section.offset )); (* type descriptor section offset *)
  637. IF Trace THEN
  638. D.String(", t="); D.Int(section.offset ,1);
  639. END;
  640. END;
  641. END WriteType;
  642. BEGIN
  643. w.Char(83X);
  644. FOR i := 0 TO symbols.Length() - 1 DO
  645. p := symbols.GetSection(i);
  646. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) THEN
  647. procedure := p.symbol(SyntaxTree.Procedure);
  648. procedureType := procedure.type(SyntaxTree.ProcedureType);
  649. IF (SyntaxTree.PublicWrite IN procedure.access) & ~(procedure.isInline) & ~(procedureType.isDelegate) & GetProcedureAllowed() THEN
  650. procedure.GetName(name);
  651. IF Trace THEN
  652. D.Str("Command : "); D.Str(name); D.Str(" @ "); D.Int(p.offset ,1);
  653. END;
  654. numberParameters := procedureType.numberParameters;
  655. (* offset of type of first parameter *)
  656. IF (numberParameters = 0 ) THEN WriteType(NIL)
  657. ELSE WriteType(procedureType.firstParameter.type)
  658. END;
  659. (* offset of type of return parameter *)
  660. WriteType(procedureType.returnType);
  661. (* command name *)
  662. w.RawString(name);
  663. (* command code offset *)
  664. w.RawNum((p.offset ));
  665. INC(numberCommands);
  666. IF Trace THEN
  667. D.Ln
  668. END
  669. END
  670. END
  671. END
  672. END Commands;
  673. (* OutPointers delivers
  674. {pointerOffset}
  675. *)
  676. PROCEDURE OutPointers(offset: LONGINT; type: SyntaxTree.Type; VAR numberPointers: LONGINT);
  677. VAR variable: SyntaxTree.Variable; i,n,size: LONGINT; base: SyntaxTree.Type;
  678. BEGIN
  679. type := type.resolved;
  680. IF type IS SyntaxTree.AnyType THEN
  681. ASSERT(offset MOD 4 = 0);
  682. w.RawNum((offset )); INC(numberPointers);
  683. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  684. ELSIF type IS SyntaxTree.PointerType THEN
  685. ASSERT(offset MOD 4 = 0);
  686. w.RawNum((offset )); INC(numberPointers);
  687. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1);D.Ln; END;
  688. ELSIF (type IS SyntaxTree.ProcedureType) & (type(SyntaxTree.ProcedureType).isDelegate) THEN
  689. ASSERT(offset MOD 4 = 0);
  690. w.RawNum((offset )+module.system.addressSize DIV 8 ); INC(numberPointers);
  691. IF Trace THEN D.Str("ptr at offset="); D.Int(offset+module.system.addressSize DIV 8,1); END;
  692. ELSIF (type IS SyntaxTree.RecordType) THEN
  693. (* never treat a record like a pointer, even if the pointer field is set! *)
  694. WITH type: SyntaxTree.RecordType DO
  695. base := type.GetBaseRecord();
  696. IF base # NIL THEN
  697. OutPointers(offset,base,numberPointers);
  698. END;
  699. variable := type.recordScope.firstVariable;
  700. WHILE(variable # NIL) DO
  701. IF ~(variable.untraced) THEN
  702. OutPointers(offset+variable.offsetInBits DIV 8,variable.type,numberPointers);
  703. END;
  704. variable := variable.nextVariable;
  705. END;
  706. END;
  707. ELSIF (type IS SyntaxTree.ArrayType) THEN
  708. WITH type: SyntaxTree.ArrayType DO
  709. IF type.form= SyntaxTree.Static THEN
  710. n := type.staticLength;
  711. base := type.arrayBase.resolved;
  712. WHILE(base IS SyntaxTree.ArrayType) DO
  713. type := base(SyntaxTree.ArrayType);
  714. n := n* type.staticLength;
  715. base := type.arrayBase.resolved;
  716. END;
  717. size := module.system.AlignedSizeOf(base) DIV 8;
  718. IF SemanticChecker.ContainsPointer(base) THEN
  719. ASSERT(n<1000000); (* not more than one million pointers on the stack ... *)
  720. FOR i := 0 TO n-1 DO
  721. OutPointers(offset+i*size,base,numberPointers);
  722. END;
  723. END;
  724. ELSE
  725. ASSERT(offset MOD 4 = 0);
  726. w.RawNum((offset )); INC(numberPointers);
  727. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  728. END;
  729. END;
  730. ELSIF (type IS SyntaxTree.MathArrayType) THEN
  731. WITH type: SyntaxTree.MathArrayType DO
  732. IF type.form = SyntaxTree.Static THEN
  733. n := type.staticLength;
  734. base := type.arrayBase.resolved;
  735. WHILE(base IS SyntaxTree.MathArrayType) DO
  736. type := base(SyntaxTree.MathArrayType);
  737. n := n* type.staticLength;
  738. base := type.arrayBase.resolved;
  739. END;
  740. size := module.system.AlignedSizeOf(base) DIV 8;
  741. IF SemanticChecker.ContainsPointer(base) THEN
  742. ASSERT(n<1000000); (* not more than one million pointers on the stack ... *)
  743. FOR i := 0 TO n-1 DO
  744. OutPointers(offset+i*size,base,numberPointers);
  745. END;
  746. END;
  747. ELSE
  748. ASSERT(offset MOD 4 = 0);
  749. w.RawNum((offset )); INC(numberPointers); (* GC relevant pointer is at offset 0 *)
  750. IF Trace THEN D.Str("ptr at offset="); D.Int(offset,1); D.Ln; END;
  751. END
  752. END;
  753. (* ELSE no pointers in type *)
  754. END;
  755. END OutPointers;
  756. (* Pointers =
  757. 84X { pointerOffset:Num}:numberPointers
  758. *)
  759. PROCEDURE Pointers;
  760. VAR
  761. s: Section; variable: SyntaxTree.Variable;
  762. i: LONGINT;
  763. BEGIN
  764. w.Char(84X);
  765. numberPointers := 0;
  766. IF Trace THEN D.Str("Global Pointers: "); D.Ln; END;
  767. FOR i := 0 TO symbols.Length() - 1 DO
  768. s := symbols.GetSection(i);
  769. IF (s.symbol # NIL) & (s.symbol IS SyntaxTree.Variable) THEN
  770. variable := s.symbol(SyntaxTree.Variable);
  771. IF ~(variable.untraced) THEN
  772. OutPointers(s.offset, variable.type, numberPointers);
  773. END
  774. END
  775. END
  776. END Pointers;
  777. PROCEDURE IsFirstOccurence(import: SyntaxTree.Import): BOOLEAN; (*! inefficient *)
  778. VAR i: SyntaxTree.Import;
  779. BEGIN
  780. i := moduleScope.firstImport;
  781. WHILE (i # NIL) & (i.module # import.module) DO
  782. i := i.nextImport;
  783. END;
  784. RETURN i = import
  785. END IsFirstOccurence;
  786. (* Imports =
  787. 85X { moduleName:String }:numberImports
  788. *)
  789. PROCEDURE Imports;
  790. VAR name: Name; import: SyntaxTree.Import;
  791. BEGIN
  792. w.Char(85X);
  793. numberImports := 0;
  794. import := moduleScope.firstImport;
  795. WHILE(import # NIL) DO
  796. IF ~Global.IsSystemModule(import.module) & IsFirstOccurence(import) THEN
  797. Global.ModuleFileName(import.module.name,import.module.context,name);
  798. w.RawString(name); INC(numberImports);
  799. IF Trace THEN
  800. D.Str("Import module : "); D.Str(name); D.Ln;
  801. END;
  802. END;
  803. import := import.nextImport;
  804. END;
  805. END Imports;
  806. (*? should this be coded fix in a separate module list ? *)
  807. (* Module Number returns the position of a module in the written import list *)
  808. PROCEDURE ModuleNumber(m: SyntaxTree.Module): LONGINT;
  809. VAR number: LONGINT; import: SyntaxTree.Import;
  810. BEGIN
  811. number := 1;
  812. import := moduleScope.firstImport;
  813. WHILE(import # NIL) & (import.module # m) DO
  814. IF ~Global.IsSystemModule(import.module) & IsFirstOccurence(import) THEN
  815. INC(number);
  816. END;
  817. import := import.nextImport;
  818. END;
  819. RETURN number;
  820. END ModuleNumber;
  821. (*
  822. VarConstLinks = 8DX {VarConstLinkEntry}: numberVarConstLinks
  823. VarConstLinkEntry = modNumber:1 entry:Number fixupCount:4 {offset:Number}:fixupCount}
  824. *)
  825. PROCEDURE VarConstLinks;
  826. VAR
  827. fixups: LONGINT; fixupsPosition: LONGINT;
  828. s: Section; fixup: Fixup; temp, i: LONGINT;
  829. sym: Section;
  830. PROCEDURE Fixups(f: Fixup);
  831. BEGIN
  832. WHILE f # NIL DO
  833. IF Trace THEN
  834. D.String("fixup "); D.Int(f.fixupSection.offset +f.fixup.offset ,1); D.Ln;
  835. END;
  836. w.RawNum((f.fixupSection.offset + f.fixup.offset )); INC(fixups);
  837. f := f.nextFixup;
  838. END;
  839. END Fixups;
  840. BEGIN
  841. w.Char(8DX);
  842. numberVarConstLinks := 0;
  843. (* global variables and constants of this module *)
  844. w.Char(0X); (* module Number = 0 => this module *)
  845. w.RawNum(-1); (* entry = -1 => this module *)
  846. fixupsPosition := w.Pos(); fixups := 0;
  847. w.RawLInt(fixups); (* number of fixups, to be patche *)
  848. IF Trace THEN D.Str("VarConstLinks:Procedures"); D.Ln; END;
  849. FOR i := 0 TO symbols.Length() - 1 DO
  850. s := symbols.GetSection(i);
  851. IF ~s.isCaseTable THEN
  852. IF (s.symbol=NIL) OR (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN
  853. IF Trace THEN D.String("varconstlink, procedure "); Basic.WriteSegmentedName(D.Log, s.name); D.Ln END;
  854. Fixups(s.fixups);
  855. END
  856. END;
  857. END;
  858. (*! can be merged with previous -- for testing consistency *)
  859. FOR i := 0 TO symbols.Length() - 1 DO
  860. s := symbols.GetSection(i);
  861. IF s.isCaseTable THEN
  862. ASSERT(s.symbol # NIL);
  863. IF (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN
  864. Fixups(s.fixups);
  865. END
  866. END;
  867. END;
  868. (*
  869. IF Trace THEN D.Str("VarConstLinks:CaseTables"); D.Ln; END;
  870. FOR i := 0 TO module.allSections.Length() - 1 DO
  871. s := module.allSections.GetSection(i);
  872. IF s.kind = Sections.CaseTableKind THEN
  873. IF (s.symbol # NIL) & ~(s.symbol IS SyntaxTree.Procedure) THEN (* includes case symbol! *)
  874. temp := GetFixups(module,s,fixup);
  875. Fixups(fixup);
  876. END
  877. END
  878. END;
  879. *)
  880. RawLIntAt(fixupsPosition,fixups); (* fixups count patched *)
  881. INC(numberVarConstLinks);
  882. IF Trace THEN D.Str("VarConstLinks:ImportedSymbols"); D.Ln; END;
  883. (* imported global variables and constants *)
  884. FOR i := 0 TO importedSymbols.Length()-1 DO
  885. sym := importedSymbols.GetSection(i);
  886. IF (sym.symbol=NIL) OR (sym.symbol # NIL) & ~(sym.symbol IS SyntaxTree.Procedure) THEN
  887. ASSERT(sym.numberFixups > 0);
  888. sym.entryNumber := numberVarConstLinks;
  889. INC(numberVarConstLinks);
  890. w.Char(CHR(ModuleNumber(sym.symbol.scope.ownerModule)));
  891. w.RawNum(0); (* entry = 0 => importing module *)
  892. w.RawLInt(sym.numberFixups); (* number of fixups, to be patched *)
  893. Fixups(sym.fixups);
  894. END;
  895. END;
  896. END VarConstLinks;
  897. (*
  898. Links = 86X {LinkEntry:Number}:numberLinks {FixupCount:Number}:numberEntries caseTableSize:Number
  899. LinkEntry = moduleNumber:1 entryNumber:1 offset:Number
  900. *)
  901. PROCEDURE Links;
  902. VAR
  903. p: Section; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType; i, counter: LONGINT; temp: LONGINT; fixup: Fixup; fixups: LONGINT;
  904. CONST
  905. FixupSentinel = LONGINT(0FFFFFFFFH);
  906. (* Insert fixup list into code *)
  907. PROCEDURE FixupList(l: Fixup): LONGINT;
  908. VAR
  909. offset,first: LONGINT;
  910. PROCEDURE Put32(offset: LONGINT; number: LONGINT);
  911. BEGIN
  912. code[offset] := CHR(number MOD 256);
  913. INC(offset); number := number DIV 256;
  914. code[offset] := CHR(number MOD 256);
  915. INC(offset); number := number DIV 256;
  916. code[offset] := CHR(number MOD 256);
  917. INC(offset); number := number DIV 256;
  918. code[offset] := CHR(number MOD 256);
  919. END Put32;
  920. BEGIN
  921. offset := (l.fixupSection.offset +l.fixup.offset );first := offset;
  922. l := l.nextFixup;
  923. WHILE l # NIL DO
  924. Put32(offset,(l.fixupSection.offset +l.fixup.offset ));
  925. offset := (l.fixupSection.offset +l.fixup.offset );
  926. l := l.nextFixup;
  927. END;
  928. Put32(offset,FixupSentinel);
  929. RETURN first;
  930. END FixupList;
  931. BEGIN
  932. w.Char(86X);
  933. numberLinks := 0;
  934. (* system call sections removed: replaced by procedure calls *)
  935. IF procedureFixupOffset #-1 THEN
  936. w.Char(0X); w.Char(SysCallMap[ProcAddr]); w.RawNum(procedureFixupOffset);
  937. INC(numberLinks);
  938. END;
  939. IF caseTableSize > 0 THEN
  940. w.Char(0X); w.Char(SysCallMap[CaseTable]); w.RawNum((constSize -caseTableSize *4));
  941. INC(numberLinks);
  942. (* case table is fixuped by the loader using offset of case table in constant section
  943. it is impossible to have disjoint case tables here
  944. *)
  945. END;
  946. counter := 0;
  947. (* cf. Entries *)
  948. FOR i := 0 TO symbols.Length() - 1 DO
  949. p := symbols.GetSection(i);
  950. IF (p.symbol # NIL) & (p.symbol IS SyntaxTree.Procedure) & ~p.symbol(SyntaxTree.Procedure).isInline THEN
  951. fixup := p.fixups;
  952. procedure := p.symbol(SyntaxTree.Procedure);
  953. procedureType := procedure.type(SyntaxTree.ProcedureType);
  954. IF (procedure.access * SyntaxTree.Public # {}) OR (procedureType.isDelegate) OR (fixup # NIL) THEN
  955. w.RawNum(p.numberFixups);
  956. INC(counter);
  957. END
  958. END
  959. END;
  960. ASSERT(counter = numberEntries);
  961. w.RawNum((caseTableSize ));
  962. END Links;
  963. (* Constants = 87X {character:1} *)
  964. PROCEDURE Constants;
  965. VAR i: LONGINT;
  966. BEGIN
  967. w.Char(87X);
  968. FOR i := 0 TO ((constSize-1) ) DO
  969. w.Char(const[i]);
  970. crc32.Char(const[i]);
  971. END;
  972. END Constants;
  973. (* Exports *)
  974. PROCEDURE Exports;
  975. VAR numberExports,numberExportsPosition: LONGINT; constant: SyntaxTree.Constant;
  976. variable: SyntaxTree.Variable; procedure : SyntaxTree.Procedure; typeDeclaration : SyntaxTree.TypeDeclaration;
  977. typeNumber: LONGINT; name: ARRAY 256 OF CHAR;
  978. PROCEDURE ExportType(type: SyntaxTree.Type);
  979. VAR destination: Section; ref: LONGINT; count: LONGINT; countPos: LONGINT;
  980. variable: SyntaxTree.Variable; procedure: SyntaxTree.Procedure; fingerPrint: SyntaxTree.FingerPrint;
  981. initialType: SyntaxTree.Type;
  982. BEGIN
  983. IF type = NIL THEN RETURN END; (* no type *)
  984. type := type.resolved;
  985. (* fof: thjs can cause a repetitive entry of the same type *)
  986. initialType := type;
  987. WHILE (type IS SyntaxTree.PointerType) OR (type IS SyntaxTree.ArrayType) OR (type IS SyntaxTree.MathArrayType) DO
  988. IF type IS SyntaxTree.PointerType THEN
  989. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  990. ELSIF type IS SyntaxTree.ArrayType THEN
  991. type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  992. ELSE
  993. type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  994. END;
  995. IF type = initialType THEN RETURN END; (* avoid cycles *)
  996. END;
  997. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = module.module) THEN
  998. w.Char(ofEURecord);
  999. destination := symbols.BySymbol(type.typeDeclaration);
  1000. ASSERT(destination # NIL);
  1001. ref := destination.entryNumber;
  1002. IF ref # 0 THEN
  1003. w.RawNum(-ref);
  1004. IF Trace THEN D.Str("already referenced as "); D.Int(ref,1); D.Ln END;
  1005. ELSE
  1006. count := 0; (* number of exported entries *)
  1007. INC(typeNumber); (* reference number to this type *)
  1008. destination.SetEntryNumber(typeNumber);
  1009. IF Trace THEN D.Str("register as "); D.Int(typeNumber,1); D.Ln END;
  1010. w.RawNum((destination.offset ));
  1011. countPos := w.Pos();
  1012. w.RawLInt(2);
  1013. ExportType(type(SyntaxTree.RecordType).baseType);
  1014. fingerPrint := fingerprinter.TypeFP(type);
  1015. (*
  1016. ASSERT(fingerPrint.privateFP # 0); (* may not be zero by object file format: would be interpreted as end of section *)
  1017. ASSERT(fingerPrint.publicFP # 0); (* ^ ^ *)
  1018. *)
  1019. IF Trace THEN D.Str("export type fp "); D.Int(fingerPrint.private,1); D.Str(","); D.Int(fingerPrint.public,1); D.Ln END;
  1020. w.RawNum(fingerPrint.private); w.RawNum(fingerPrint.public);
  1021. variable := type(SyntaxTree.RecordType).recordScope.firstVariable;
  1022. WHILE variable # NIL DO
  1023. IF variable.access * SyntaxTree.Public # {} THEN
  1024. fingerPrint := fingerprinter.SymbolFP(variable);
  1025. w.RawNum(fingerPrint.shallow);
  1026. ExportType(variable.type);
  1027. INC(count);
  1028. END;
  1029. variable := variable.nextVariable;
  1030. END;
  1031. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1032. WHILE procedure # NIL DO
  1033. IF (procedure.access * SyntaxTree.Public # {}) & ~(procedure.isInline) THEN
  1034. fingerPrint := fingerprinter.SymbolFP(procedure);
  1035. w.RawNum(fingerPrint.shallow);
  1036. INC(count);
  1037. END;
  1038. procedure := procedure.nextProcedure;
  1039. END;
  1040. IF count # 0 THEN RawLIntAt(countPos,count+2) END;
  1041. w.Char(ofEUEnd);
  1042. END;
  1043. END;
  1044. END ExportType;
  1045. PROCEDURE SymbolOffset(symbol: SyntaxTree.Symbol): LONGINT;
  1046. VAR s: Section; name: SyntaxTree.IdentifierString;
  1047. BEGIN
  1048. IF (symbol IS SyntaxTree.Procedure) & (symbol(SyntaxTree.Procedure).isInline) THEN
  1049. RETURN 0
  1050. END;
  1051. symbol.GetName(name); (* debugging *)
  1052. s := symbols.BySymbol(symbol); (* TODO *)
  1053. ASSERT(s#NIL);
  1054. RETURN (s.offset);
  1055. END SymbolOffset;
  1056. PROCEDURE ExportSymbol(symbol: SyntaxTree.Symbol; offset: LONGINT;CONST prefix: ARRAY OF CHAR);
  1057. VAR fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT;
  1058. BEGIN
  1059. fingerPrint := fingerprinter.SymbolFP(symbol);
  1060. fp := fingerPrint.shallow;
  1061. (*
  1062. IF prefix # "" THEN (* make unique by object name prefix *)
  1063. FingerPrint.FPString(fp,prefix)
  1064. END;
  1065. *)
  1066. w.RawNum(fp);
  1067. (*! check for duplicate fingerprint *)
  1068. w.RawNum(offset );
  1069. IF Trace THEN
  1070. symbol.GetName(name);
  1071. D.Str("FoxObjectFile.Exports.ExportSymbol ");
  1072. IF prefix # "" THEN D.Str(prefix); D.Str(".") END;
  1073. D.Str(name);
  1074. D.Str(" : ");
  1075. D.Hex(fp,-8); D.Ln;
  1076. END;
  1077. END ExportSymbol;
  1078. PROCEDURE ExportMethods(typeDeclaration: SyntaxTree.TypeDeclaration);
  1079. VAR name: SyntaxTree.IdentifierString; type: SyntaxTree.Type; fingerPrint: SyntaxTree.FingerPrint; initialType: SyntaxTree.Type;
  1080. BEGIN
  1081. type := typeDeclaration.declaredType;
  1082. typeDeclaration.GetName(name);
  1083. type := type.resolved; initialType := type;
  1084. WHILE (type IS SyntaxTree.PointerType) OR (type IS SyntaxTree.ArrayType) OR (type IS SyntaxTree.MathArrayType) DO
  1085. IF type IS SyntaxTree.PointerType THEN
  1086. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1087. ELSIF type IS SyntaxTree.ArrayType THEN
  1088. type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1089. ELSE
  1090. type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1091. END;
  1092. IF type = initialType THEN RETURN END; (* avoid circles *)
  1093. END;
  1094. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = module.module) THEN
  1095. fingerPrint := fingerprinter.TypeFP(type); (* make sure that fingerprint has traversed all methods ... *)
  1096. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1097. WHILE procedure # NIL DO
  1098. IF (procedure.access * SyntaxTree.Public # {}) THEN
  1099. ExportSymbol(procedure,SymbolOffset(procedure),name);
  1100. INC(numberExports);
  1101. END;
  1102. procedure := procedure.nextProcedure;
  1103. END;
  1104. END;
  1105. END ExportMethods;
  1106. BEGIN
  1107. w.Char(88X);
  1108. numberExports := 0; typeNumber := 0;
  1109. numberExportsPosition := w.Pos();
  1110. w.RawLInt(numberExports);
  1111. (*! in the end anything that has an offset should be present in the BackendStructures.Module,
  1112. therefore the list can also be traverse from the respective Backend structure *)
  1113. (* constants *)
  1114. constant := moduleScope.firstConstant;
  1115. WHILE constant # NIL DO
  1116. IF (constant.access * SyntaxTree.Public # {}) THEN
  1117. IF Trace THEN
  1118. constant.GetName(name);
  1119. D.String("Constant:"); D.String(name); D.Ln;
  1120. END;
  1121. IF (~(constant.type IS SyntaxTree.BasicType)) THEN
  1122. ExportSymbol(constant,SymbolOffset(constant),"");
  1123. ELSE
  1124. ExportSymbol(constant,0,"")
  1125. END;
  1126. INC(numberExports);
  1127. END;
  1128. constant := constant.nextConstant;
  1129. END;
  1130. (* global variables *)
  1131. variable := moduleScope.firstVariable;
  1132. WHILE variable # NIL DO
  1133. IF variable.access * SyntaxTree.Public # {} THEN
  1134. IF Trace THEN
  1135. variable.GetName(name);
  1136. D.String("Variable:"); D.String(name); D.Ln;
  1137. END;
  1138. ExportSymbol(variable,SymbolOffset(variable),"");
  1139. ExportType(variable.type);
  1140. INC(numberExports);
  1141. END;
  1142. variable := variable.nextVariable;
  1143. END;
  1144. (* type declarations *)
  1145. typeDeclaration := moduleScope.firstTypeDeclaration;
  1146. WHILE typeDeclaration # NIL DO
  1147. IF TRUE (* typeDeclaration.access * SyntaxTree.Public # {} *) THEN
  1148. IF Trace THEN
  1149. typeDeclaration.GetName(name);
  1150. D.String("TypeDeclaration:"); D.String(name); D.Ln;
  1151. END;
  1152. ExportSymbol(typeDeclaration,0,"");
  1153. ExportType(typeDeclaration.declaredType);
  1154. INC(numberExports);
  1155. END;
  1156. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1157. END;
  1158. (* exported procedures *)
  1159. procedure := moduleScope.firstProcedure;
  1160. WHILE procedure # NIL DO
  1161. IF (procedure.access* SyntaxTree.Public # {}) THEN
  1162. IF Trace THEN
  1163. procedure.GetName(name);
  1164. D.String("Procedure:"); D.String(name); D.Ln;
  1165. END;
  1166. ExportSymbol(procedure,SymbolOffset(procedure),"");
  1167. INC(numberExports);
  1168. END;
  1169. procedure := procedure.nextProcedure;
  1170. END;
  1171. (* exported methods *)
  1172. typeDeclaration := moduleScope.firstTypeDeclaration;
  1173. WHILE typeDeclaration # NIL DO
  1174. IF typeDeclaration.access * SyntaxTree.Public # {} THEN
  1175. ExportMethods(typeDeclaration);
  1176. END;
  1177. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1178. END;
  1179. RawLIntAt(numberExportsPosition,numberExports);
  1180. w.Char(0X);
  1181. END Exports;
  1182. (* Code = 89X {character:1} *)
  1183. PROCEDURE Code;
  1184. VAR i: LONGINT;
  1185. BEGIN
  1186. w.Char(89X);
  1187. FOR i := 0 TO ((codeSize-1) ) DO
  1188. w.Char(code[i]);
  1189. crc32.Char(code[i]);
  1190. END;
  1191. END Code;
  1192. (*
  1193. Use = 08AX {UsedModules} 0X
  1194. UsedModules = moduleName:String {UsedConstant | UsedVariable | UsedProcedure | UsedType } 0X
  1195. UsedConstant = FP:Number constName:String 0X
  1196. UsedVariable = FP:Number varName:String fixlist:Number [1X UsedRecord]
  1197. UsedProcedure = FP:Number procName:String offset:Number
  1198. UsedType = FP:Number typeName:String 0X [1X UsedRecord]
  1199. UsedRecord = tdentry:Number [FP "@"] 0X
  1200. *)
  1201. PROCEDURE Use;
  1202. VAR import: SyntaxTree.Import; name: SyntaxTree.IdentifierString; importedModule: SyntaxTree.Module; s: Section;
  1203. constant: SyntaxTree.Constant; variable: SyntaxTree.Variable; typeDeclaration: SyntaxTree.TypeDeclaration; procedure: SyntaxTree.Procedure;
  1204. type: SyntaxTree.Type;fixup: Fixup; fixups: LONGINT; sym: Section;
  1205. PROCEDURE UseEntry(module: SyntaxTree.Module; symbol: SyntaxTree.Symbol; offsetInBytes: LONGINT; CONST prefix: ARRAY OF CHAR);
  1206. VAR name,suffix: Basic.SectionName; fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT;
  1207. BEGIN
  1208. symbol.GetName(suffix);
  1209. IF prefix # "" THEN
  1210. COPY(prefix,name); Strings.Append(name,"."); Strings.Append(name,suffix);
  1211. ELSE
  1212. name := suffix;
  1213. END;
  1214. fingerPrint := fingerprinter.SymbolFP(symbol);
  1215. fp := fingerPrint.shallow;
  1216. (*
  1217. IF prefix # "" THEN FingerPrint.FPString(fp,prefix) END;
  1218. *)
  1219. w.RawNum(fp);
  1220. IF Trace THEN
  1221. D.Str("FoxObjectFile.Use ");
  1222. D.Str(suffix);
  1223. D.Str(" : "); D.Hex(SYSTEM.VAL(LONGINT,symbol),-8); D.Str(" : ");
  1224. D.Hex(fp,-8);
  1225. D.String(" @ ");
  1226. D.Int(offsetInBytes-ofEUProcFlag,1);
  1227. D.Ln;
  1228. END;
  1229. w.RawString(name);
  1230. w.RawNum(offsetInBytes);
  1231. END UseEntry;
  1232. PROCEDURE UseType(type: SyntaxTree.Type);
  1233. VAR t: Section; fingerPrint: SyntaxTree.FingerPrint; name: SyntaxTree.IdentifierString;
  1234. BEGIN
  1235. type := type.resolved;
  1236. LOOP
  1237. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1238. ELSIF type IS SyntaxTree.ArrayType THEN type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1239. ELSIF type IS SyntaxTree.MathArrayType THEN type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1240. ELSE EXIT
  1241. END;
  1242. END;
  1243. IF type IS SyntaxTree.RecordType THEN
  1244. WITH type: SyntaxTree.RecordType DO
  1245. type.typeDeclaration.GetName(name); (* debugging *)
  1246. IF type.recordScope.ownerModule = importedModule THEN (* type belongs to currently processed module *)
  1247. IF Trace THEN D.Str("UseTypeFP:"); D.Str(name); D.Str("?"); D.Ln END;
  1248. t := symbols.BySymbol(type.typeDeclaration); (* TODO *)
  1249. IF (t # NIL) & (t.referenced) (*(t.fixups # NIL)*) THEN
  1250. t.referenced := FALSE;
  1251. fingerPrint := fingerprinter.TypeFP(type);
  1252. w.Char(ofEURecord);
  1253. w.RawNum(-(t.offset ));
  1254. (* privateFP never set in old compiler *)
  1255. IF Trace THEN D.Str("UseTypeFP:"); D.Str(name); D.Str(":"); D.Int(fingerPrint.public,1); D.Ln END;
  1256. w.RawNum(fingerPrint.public);
  1257. w.RawString("@");
  1258. w.Char(ofEUEnd);
  1259. END;
  1260. ELSE
  1261. (* nothing to be done? => module must be added to import section, this must be done by the semantic checker *)
  1262. END
  1263. END
  1264. END
  1265. END UseType;
  1266. PROCEDURE UseMethods(typeDeclaration: SyntaxTree.TypeDeclaration);
  1267. VAR procedure: SyntaxTree.Procedure; sym: Section; prefix: SyntaxTree.IdentifierString; fingerPrint: SyntaxTree.FingerPrint; type: SyntaxTree.Type;
  1268. fixup: Fixup; fixups: LONGINT;
  1269. BEGIN
  1270. typeDeclaration.GetName(prefix);
  1271. type := typeDeclaration.declaredType.resolved;
  1272. LOOP
  1273. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1274. (*!???? => problems with name prefix. Necessary to treat arrays here?
  1275. ELSIF type IS SyntaxTree.ArrayType THEN type := type(SyntaxTree.ArrayType).arrayBase.resolved;
  1276. ELSIF type IS SyntaxTree.MathArrayType THEN type := type(SyntaxTree.MathArrayType).arrayBase.resolved;
  1277. *)
  1278. ELSE EXIT
  1279. END;
  1280. END;
  1281. IF (type IS SyntaxTree.RecordType) & (type.scope.ownerModule = importedModule) (* do not take alias *) THEN
  1282. fingerPrint := fingerprinter.TypeFP(type); (* make sure that type is fingerprinted including all methods *)
  1283. procedure := type(SyntaxTree.RecordType).recordScope.firstProcedure;
  1284. WHILE procedure # NIL DO
  1285. sym := importedSymbols.BySymbol(procedure);
  1286. IF sym # NIL THEN
  1287. fixup := sym.fixups;
  1288. UseEntry(importedModule,procedure,(fixup.fixupSection.offset + fixup.fixup.offset )+ofEUProcFlag,prefix);
  1289. END;
  1290. procedure := procedure.nextProcedure
  1291. END
  1292. END
  1293. END UseMethods;
  1294. BEGIN
  1295. w.Char(08AX);
  1296. import := moduleScope.firstImport;
  1297. WHILE(import # NIL) DO (*! in a new object file this would not necessarily be ordered by imports (?) *)
  1298. IF (import.module # module.system.systemModule[import.module.case]) & IsFirstOccurence(import) THEN
  1299. importedModule := import.module;
  1300. ASSERT(importedModule # NIL);
  1301. ASSERT(importedModule # module.system.systemModule[0]);
  1302. ASSERT(importedModule # module.system.systemModule[1]);
  1303. Global.ModuleFileName(import.module.name,import.module.context,name);
  1304. w.RawString(name);
  1305. IF Trace THEN
  1306. D.Str("Use module : "); D.Str(name); D.Ln;
  1307. END;
  1308. constant := importedModule.moduleScope.firstConstant;
  1309. WHILE constant # NIL DO
  1310. sym := importedSymbols.BySymbol(constant);
  1311. IF sym # NIL THEN UseEntry(importedModule,constant,0,"") END;
  1312. constant := constant.nextConstant
  1313. END;
  1314. variable := importedModule.moduleScope.firstVariable;
  1315. WHILE variable # NIL DO
  1316. sym := importedSymbols.BySymbol(variable);
  1317. IF sym # NIL THEN
  1318. UseEntry(importedModule,variable,sym.entryNumber,"");
  1319. UseType(variable.type);
  1320. END;
  1321. variable := variable.nextVariable
  1322. END;
  1323. typeDeclaration := importedModule.moduleScope.firstTypeDeclaration;
  1324. WHILE typeDeclaration # NIL DO
  1325. type := typeDeclaration.declaredType;
  1326. IF type IS SyntaxTree.PointerType THEN type := type(SyntaxTree.PointerType).pointerBase END;
  1327. sym := symbols.BySymbol(typeDeclaration); (* only if has been used -- contained in module sections: alias *)
  1328. IF (sym # NIL) & (sym.referenced) THEN
  1329. UseEntry(importedModule,typeDeclaration,0,"");
  1330. UseType(typeDeclaration.declaredType);
  1331. END;
  1332. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1333. END;
  1334. procedure := importedModule.moduleScope.firstProcedure;
  1335. WHILE procedure # NIL DO
  1336. IF ~procedure.isInline THEN
  1337. sym := importedSymbols.BySymbol(procedure);
  1338. IF sym # NIL THEN
  1339. fixup := sym.fixups;
  1340. UseEntry(importedModule,procedure,(fixup.fixupSection.offset + fixup.fixup.offset )+ofEUProcFlag,"");
  1341. END;
  1342. END;
  1343. procedure := procedure.nextProcedure
  1344. END;
  1345. typeDeclaration := importedModule.moduleScope.firstTypeDeclaration;
  1346. WHILE typeDeclaration # NIL DO
  1347. IF ~(typeDeclaration.declaredType IS SyntaxTree.QualifiedType) (* alias *) THEN
  1348. UseMethods(typeDeclaration);
  1349. END;
  1350. typeDeclaration := typeDeclaration.nextTypeDeclaration
  1351. END;
  1352. w.Char(0X);
  1353. END;
  1354. import := import.nextImport;
  1355. END;
  1356. w.Char(0X);
  1357. END Use;
  1358. PROCEDURE WriteType(d:Section; type: SyntaxTree.RecordType; VAR tdSize: LONGINT (* ug *));
  1359. CONST MaxTags = 16; (* ug: temporary solution, Modules.MaxTags *)
  1360. VAR
  1361. tdSizePos, oldmth,newmeth: LONGINT; base: SyntaxTree.RecordType;
  1362. name: SyntaxTree.IdentifierString;
  1363. baseModule: LONGINT; baseEntry: LONGINT;
  1364. upperPartTdSize, lowerPartTdSize: LONGINT;
  1365. size: LONGINT;
  1366. numberPointersPosition: LONGINT;
  1367. numberPointers: LONGINT;
  1368. destination: Section;
  1369. procedure: Section;
  1370. fp: SyntaxTree.FingerPrint;
  1371. m: SyntaxTree.Procedure;
  1372. i: LONGINT;
  1373. typeDeclaration: SyntaxTree.TypeDeclaration;
  1374. BEGIN
  1375. name := "@@";
  1376. ASSERT(type.typeDeclaration # NIL);
  1377. type.typeDeclaration.GetName(name);
  1378. size := module.system.AlignedSizeOf(type) DIV 8;
  1379. w.RawNum(size );
  1380. w.RawNum((d.offset )); (* type descriptor pointer address, patched by loader to type desciptor address *)
  1381. base := type.GetBaseRecord();
  1382. IF (base = NIL) THEN (* no base type *)
  1383. oldmth := 0;
  1384. baseModule := -1;
  1385. baseEntry := -1
  1386. ELSE
  1387. baseModule := 0; (* base type in local module *)
  1388. IF (base.typeDeclaration # NIL) & (base.typeDeclaration.scope # NIL) & (base.typeDeclaration.scope.ownerModule # moduleScope.ownerModule) THEN (* base type in other module *)
  1389. baseModule := ModuleNumber(base.typeDeclaration.scope.ownerModule);
  1390. typeDeclaration := base.typeDeclaration;
  1391. ASSERT(baseModule # 0);
  1392. ELSE
  1393. typeDeclaration := NIL;
  1394. END;
  1395. IF baseModule = 0 THEN
  1396. destination := symbols.BySymbol(base.typeDeclaration); (*TODO*)
  1397. ASSERT(destination # NIL);
  1398. baseEntry := (destination.offset ); (* destination must be non-nil *)
  1399. ELSIF (typeDeclaration # NIL) THEN
  1400. fp := fingerprinter.SymbolFP(typeDeclaration);
  1401. baseEntry := fp.shallow;
  1402. ELSE
  1403. HALT(100);
  1404. (* ELSE
  1405. base := base(SyntaxTree.PointerType).pointerBase;
  1406. fp := fingerprinter.SymbolFP(base.typeDeclaration);
  1407. baseEntry := fp.FP;
  1408. *)
  1409. END;
  1410. oldmth := base.recordScope.numberMethods;
  1411. END;
  1412. w.RawNum(baseModule);
  1413. w.RawNum(baseEntry);
  1414. newmeth := 0;
  1415. m := type.recordScope.firstProcedure;
  1416. WHILE (m# NIL) DO
  1417. INC(newmeth); (*! check that this is not an inline procedure *)
  1418. m := m.nextProcedure;
  1419. END;
  1420. IF type.IsProtected() THEN
  1421. w.RawNum(-type.recordScope.numberMethods); (* number methods total *)
  1422. ELSE
  1423. w.RawNum(type.recordScope.numberMethods); (* number methods total *)
  1424. END;
  1425. w.RawNum(oldmth); (* inherited methods total *)
  1426. w.RawNum(newmeth); (* new methods (overridden or new) *)
  1427. numberPointersPosition:= w.Pos();
  1428. w.RawLInt(0);
  1429. w.RawString(name);
  1430. tdSizePos := w.Pos();
  1431. w.RawLInt(0);
  1432. i := 0;
  1433. m := type.recordScope.firstProcedure;
  1434. WHILE (m#NIL) DO
  1435. IF ~(m.isInline) THEN
  1436. procedure := symbols.BySymbol(m); (*TODO*)
  1437. ASSERT(procedure # NIL);
  1438. m.GetName(name);
  1439. w.RawNum(procedure.symbol(SyntaxTree.Procedure).methodNumber);
  1440. w.RawNum(procedure.entryNumber);
  1441. INC(i);
  1442. END;
  1443. m := m.nextProcedure;
  1444. END;
  1445. (* Ptrs in Record *)
  1446. numberPointers := 0;
  1447. IF Trace THEN D.Str("pointers of type: "); D.Ln; END;
  1448. OutPointers(0, type, numberPointers); (* debug = FALSE *)
  1449. IF numberPointers # 0 THEN RawLIntAt(numberPointersPosition,numberPointers) END;
  1450. (* ug *) upperPartTdSize := module.system.addressSize DIV 8 * (MaxTags + type.recordScope.numberMethods + 1 + 1); (* tags, methods, methods end marker (sentinel), address of TypeInfo *)
  1451. (* ug *) lowerPartTdSize := module.system.addressSize DIV 8 * (2 + (4 + numberPointers) + 1);
  1452. (* ug *) tdSize := upperPartTdSize + lowerPartTdSize;
  1453. (* ug *) RawLIntAt(tdSizePos, tdSize) ;
  1454. END WriteType;
  1455. PROCEDURE Types;
  1456. VAR
  1457. t: Section; tdSize, i: LONGINT;
  1458. typeDeclaration: SyntaxTree.TypeDeclaration; type: SyntaxTree.Type;
  1459. name: ARRAY 256 OF CHAR;
  1460. BEGIN
  1461. w.Char(08BX);
  1462. numberTypes := 0; typeDescSize := 0;
  1463. FOR i := 0 TO symbols.Length() - 1 DO
  1464. t := symbols.GetSection(i);
  1465. IF (t.symbol # NIL) & (t.symbol IS SyntaxTree.TypeDeclaration) THEN
  1466. typeDeclaration := t.symbol(SyntaxTree.TypeDeclaration);
  1467. type := typeDeclaration.declaredType;
  1468. typeDeclaration.GetName(name);
  1469. IF type IS SyntaxTree.PointerType THEN
  1470. IF type(SyntaxTree.PointerType).pointerBase.resolved.typeDeclaration = typeDeclaration THEN (* avoid duplicate declarations *)
  1471. type := type(SyntaxTree.PointerType).pointerBase.resolved;
  1472. END;
  1473. END;
  1474. IF Trace THEN D.Str("FoxObjectFile.Types: "); D.String(name); D.Ln; END;
  1475. IF (type IS SyntaxTree.RecordType) & (type(SyntaxTree.RecordType).recordScope.ownerModule = moduleScope.ownerModule) OR (type(SyntaxTree.RecordType).recordScope.ownerModule = NIL) THEN
  1476. t := symbols.BySymbol(type.typeDeclaration);
  1477. ASSERT(t # NIL);
  1478. WriteType(t,type(SyntaxTree.RecordType),tdSize);
  1479. INC(typeDescSize,tdSize);
  1480. INC(numberTypes);
  1481. END;
  1482. END
  1483. END
  1484. END Types;
  1485. (* Stores the exception handle table in the following format
  1486. ExceptionHandlerTable ::= 8EX {ExceptionTableEntry}
  1487. ExceptionTableEntry ::= 0FFX pcFrom(4 bytes) pcTo(4 bytes) pcHandler(4 bytes)
  1488. Since there is only one FINALLY in every procedure, method, body, ... we don't need
  1489. to obtain an order for nesting.
  1490. *)
  1491. PROCEDURE ExceptionTable;
  1492. VAR
  1493. p: Section; pcFrom, pcTo, pcHandler, i: LONGINT;
  1494. binarySection: BinaryCode.Section;
  1495. BEGIN
  1496. exTableLen := 0;
  1497. w.Char(08EX);
  1498. FOR i := 0 TO symbols.Length() - 1 DO
  1499. p := symbols.GetSection(i);
  1500. IF (p.type = Sections.CodeSection) OR (p.type= Sections.BodyCodeSection) THEN
  1501. binarySection := p.resolved;
  1502. IF binarySection.finally >= 0 THEN
  1503. pcFrom := p.offset;
  1504. pcTo := binarySection.finally+pcFrom;
  1505. pcHandler := binarySection.finally+pcFrom;
  1506. w.Char(0FEX);
  1507. w.RawNum(pcFrom);
  1508. w.RawNum(pcTo);
  1509. w.RawNum(pcHandler);
  1510. INC(exTableLen);
  1511. END;
  1512. END
  1513. END;
  1514. END ExceptionTable;
  1515. PROCEDURE PtrsInProcBlock;
  1516. VAR
  1517. i, counter: LONGINT; destination: Section;
  1518. PROCEDURE PointerOffsets(destination : Section);
  1519. VAR
  1520. numberPointers,numberPointersPos: LONGINT; procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  1521. variable: SyntaxTree.Variable; parameter: SyntaxTree.Parameter;
  1522. BEGIN
  1523. (*!
  1524. ASSERT(destination.offset <= destination.beginOffset);
  1525. ASSERT(destination.beginOffset <= destination.endOffset);
  1526. *)
  1527. w.RawNum((destination.offset ));
  1528. w.RawNum(destination.offset+destination.resolved.validPAFEnter);
  1529. w.RawNum(destination.offset+destination.resolved.validPAFExit);
  1530. (*!
  1531. w.RawNum(destination.beginOffset);
  1532. w.RawNum(destination.endOffset);
  1533. *)
  1534. numberPointers := 0;
  1535. numberPointersPos := w.Pos();
  1536. w.RawLInt(0);
  1537. procedure := destination.symbol(SyntaxTree.Procedure);
  1538. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1539. variable := procedure.procedureScope.firstVariable;
  1540. WHILE(variable # NIL) DO
  1541. IF ~(variable.untraced) THEN
  1542. OutPointers(variable.offsetInBits DIV 8,variable.type,numberPointers);
  1543. END;
  1544. variable := variable.nextVariable
  1545. END;
  1546. parameter := procedureType.firstParameter;
  1547. WHILE(parameter # NIL) DO
  1548. IF ~(parameter.untraced) THEN
  1549. OutPointers(parameter.offsetInBits DIV 8,parameter.type,numberPointers);
  1550. END;
  1551. parameter := parameter.nextParameter;
  1552. END;
  1553. (*
  1554. parameter := procedureType.selfParameter;
  1555. IF parameter # NIL THEN
  1556. OutPointers(parameter.offsetInBits DIV 8,parameter.type,numberPointers);
  1557. END;
  1558. *)
  1559. RawLIntAt(numberPointersPos,numberPointers);
  1560. IF numberPointers > maxPtrs THEN
  1561. maxPtrs := numberPointers
  1562. END;
  1563. END PointerOffsets;
  1564. BEGIN
  1565. w.Char(08FX);
  1566. IF Trace THEN D.Str("FoxObjectFile.PtrsInProcBlock"); D.Ln; END;
  1567. maxPtrs := 0;
  1568. counter := 0;
  1569. FOR i := 0 TO symbols.Length() - 1 DO
  1570. destination := symbols.GetSection(i);
  1571. IF (destination.type # Sections.InitCodeSection) & (destination.symbol # NIL) & (destination.symbol IS SyntaxTree.Procedure) & ~destination.symbol(SyntaxTree.Procedure).isInline THEN
  1572. IF Trace THEN D.Str("pointers in "); Basic.WriteSegmentedName(D.Log,destination.name); D.Ln END;
  1573. PointerOffsets(destination);
  1574. INC(counter);
  1575. END
  1576. END;
  1577. numberProcs := counter;
  1578. END PtrsInProcBlock;
  1579. PROCEDURE References;
  1580. CONST
  1581. rfDirect = 1X; rfIndirect = 3X;
  1582. rfStaticArray= 12X; rfDynamicArray=14X; rfOpenArray=15X;
  1583. rfByte = 1X; rfBoolean = 2X; rfChar8=3X; rfShortint=04X; rfInteger = 05X; rfLongint = 06X;
  1584. rfReal = 07X; rfLongreal = 08X; rfSet = 09X; rfDelegate = 0EX; rfString = 0FH; rfPointer = 0DX; rfHugeint = 10X;
  1585. rfChar16=11X; rfChar32=12X; rfAll=13X; rfSame=14X; rfRange=15X; rfRecord=16X; rfComplex = 17X; rfLongcomplex = 18X;
  1586. rfRecordPointer=1DX;
  1587. rfArrayFlag = 80X;
  1588. VAR
  1589. start, i: LONGINT; s: Section;
  1590. PROCEDURE BaseType(type: SyntaxTree.Type): CHAR;
  1591. VAR char: CHAR;
  1592. BEGIN
  1593. IF type = NIL THEN char := rfLongint
  1594. ELSIF type IS SyntaxTree.ByteType THEN char := rfByte
  1595. ELSIF type IS SyntaxTree.BooleanType THEN char := rfBoolean
  1596. ELSIF type IS SyntaxTree.CharacterType THEN
  1597. IF type.sizeInBits = 8 THEN char := rfChar8
  1598. ELSIF type.sizeInBits = 16 THEN char := rfChar16
  1599. ELSIF type.sizeInBits = 32 THEN char := rfChar32
  1600. END;
  1601. ELSIF (type IS SyntaxTree.IntegerType) OR (type IS SyntaxTree.AddressType) OR (type IS SyntaxTree.SizeType) THEN
  1602. IF type.sizeInBits = 8 THEN char := rfShortint
  1603. ELSIF type.sizeInBits = 16 THEN char := rfInteger
  1604. ELSIF type.sizeInBits = 32 THEN char := rfLongint
  1605. ELSIF type.sizeInBits =64 THEN char := rfHugeint
  1606. END;
  1607. ELSIF type IS SyntaxTree.SizeType THEN char := rfLongint
  1608. ELSIF type IS SyntaxTree.FloatType THEN
  1609. IF type.sizeInBits = 32 THEN char := rfReal
  1610. ELSIF type.sizeInBits = 64 THEN char := rfLongreal
  1611. END;
  1612. ELSIF type IS SyntaxTree.ComplexType THEN
  1613. IF type.sizeInBits = 64 THEN char := rfComplex
  1614. ELSIF type.sizeInBits = 128 THEN char := rfLongcomplex
  1615. END;
  1616. ELSIF type IS SyntaxTree.SetType THEN char := rfSet
  1617. ELSIF type IS SyntaxTree.AnyType THEN char := rfPointer
  1618. ELSIF type IS SyntaxTree.ObjectType THEN char := rfPointer
  1619. ELSIF type IS SyntaxTree.PointerType THEN char := rfPointer
  1620. ELSIF type IS SyntaxTree.ProcedureType THEN char := rfDelegate
  1621. ELSIF type IS SyntaxTree.RangeType THEN char := rfRange
  1622. ELSE char := rfShortint; (*RETURN (* ARRAY OF unknown (record): do not write anything *)*)
  1623. END;
  1624. RETURN char
  1625. END BaseType;
  1626. PROCEDURE RecordType(type: SyntaxTree.RecordType);
  1627. VAR destination: Section; name: SyntaxTree.IdentifierString;
  1628. BEGIN
  1629. destination := symbols.BySymbol(type.typeDeclaration);
  1630. IF destination = NIL THEN destination := importedSymbols.BySymbol(type.typeDeclaration) END;
  1631. IF destination = NIL THEN
  1632. (* imported unused record type *)
  1633. w.Char(0X); (* nil type *)
  1634. type.typeDeclaration.GetName(name);
  1635. (*
  1636. this happens when a symbol from a different module is used but the type desciptor is not necessary to be present in the current module
  1637. D.Str("Warning: Unreferenced record type encountered: "); D.String(name); D.String(" unused? "); D.Ln;
  1638. *)
  1639. ELSE
  1640. IF type.pointerType # NIL THEN
  1641. w.Char(rfRecordPointer)
  1642. ELSE
  1643. w.Char(rfRecord);
  1644. END;
  1645. w.RawNum((destination.offset ));
  1646. END;
  1647. END RecordType;
  1648. PROCEDURE StaticArrayLength(type: SyntaxTree.ArrayType; VAR baseType: SyntaxTree.Type): LONGINT;
  1649. BEGIN
  1650. baseType := type.arrayBase.resolved;
  1651. IF type.form = SyntaxTree.Static THEN
  1652. IF baseType IS SyntaxTree.ArrayType THEN
  1653. RETURN type.staticLength * StaticArrayLength(baseType(SyntaxTree.ArrayType),baseType)
  1654. ELSE
  1655. RETURN type.staticLength
  1656. END
  1657. ELSE
  1658. RETURN 0
  1659. END;
  1660. END StaticArrayLength;
  1661. PROCEDURE ArrayType(type: SyntaxTree.ArrayType);
  1662. VAR length: LONGINT; baseType: SyntaxTree.Type; char: CHAR;
  1663. BEGIN
  1664. length := StaticArrayLength(type, baseType);
  1665. char := BaseType(baseType);
  1666. IF type.form # SyntaxTree.Open THEN
  1667. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1668. w.RawNum(length)
  1669. ELSE
  1670. length :=0;
  1671. (*length := 1+SemanticChecker.Dimension(type,{SyntaxTree.Open});*)
  1672. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1673. w.RawNum(length)
  1674. END;
  1675. END ArrayType;
  1676. PROCEDURE StaticMathArrayLength(type: SyntaxTree.MathArrayType; VAR baseType: SyntaxTree.Type): LONGINT;
  1677. BEGIN
  1678. baseType := type.arrayBase;
  1679. IF baseType # NIL THEN
  1680. baseType := baseType.resolved;
  1681. END;
  1682. IF type.form = SyntaxTree.Static THEN
  1683. IF (baseType # NIL) & (baseType IS SyntaxTree.MathArrayType) THEN
  1684. RETURN type.staticLength * StaticMathArrayLength(baseType(SyntaxTree.MathArrayType),baseType)
  1685. ELSE
  1686. RETURN type.staticLength
  1687. END
  1688. ELSE
  1689. RETURN 0
  1690. END;
  1691. END StaticMathArrayLength;
  1692. PROCEDURE MathArrayType(type: SyntaxTree.MathArrayType);
  1693. VAR length: LONGINT; baseType: SyntaxTree.Type; char: CHAR;
  1694. BEGIN
  1695. length := StaticMathArrayLength(type, baseType);
  1696. char := BaseType(baseType);
  1697. IF type.form = SyntaxTree.Open THEN
  1698. char := BaseType(module.system.addressType);
  1699. length := 5+2*SemanticChecker.Dimension(type,{SyntaxTree.Open});
  1700. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1701. w.RawNum(length)
  1702. ELSIF type.form=SyntaxTree.Tensor THEN
  1703. char := BaseType(module.system.addressType);
  1704. w.Char(CHR(ORD(char)));
  1705. ELSE
  1706. w.Char(CHR(ORD(char)+ORD(rfArrayFlag)));
  1707. w.RawNum(length)
  1708. END;
  1709. END MathArrayType;
  1710. PROCEDURE Type(type: SyntaxTree.Type);
  1711. BEGIN
  1712. IF type = NIL THEN w.Char(0X); RETURN ELSE type := type.resolved END;
  1713. IF type IS SyntaxTree.BasicType THEN
  1714. w.Char(BaseType(type))
  1715. ELSIF type IS SyntaxTree.RecordType THEN
  1716. RecordType(type(SyntaxTree.RecordType));
  1717. ELSIF type IS SyntaxTree.ArrayType THEN
  1718. ArrayType(type(SyntaxTree.ArrayType))
  1719. ELSIF type IS SyntaxTree.EnumerationType THEN
  1720. w.Char(BaseType(module.system.longintType))
  1721. ELSIF type IS SyntaxTree.PointerType THEN
  1722. IF type(SyntaxTree.PointerType).pointerBase IS SyntaxTree.RecordType THEN
  1723. RecordType(type(SyntaxTree.PointerType).pointerBase(SyntaxTree.RecordType));
  1724. ELSE
  1725. w.Char(BaseType(type))
  1726. END;
  1727. ELSIF type IS SyntaxTree.ProcedureType THEN
  1728. w.Char(BaseType(type));
  1729. ELSIF type IS SyntaxTree.MathArrayType THEN
  1730. MathArrayType(type(SyntaxTree.MathArrayType));
  1731. ELSE HALT(200)
  1732. END;
  1733. END Type;
  1734. PROCEDURE WriteVariable(variable: SyntaxTree.Variable; indirect: BOOLEAN);
  1735. VAR name: ARRAY 256 OF CHAR; s: Section;
  1736. BEGIN
  1737. IF variable.externalName # NIL THEN RETURN END;
  1738. IF indirect THEN w.Char(rfIndirect) ELSE w.Char(rfDirect) END;
  1739. variable.GetName(name);
  1740. Type(variable.type);
  1741. s := symbols.BySymbol(variable);
  1742. IF s # NIL THEN (* global variable *)
  1743. w.RawNum( s.offset );
  1744. ELSE
  1745. w.RawNum( variable.offsetInBits DIV 8 );
  1746. END;
  1747. w.RawString(name);
  1748. END WriteVariable;
  1749. PROCEDURE WriteParameter(variable: SyntaxTree.Parameter; indirect: BOOLEAN);
  1750. VAR name: ARRAY 256 OF CHAR;
  1751. BEGIN
  1752. IF indirect THEN w.Char(rfIndirect) ELSE w.Char(rfDirect) END;
  1753. variable.GetName(name);
  1754. Type(variable.type);
  1755. w.RawNum((variable.offsetInBits DIV 8));
  1756. variable.GetName(name);
  1757. w.RawString(name);
  1758. END WriteParameter;
  1759. PROCEDURE ReturnType(type: SyntaxTree.Type);
  1760. BEGIN
  1761. IF type = NIL THEN w.Char(0X); RETURN ELSE type := type.resolved END;
  1762. IF type IS SyntaxTree.ArrayType THEN
  1763. WITH type: SyntaxTree.ArrayType DO
  1764. IF type.form = SyntaxTree.Static THEN w.Char(rfStaticArray)
  1765. ELSE w.Char(rfOpenArray)
  1766. END
  1767. END
  1768. ELSIF type IS SyntaxTree.MathArrayType THEN
  1769. WITH type: SyntaxTree.MathArrayType DO
  1770. IF type.form = SyntaxTree.Static THEN w.Char(rfStaticArray)
  1771. ELSE w.Char(rfOpenArray)
  1772. END
  1773. END
  1774. ELSIF type IS SyntaxTree.RecordType THEN
  1775. w.Char(rfRecord);
  1776. ELSE
  1777. w.Char(BaseType(type));
  1778. END;
  1779. END ReturnType;
  1780. PROCEDURE DeclarationName(typeDeclaration: SyntaxTree.TypeDeclaration; VAR name: ARRAY OF CHAR);
  1781. BEGIN
  1782. IF typeDeclaration = NIL THEN COPY("@ANONYMOUS",name)
  1783. ELSE typeDeclaration.GetName(name)
  1784. END;
  1785. END DeclarationName;
  1786. PROCEDURE Procedure(s: Section);
  1787. VAR procedure: SyntaxTree.Procedure; procedureType: SyntaxTree.ProcedureType;
  1788. parameter: SyntaxTree.Parameter; variable: SyntaxTree.Variable;
  1789. name,recordName: ARRAY 256 OF CHAR;
  1790. record: SyntaxTree.RecordType; i: LONGINT;
  1791. BEGIN
  1792. procedure := s.symbol(SyntaxTree.Procedure); (*! check for variable or type symbol for object body *)
  1793. (*procedure.name,name);*)
  1794. Global.GetSymbolNameInScope(procedure,moduleScope,name);
  1795. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1796. w.Char(0F9X);
  1797. w.RawNum((s.offset ));
  1798. w.RawNum(procedureType.numberParameters);
  1799. ReturnType(procedureType.returnType);
  1800. w.RawNum(0); (*! level *)
  1801. w.RawNum(0);
  1802. (*
  1803. IF procedure.scope IS SyntaxTree.RecordScope THEN (* add object name *)
  1804. record := procedure.scope(SyntaxTree.RecordScope).ownerRecord;
  1805. recordName := "";
  1806. IF record.pointerType # NIL THEN
  1807. DeclarationName(record.pointerType.typeDeclaration,recordName);
  1808. ELSE
  1809. DeclarationName(record.typeDeclaration,recordName);
  1810. END;
  1811. i := 0;
  1812. WHILE recordName[i] # 0X DO
  1813. w.Char(recordName[i]); INC(i);
  1814. END;
  1815. w.Char(".");
  1816. END;
  1817. *)
  1818. w.RawString(name);
  1819. parameter := procedureType.firstParameter;
  1820. WHILE(parameter # NIL) DO
  1821. WriteParameter(parameter,parameter.kind # SyntaxTree.ValueParameter); (*!treat exceptions !*)
  1822. parameter := parameter.nextParameter;
  1823. END;
  1824. (*
  1825. parameter := procedureType.selfParameter;
  1826. IF parameter # NIL THEN
  1827. WriteParameter(parameter,parameter.kind # SyntaxTree.ValueParameter); (*!treat exceptions !*)
  1828. END;
  1829. *)
  1830. variable := procedure.procedureScope.firstVariable;
  1831. WHILE(variable # NIL) DO
  1832. WriteVariable(variable,FALSE);
  1833. variable := variable.nextVariable;
  1834. END;
  1835. END Procedure;
  1836. PROCEDURE Scope(s: Section);
  1837. VAR variable: SyntaxTree.Variable;
  1838. BEGIN
  1839. w.Char(0F8X);
  1840. w.RawNum((s.offset ));
  1841. w.RawString("$$");
  1842. variable := moduleScope.firstVariable;
  1843. WHILE(variable # NIL) DO
  1844. WriteVariable(variable,FALSE);
  1845. variable := variable.nextVariable;
  1846. END;
  1847. END Scope;
  1848. BEGIN
  1849. start := w.Pos();
  1850. w.Char(08CX);
  1851. FOR i := 0 TO symbols.Length() - 1 DO
  1852. s := symbols.GetSection(i);
  1853. IF (s.symbol = moduleScope.bodyProcedure) THEN
  1854. Scope(s) (*! must be first procedure in ref section *)
  1855. END
  1856. END;
  1857. FOR i := 0 TO symbols.Length() - 1 DO
  1858. s := symbols.GetSection(i);
  1859. IF (s.symbol = moduleScope.bodyProcedure) THEN (* already done, see above *)
  1860. ELSIF(s.symbol # NIL) & (s.symbol IS SyntaxTree.Procedure) & ~s.symbol(SyntaxTree.Procedure).isInline THEN
  1861. Procedure(s)
  1862. END
  1863. END;
  1864. refSize := w.Pos()-start;
  1865. END References;
  1866. PROCEDURE LinkFixups;
  1867. VAR
  1868. section: Section; symbol: SyntaxTree.Symbol; fixups, i: LONGINT; fixup: Fixup; bfixup: BinaryCode.Fixup;
  1869. PROCEDURE Put32(code: ByteArray; offset: LONGINT; number: LONGINT);
  1870. BEGIN
  1871. code[offset] := CHR(number MOD 256);
  1872. INC(offset); number := number DIV 256;
  1873. code[offset] := CHR(number MOD 256);
  1874. INC(offset); number := number DIV 256;
  1875. code[offset] := CHR(number MOD 256);
  1876. INC(offset); number := number DIV 256;
  1877. code[offset] := CHR(number MOD 256);
  1878. END Put32;
  1879. PROCEDURE Link(first: Fixup);
  1880. VAR this,prev: LONGINT;fixup: Fixup;
  1881. CONST Sentinel = LONGINT(0FFFFFFFFH);
  1882. BEGIN
  1883. fixup := first;
  1884. prev := -1;
  1885. WHILE fixup # NIL DO
  1886. this := (fixup.fixupSection.offset +fixup.fixup.offset );
  1887. IF prev # -1 THEN
  1888. Put32(code,prev,this);
  1889. IF Trace THEN
  1890. D.String("link: "); D.Int(prev,1); D.String(":"); D.Int(this,1); D.Ln;
  1891. END;
  1892. END;
  1893. prev := this;
  1894. fixup := fixup.nextFixup;
  1895. END;
  1896. IF prev # -1 THEN
  1897. Put32(code,prev,Sentinel);
  1898. IF Trace THEN
  1899. D.String("link: "); D.Int(prev,1); D.String(":"); D.Int(Sentinel,1); D.Ln;
  1900. END;
  1901. END;
  1902. END Link;
  1903. BEGIN
  1904. IF Trace THEN D.Str("LinkFixups"); D.Ln; END;
  1905. FOR i := 0 TO importedSymbols.Length()-1 DO
  1906. section := importedSymbols.GetSection(i);
  1907. symbol := section.symbol;
  1908. IF (symbol # NIL) & (symbol IS SyntaxTree.Procedure) THEN
  1909. Link(section.fixups);
  1910. END;
  1911. END;
  1912. END LinkFixups;
  1913. PROCEDURE MakeSections;
  1914. VAR i: LONGINT; fixup: BinaryCode.Fixup; section: Sections.Section; symbol: Section;
  1915. imported: BOOLEAN;
  1916. PROCEDURE Enter(section: Sections.Section; symbols: SectionList; VAR symbol: Section): BOOLEAN;
  1917. BEGIN
  1918. IF section # NIL THEN
  1919. symbol := symbols.AddSection(section.name);
  1920. symbol.isCaseTable := section.isCaseTable;
  1921. symbol.referenced := section.referenced;
  1922. symbol.offset := section.offset;
  1923. symbol.type := section.type;
  1924. symbol.resolved := section(IntermediateCode.Section).resolved;
  1925. IF (section.symbol # NIL) & (symbol.symbol = NIL) THEN
  1926. symbol.symbol := section.symbol;
  1927. symbols.symbolLookup.Put(symbol.symbol, symbol)
  1928. END;
  1929. RETURN TRUE
  1930. ELSE
  1931. RETURN FALSE
  1932. END;
  1933. END Enter;
  1934. BEGIN
  1935. NEW(symbols); NEW(importedSymbols);
  1936. (* enter all sections first to keep ordering *)
  1937. FOR i := 0 TO module.allSections.Length() - 1 DO
  1938. section := module.allSections.GetSection(i);
  1939. IF (section.type # Sections.InlineCodeSection) & (section.type # Sections.InitCodeSection) & ~section.isCaseTable THEN
  1940. IF Enter(section, symbols,symbol) THEN END;
  1941. END;
  1942. END;
  1943. FOR i := 0 TO module.allSections.Length() - 1 DO
  1944. section := module.allSections.GetSection(i);
  1945. IF (section.type # Sections.InlineCodeSection) & (section.type # Sections.InitCodeSection) & ~section.isCaseTable THEN
  1946. (* IF Enter(section, symbols,symbol) THEN END;*)
  1947. fixup := section(IntermediateCode.Section).resolved.fixupList.firstFixup;
  1948. WHILE (fixup # NIL) DO
  1949. IF Enter(module.allSections.FindByName(fixup.symbol.name), symbols,symbol) THEN
  1950. symbol.AddFixup(fixup, section);
  1951. END;
  1952. IF Enter(module.importedSections.FindByName(fixup.symbol.name), importedSymbols,symbol) THEN
  1953. symbol.AddFixup(fixup, section)
  1954. END;
  1955. fixup := fixup.nextFixup;
  1956. END
  1957. END
  1958. END;
  1959. IF Trace THEN
  1960. D.String("imported sections(module) "); D.Ln;
  1961. module.importedSections.Dump(D.Log); D.Ln;
  1962. D.String("sections(module) "); D.Ln;
  1963. module.allSections.Dump(D.Log); D.Ln;
  1964. D.String("imported: "); D.Ln; importedSymbols.Dump(D.Log);
  1965. D.String("not imported: "); D.Ln; symbols.Dump(D.Log);
  1966. D.Ln;
  1967. END;
  1968. END MakeSections;
  1969. (* ObjectFile =
  1970. ofFileTag ofNoZeroCompression ofFileVersion
  1971. SymbolFile
  1972. Header
  1973. Entries
  1974. Commands
  1975. Pointers
  1976. Imports
  1977. VarConstLinks
  1978. Links
  1979. Constants
  1980. Exports
  1981. Code
  1982. Use
  1983. Types
  1984. ExceptionTable
  1985. PtrsInProcBlock
  1986. References
  1987. *)
  1988. BEGIN
  1989. MakeSectionOffsets(module,constSize,dataSize,codeSize,caseTableSize,const,code);
  1990. MakeSections;
  1991. (* from here on we do not need IntermediateCode.Sections any more *)
  1992. LinkFixups;
  1993. IF Trace THEN module.Dump(D.Log);D.Ln; D.Update; END;
  1994. NEW(fingerprinter,module.system);
  1995. (* module.module.name,moduleName);*)
  1996. Global.ModuleFileName(module.module.name,module.module.context,moduleName);
  1997. NEW(crc32);
  1998. IF Trace THEN D.Str("module: "); D.Str(moduleName); D.Ln END;
  1999. moduleScope := module.module.moduleScope;
  2000. w.Char(ofFileTag);
  2001. w.Char(ofNoZeroCompress);
  2002. w.Char(ofFileVersion);
  2003. SymbolFile;
  2004. Header; Entries; Commands; Pointers; Imports; VarConstLinks; Links;
  2005. Constants; Exports; Code; Use; Types; ExceptionTable; PtrsInProcBlock; References;
  2006. endPos := w.Pos();
  2007. w.SetPos(headerPos);
  2008. crc := crc32.GetCRC();
  2009. Header;
  2010. w.SetPos(endPos);
  2011. w.Update;
  2012. END WriteObjectFile;
  2013. PROCEDURE Get*(): Formats.ObjectFileFormat;
  2014. VAR objectFileFormat: ObjectFileFormat;
  2015. BEGIN NEW(objectFileFormat); RETURN objectFileFormat
  2016. END Get;
  2017. BEGIN
  2018. SysCallMap[CaseTable] := 0FFX;
  2019. SysCallMap[ProcAddr] := 0FEX;
  2020. SysCallMap[NewRec] := 0FDX;
  2021. SysCallMap[NewSys] := 0FCX;
  2022. SysCallMap[NewArr] := 0FBX;
  2023. SysCallMap[Start] := CHR(250);
  2024. SysCallMap[Await] := CHR(249);
  2025. SysCallMap[Lock] := CHR(247);
  2026. SysCallMap[Unlock] := CHR(246);
  2027. SysCallMap[InterfaceLookup] := CHR(245);
  2028. SysCallMap[RegisterInterface] := CHR(244);
  2029. SysCallMap[GetProcedure] := CHR(243);
  2030. END FoxBinaryObjectFile.