ogwasm.pas 254 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534
  1. {
  2. Copyright (c) 2021 by Nikolay Nikolov
  3. Contains the WebAssembly binary module format reader and writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogwasm;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,cpubase,
  25. { assembler }
  26. aasmbase,assemble,aasmcpu,
  27. { WebAssembly module format definitions }
  28. wasmbase,
  29. { output }
  30. ogbase,
  31. owbase;
  32. type
  33. TWasmObjSymbolExtraData = class;
  34. TGlobalInitializer = record
  35. case typ:TWasmBasicType of
  36. wbt_i32: (init_i32: Int32);
  37. wbt_i64: (init_i64: Int64);
  38. wbt_f32: (init_f32: Single);
  39. wbt_f64: (init_f64: Double);
  40. end;
  41. { TWasmObjSymbolLinkingData }
  42. TWasmObjSymbolLinkingData = class
  43. public
  44. ImportModule: ansistring;
  45. ImportName: ansistring;
  46. FuncType: TWasmFuncType;
  47. ExeFunctionIndex: Integer;
  48. ExeIndirectFunctionTableIndex: Integer;
  49. ExeTypeIndex: Integer;
  50. ExeTagIndex: Integer;
  51. GlobalType: TWasmBasicType;
  52. GlobalIsMutable: Boolean;
  53. GlobalInitializer: TGlobalInitializer;
  54. IsExported: Boolean;
  55. ExportName: ansistring;
  56. constructor Create;
  57. destructor Destroy;override;
  58. end;
  59. { TWasmObjSymbol }
  60. TWasmObjSymbol = class(TObjSymbol)
  61. FuncIndex: Integer;
  62. SymbolIndex: Integer;
  63. GlobalIndex: Integer;
  64. TagIndex: Integer;
  65. AliasOf: ansistring;
  66. ExtraData: TWasmObjSymbolExtraData;
  67. LinkingData: TWasmObjSymbolLinkingData;
  68. TlsGlobalSym: TWasmObjSymbol;
  69. TlsDataSym: TWasmObjSymbol;
  70. constructor create(AList:TFPHashObjectList;const AName:string);override;
  71. destructor Destroy;override;
  72. function IsAlias: Boolean;
  73. end;
  74. { TWasmObjRelocation }
  75. TWasmObjRelocation = class(TObjRelocation)
  76. public
  77. TypeIndex: Integer;
  78. Addend: LongInt;
  79. { used during linking }
  80. FuncType: TWasmFuncType;
  81. ExeTypeIndex: Integer;
  82. IsFunctionOffsetI32: Boolean;
  83. constructor CreateTypeIndex(ADataOffset:TObjSectionOfs; ATypeIndex: Integer);
  84. constructor CreateFuncType(ADataOffset:TObjSectionOfs; AFuncType: TWasmFuncType);
  85. destructor Destroy;override;
  86. function ToString:ansistring;override;
  87. end;
  88. { TWasmObjSymbolExtraData }
  89. TWasmObjSymbolExtraData = class(TFPHashObject)
  90. TypeIdx: Integer;
  91. ExceptionTagTypeIdx: Integer;
  92. ImportModule: ansistring;
  93. ImportName: ansistring;
  94. ExportName: ansistring;
  95. GlobalType: TWasmBasicType;
  96. GlobalIsImmutable: Boolean;
  97. Locals: array of TWasmBasicType;
  98. EncodedLocals: tdynamicarray;
  99. constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  100. destructor Destroy; override;
  101. procedure AddLocals(alocals: TWasmLocalsDynArray);
  102. end;
  103. { TWasmObjSection }
  104. TWasmObjSection = class(TObjSection)
  105. public
  106. SegIdx: Integer;
  107. SegSymIdx: Integer;
  108. SegOfs: qword;
  109. FileSectionOfs: qword;
  110. MainFuncSymbol: TWasmObjSymbol;
  111. CustomSectionIdx: Integer;
  112. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
  113. function IsCode: Boolean;
  114. function IsData: Boolean;
  115. function IsDebug: Boolean;
  116. end;
  117. { TWasmFuncTypeTable }
  118. TWasmFuncTypeTable = class
  119. private
  120. FFuncTypes: array of TWasmFuncType;
  121. function GetCount: Integer;
  122. function GetItem(Index: Integer): TWasmFuncType;
  123. public
  124. destructor Destroy; override;
  125. function AddOrGetFuncType(wft: TWasmFuncType): integer;
  126. procedure WriteTo(d: tdynamicarray);
  127. property Count: Integer read GetCount;
  128. property Items[Index: Integer]: TWasmFuncType read GetItem; default;
  129. end;
  130. { TWasmObjData }
  131. TWasmObjData = class(TObjData)
  132. private
  133. FFuncTypes: TWasmFuncTypeTable;
  134. FObjSymbolsExtraDataList: TFPHashObjectList;
  135. FLastFuncName: string;
  136. function is_smart_section(atype:TAsmSectiontype):boolean;
  137. function sectionname_gas(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  138. public
  139. constructor create(const n:string);override;
  140. destructor destroy; override;
  141. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  142. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
  143. function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
  144. function globalref(asmsym:TAsmSymbol):TObjSymbol;
  145. function ExceptionTagRef(asmsym:TAsmSymbol):TObjSymbol;
  146. procedure DeclareGlobalType(gt: tai_globaltype);
  147. procedure DeclareFuncType_Pass0(ft: tai_functype);
  148. procedure DeclareFuncType_Pass1(ft: tai_functype);
  149. procedure DeclareFuncType_Pass2(ft: tai_functype);
  150. procedure DeclareTagType(tt: tai_tagtype);
  151. procedure DeclareExportName(en: tai_export_name);
  152. procedure DeclareImportModule(aim: tai_import_module);
  153. procedure DeclareImportName(ain: tai_import_name);
  154. procedure DeclareLocals_Pass0(al: tai_local);
  155. procedure DeclareLocals_Pass1(al: tai_local);
  156. procedure WriteLocals_Pass2(al: tai_local);
  157. procedure symbolpairdefine(akind: TSymbolPairKind;const asym, avalue: string);override;
  158. property FuncTypes: TWasmFuncTypeTable read FFuncTypes;
  159. end;
  160. { TWasmObjOutput }
  161. TWasmObjOutput = class(tObjOutput)
  162. private
  163. FData: TWasmObjData;
  164. FWasmRelocationCodeTable: tdynamicarray;
  165. FWasmRelocationCodeTableEntriesCount: Integer;
  166. FWasmRelocationDataTable: tdynamicarray;
  167. FWasmRelocationDataTableEntriesCount: Integer;
  168. FWasmRelocationDebugFrameTable: tdynamicarray;
  169. FWasmRelocationDebugFrameTableEntriesCount: Integer;
  170. FWasmRelocationDebugInfoTable: tdynamicarray;
  171. FWasmRelocationDebugInfoTableEntriesCount: Integer;
  172. FWasmRelocationDebugLineTable: tdynamicarray;
  173. FWasmRelocationDebugLineTableEntriesCount: Integer;
  174. FWasmRelocationDebugAbbrevTable: tdynamicarray;
  175. FWasmRelocationDebugAbbrevTableEntriesCount: Integer;
  176. FWasmRelocationDebugArangesTable: tdynamicarray;
  177. FWasmRelocationDebugArangesTableEntriesCount: Integer;
  178. FWasmRelocationDebugRangesTable: tdynamicarray;
  179. FWasmRelocationDebugRangesTableEntriesCount: Integer;
  180. FWasmRelocationDebugStrTable: tdynamicarray;
  181. FWasmRelocationDebugStrTableEntriesCount: Integer;
  182. FWasmSymbolTable: tdynamicarray;
  183. FWasmSymbolTableEntriesCount: Integer;
  184. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  185. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  186. FWasmLinkingSubsections: array [low(TWasmLinkingSubsectionType)..high(TWasmLinkingSubsectionType)] of tdynamicarray;
  187. procedure WriteWasmSection(wsid: TWasmSectionID);
  188. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  189. function IsExternalFunction(sym: TObjSymbol): Boolean;
  190. function IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  191. procedure WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  192. procedure WriteSymbolTable;
  193. procedure WriteRelocationCodeTable(CodeSectionIndex: Integer);
  194. procedure WriteRelocationDataTable(DataSectionIndex: Integer);
  195. procedure MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  196. procedure WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  197. procedure DoRelocations;
  198. procedure WriteRelocations;
  199. function FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  200. protected
  201. function writeData(Data:TObjData):boolean;override;
  202. public
  203. constructor create(AWriter:TObjectWriter);override;
  204. destructor destroy;override;
  205. end;
  206. { TWasmObjInput }
  207. TWasmObjInput = class(TObjInput)
  208. private
  209. FFuncTypes: array of TWasmFuncType;
  210. public
  211. constructor create;override;
  212. destructor Destroy;override;
  213. class function CanReadObjData(AReader:TObjectreader):boolean;override;
  214. function ReadObjData(AReader:TObjectreader;out ObjData:TObjData):boolean;override;
  215. end;
  216. { TWasmExeOutput }
  217. TWasmExeOutput = class(TExeOutput)
  218. private
  219. const
  220. DataSections: array [1..3] of string = (
  221. '.rodata',
  222. '.data',
  223. 'fpc.resources');
  224. WasmPageSize = 65536;
  225. type
  226. TCustomSectionNameMapEntry = record
  227. idx: UInt32;
  228. name: string;
  229. end;
  230. TCustomSectionNameMap = array of TCustomSectionNameMapEntry;
  231. private
  232. FImports: TFPHashObjectList;
  233. FFuncTypes: TWasmFuncTypeTable;
  234. FFunctionImports: array of record
  235. ModName: ansistring;
  236. Name: ansistring;
  237. TypeIdx: uint32;
  238. end;
  239. FTagImports: array of record
  240. end;
  241. FIndirectFunctionTable: array of record
  242. FuncIdx: Integer;
  243. end;
  244. FImportedMemories: array of record
  245. ModName: ansistring;
  246. Name: ansistring;
  247. MemType: TWasmMemoryType;
  248. end;
  249. FMemories: array of TWasmMemoryType;
  250. FRelocationPass: Integer;
  251. FWasmSections: array [TWasmSectionID] of tdynamicarray;
  252. FWasmCustomSections: array [TWasmCustomSectionType] of tdynamicarray;
  253. FWasmNameSubsections: array [TWasmNameSubsectionType] of tdynamicarray;
  254. FStackPointerSym: TWasmObjSymbol;
  255. FTlsBaseSym: TWasmObjSymbol;
  256. FTlsSizeSym: TWasmObjSymbol;
  257. FTlsAlignSym: TWasmObjSymbol;
  258. FInitTlsFunctionSym: TWasmObjSymbol;
  259. FInitSharedMemoryFunctionSym: TWasmObjSymbol;
  260. FMinMemoryPages,
  261. FMaxMemoryPages: Integer;
  262. { use for the Name section }
  263. FFunctionNameMap: TCustomSectionNameMap;
  264. FGlobalNameMap: TCustomSectionNameMap;
  265. FDataNameMap: TCustomSectionNameMap;
  266. FTagNameMap: TCustomSectionNameMap;
  267. procedure AddToNameMap(var nm: TCustomSectionNameMap; aidx: UInt32; const aname: string);
  268. procedure AddToFunctionNameMap(aidx: UInt32; const aname: string);
  269. procedure AddToGlobalNameMap(aidx: UInt32; const aname: string);
  270. procedure AddToDataNameMap(aidx: UInt32; const aname: string);
  271. procedure AddToTagNameMap(aidx: UInt32; const aname: string);
  272. procedure WriteWasmSection(wsid: TWasmSectionID);
  273. procedure WriteWasmSectionIfNotEmpty(wsid: TWasmSectionID);
  274. procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  275. procedure PrepareImports;
  276. procedure PrepareFunctions;
  277. procedure PrepareTags;
  278. function AddOrGetIndirectFunctionTableIndex(FuncIdx: Integer): integer;
  279. procedure SetStackPointer;
  280. procedure SetTlsSizeAlignAndBase;
  281. procedure SetThreadVarGlobalsInitValues;
  282. procedure GenerateCode_InitTls;
  283. procedure GenerateCode_InitSharedMemory;
  284. procedure GenerateCode_InvokeHelper;
  285. procedure WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
  286. procedure WriteMemoryTo(dest: tdynamicarray;const MemType:TWasmMemoryType);
  287. function Memory2String(const MemType:TWasmMemoryType):string;
  288. procedure WriteMap_TypeSection;
  289. procedure WriteMap_IndirectFunctionTable;
  290. protected
  291. function writeData:boolean;override;
  292. procedure DoRelocationFixup(objsec:TObjSection);override;
  293. public
  294. constructor create;override;
  295. destructor destroy;override;
  296. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  297. procedure AfterUnusedSectionRemoval;override;
  298. procedure MemPos_ExeSection(const aname:string);override;
  299. procedure Load_Symbol(const aname: string);override;
  300. end;
  301. { TWasmAssembler }
  302. TWasmAssembler = class(tinternalassembler)
  303. constructor create(info: pasminfo; smart:boolean);override;
  304. end;
  305. implementation
  306. uses
  307. cutils,verbose,version,globals,fmodule,ogmap;
  308. const
  309. StackPointerSymStr='__stack_pointer';
  310. procedure WriteUleb5(d: tdynamicarray; v: uint64);
  311. var
  312. b: byte;
  313. i: Integer;
  314. begin
  315. for i:=1 to 5 do
  316. begin
  317. b:=byte(v) and 127;
  318. v:=v shr 7;
  319. if i<>5 then
  320. b:=b or 128;
  321. d.write(b,1);
  322. end;
  323. end;
  324. procedure WriteUleb5(d: tobjsection; v: uint64);
  325. var
  326. b: byte;
  327. i: Integer;
  328. begin
  329. for i:=1 to 5 do
  330. begin
  331. b:=byte(v) and 127;
  332. v:=v shr 7;
  333. if i<>5 then
  334. b:=b or 128;
  335. d.write(b,1);
  336. end;
  337. end;
  338. procedure WriteSleb5(d: tdynamicarray; v: int64);
  339. var
  340. b: byte;
  341. i: Integer;
  342. begin
  343. for i:=1 to 5 do
  344. begin
  345. b:=byte(v) and 127;
  346. v:=SarInt64(v,7);
  347. if i<>5 then
  348. b:=b or 128;
  349. d.write(b,1);
  350. end;
  351. end;
  352. procedure WriteSleb5(d: tobjsection; v: int64);
  353. var
  354. b: byte;
  355. i: Integer;
  356. begin
  357. for i:=1 to 5 do
  358. begin
  359. b:=byte(v) and 127;
  360. v:=SarInt64(v,7);
  361. if i<>5 then
  362. b:=b or 128;
  363. d.write(b,1);
  364. end;
  365. end;
  366. procedure WriteUleb(d: tdynamicarray; v: uint64);
  367. var
  368. b: byte;
  369. begin
  370. repeat
  371. b:=byte(v) and 127;
  372. v:=v shr 7;
  373. if v<>0 then
  374. b:=b or 128;
  375. d.write(b,1);
  376. until v=0;
  377. end;
  378. procedure WriteUleb(d: tobjsection; v: uint64);
  379. var
  380. b: byte;
  381. begin
  382. repeat
  383. b:=byte(v) and 127;
  384. v:=v shr 7;
  385. if v<>0 then
  386. b:=b or 128;
  387. d.write(b,1);
  388. until v=0;
  389. end;
  390. procedure WriteUleb(w: TObjectWriter; v: uint64);
  391. var
  392. b: byte;
  393. begin
  394. repeat
  395. b:=byte(v) and 127;
  396. v:=v shr 7;
  397. if v<>0 then
  398. b:=b or 128;
  399. w.write(b,1);
  400. until v=0;
  401. end;
  402. procedure WriteSleb(d: tdynamicarray; v: int64);
  403. var
  404. b: byte;
  405. Done: Boolean=false;
  406. begin
  407. repeat
  408. b:=byte(v) and 127;
  409. v:=SarInt64(v,7);
  410. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  411. Done:=true
  412. else
  413. b:=b or 128;
  414. d.write(b,1);
  415. until Done;
  416. end;
  417. procedure WriteSleb(d: tobjsection; v: int64);
  418. var
  419. b: byte;
  420. Done: Boolean=false;
  421. begin
  422. repeat
  423. b:=byte(v) and 127;
  424. v:=SarInt64(v,7);
  425. if ((v=0) and ((b and 64)=0)) or ((v=-1) and ((b and 64)<>0)) then
  426. Done:=true
  427. else
  428. b:=b or 128;
  429. d.write(b,1);
  430. until Done;
  431. end;
  432. function UlebEncodingSize(v: uint64): Integer;
  433. var
  434. b: byte;
  435. begin
  436. Result:=0;
  437. repeat
  438. b:=byte(v) and 127;
  439. v:=v shr 7;
  440. if v<>0 then
  441. b:=b or 128;
  442. Inc(Result);
  443. until v=0;
  444. end;
  445. {$ifdef FPC_LITTLE_ENDIAN}
  446. procedure WriteF32LE(d: tdynamicarray; v: Single);
  447. begin
  448. d.write(v,4);
  449. end;
  450. procedure WriteF64LE(d: tdynamicarray; v: Double);
  451. begin
  452. d.write(v,8);
  453. end;
  454. {$else FPC_LITTLE_ENDIAN}
  455. procedure WriteF32LE(d: tdynamicarray; v: Single);
  456. var
  457. tmpI: UInt32;
  458. begin
  459. Move(v,tmpI,4);
  460. tmpI:=SwapEndian(tmpI);
  461. d.write(tmpI,4);
  462. end;
  463. procedure WriteF64LE(d: tdynamicarray; v: Double);
  464. var
  465. tmpI: UInt64;
  466. begin
  467. Move(v,tmpI,8);
  468. tmpI:=SwapEndian(tmpI);
  469. d.write(tmpI,8);
  470. end;
  471. {$endif FPC_LITTLE_ENDIAN}
  472. procedure WriteByte(d: tdynamicarray; b: byte);
  473. begin
  474. d.write(b,1);
  475. end;
  476. procedure WriteName(d: tdynamicarray; const s: string);
  477. begin
  478. WriteUleb(d,Length(s));
  479. d.writestr(s);
  480. end;
  481. procedure WriteWasmBasicType(dest: tdynamicarray; wbt: TWasmBasicType);
  482. begin
  483. WriteByte(dest,encode_wasm_basic_type(wbt));
  484. end;
  485. procedure WriteWasmResultType(dest: tdynamicarray; wrt: TWasmResultType);
  486. var
  487. i: Integer;
  488. begin
  489. WriteUleb(dest,Length(wrt));
  490. for i:=low(wrt) to high(wrt) do
  491. WriteWasmBasicType(dest,wrt[i]);
  492. end;
  493. function ReadUleb(d: tdynamicarray): uint64;
  494. var
  495. b: byte;
  496. shift:integer;
  497. begin
  498. b:=0;
  499. result:=0;
  500. shift:=0;
  501. repeat
  502. d.read(b,1);
  503. result:=result or (uint64(b and 127) shl shift);
  504. inc(shift,7);
  505. until (b and 128)=0;
  506. end;
  507. function ReadSleb(d: tdynamicarray): int64;
  508. var
  509. b: byte;
  510. shift:integer;
  511. begin
  512. b:=0;
  513. result:=0;
  514. shift:=0;
  515. repeat
  516. d.read(b,1);
  517. result:=result or (uint64(b and 127) shl shift);
  518. inc(shift,7);
  519. until (b and 128)=0;
  520. {$ifopt Q+}
  521. {$define overflowon}
  522. {$Q-}
  523. {$endif}
  524. {$ifopt R+}
  525. {$define rangeon}
  526. {$R-}
  527. {$endif}
  528. if ((b and 64)<>0) and (Shift < 64) then
  529. result:=result or (high(uint64) shl shift);
  530. end;
  531. {$ifdef overflowon}
  532. {$Q+}
  533. {$undef overflowon}
  534. {$endif}
  535. {$ifdef rangeon}
  536. {$R+}
  537. {$undef rangeon}
  538. {$endif}
  539. procedure AddSleb5(d: tdynamicarray; v: int64);
  540. var
  541. q: Int64;
  542. p: LongWord;
  543. begin
  544. p:=d.Pos;
  545. q:=ReadSleb(d);
  546. q:=q+v;
  547. d.seek(p);
  548. WriteSleb5(d,q);
  549. end;
  550. procedure AddUleb5(d: tdynamicarray; v: int64);
  551. var
  552. q: UInt64;
  553. p: LongWord;
  554. begin
  555. p:=d.Pos;
  556. q:=ReadUleb(d);
  557. q:=q+v;
  558. d.seek(p);
  559. WriteUleb5(d,q);
  560. end;
  561. procedure AddInt32(d: tdynamicarray; v: int32);
  562. var
  563. q: int32;
  564. p: LongWord;
  565. begin
  566. p:=d.Pos;
  567. d.read(q,4);
  568. {$ifdef FPC_BIG_ENDIAN}
  569. q:=SwapEndian(q);
  570. {$endif FPC_BIG_ENDIAN}
  571. q:=q+v;
  572. {$ifdef FPC_BIG_ENDIAN}
  573. q:=SwapEndian(q);
  574. {$endif FPC_BIG_ENDIAN}
  575. d.seek(p);
  576. d.write(q,4);
  577. end;
  578. procedure CopyDynamicArray(src, dest: tdynamicarray; size: QWord);
  579. var
  580. buf: array [0..4095] of byte;
  581. bs: Integer;
  582. begin
  583. while size>0 do
  584. begin
  585. if size<SizeOf(buf) then
  586. bs:=Integer(size)
  587. else
  588. bs:=SizeOf(buf);
  589. src.read(buf,bs);
  590. dest.write(buf,bs);
  591. dec(size,bs);
  592. end;
  593. end;
  594. procedure WriteZeros(dest: tdynamicarray; size: QWord);
  595. var
  596. buf : array[0..1023] of byte;
  597. bs: Integer;
  598. begin
  599. fillchar(buf,sizeof(buf),0);
  600. while size>0 do
  601. begin
  602. if size<SizeOf(buf) then
  603. bs:=Integer(size)
  604. else
  605. bs:=SizeOf(buf);
  606. dest.write(buf,bs);
  607. dec(size,bs);
  608. end;
  609. end;
  610. {****************************************************************************
  611. TWasmObjSymbolLinkingData
  612. ****************************************************************************}
  613. constructor TWasmObjSymbolLinkingData.Create;
  614. begin
  615. ExeFunctionIndex:=-1;
  616. ExeIndirectFunctionTableIndex:=-1;
  617. ExeTypeIndex:=-1;
  618. ExeTagIndex:=-1;
  619. end;
  620. destructor TWasmObjSymbolLinkingData.Destroy;
  621. begin
  622. FuncType.Free;
  623. inherited Destroy;
  624. end;
  625. {****************************************************************************
  626. TWasmObjRelocation
  627. ****************************************************************************}
  628. constructor TWasmObjRelocation.CreateTypeIndex(ADataOffset: TObjSectionOfs; ATypeIndex: Integer);
  629. begin
  630. DataOffset:=ADataOffset;
  631. Symbol:=nil;
  632. OrgSize:=0;
  633. Group:=nil;
  634. ObjSection:=nil;
  635. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  636. TypeIndex:=ATypeIndex;
  637. FuncType:=nil;
  638. ExeTypeIndex:=-1;
  639. end;
  640. constructor TWasmObjRelocation.CreateFuncType(ADataOffset: TObjSectionOfs; AFuncType: TWasmFuncType);
  641. begin
  642. DataOffset:=ADataOffset;
  643. Symbol:=nil;
  644. OrgSize:=0;
  645. Group:=nil;
  646. ObjSection:=nil;
  647. ftype:=ord(RELOC_TYPE_INDEX_LEB);
  648. TypeIndex:=-1;
  649. ExeTypeIndex:=-1;
  650. FuncType:=TWasmFuncType.Create(AFuncType);
  651. end;
  652. destructor TWasmObjRelocation.Destroy;
  653. begin
  654. FuncType.Free;
  655. inherited Destroy;
  656. end;
  657. function TWasmObjRelocation.ToString: ansistring;
  658. var
  659. FuncTypeStr: ansistring;
  660. begin
  661. if Assigned(FuncType) then
  662. FuncTypeStr:=FuncType.ToString
  663. else
  664. FuncTypeStr:='nil';
  665. WriteStr(Result,'('+inherited+';TypeIndex:'+tostr(TypeIndex)+
  666. ';Addend:'+tostr(Addend)+';FuncType:'+FuncTypeStr+
  667. ';ExeTypeIndex:'+tostr(ExeTypeIndex)+
  668. ';IsFunctionOffsetI32:',IsFunctionOffsetI32,')');
  669. end;
  670. {****************************************************************************
  671. TWasmObjSymbol
  672. ****************************************************************************}
  673. constructor TWasmObjSymbol.create(AList: TFPHashObjectList; const AName: string);
  674. begin
  675. inherited create(AList,AName);
  676. FuncIndex:=-1;
  677. SymbolIndex:=-1;
  678. GlobalIndex:=-1;
  679. TagIndex:=-1;
  680. AliasOf:='';
  681. ExtraData:=nil;
  682. LinkingData:=TWasmObjSymbolLinkingData.Create;
  683. end;
  684. destructor TWasmObjSymbol.Destroy;
  685. begin
  686. LinkingData.Free;
  687. inherited Destroy;
  688. end;
  689. function TWasmObjSymbol.IsAlias: Boolean;
  690. begin
  691. result:=AliasOf<>'';
  692. end;
  693. {****************************************************************************
  694. TWasmObjSymbolExtraData
  695. ****************************************************************************}
  696. constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
  697. begin
  698. EncodedLocals:=nil;
  699. inherited Create(HashObjectList,s);
  700. TypeIdx:=-1;
  701. ExceptionTagTypeIdx:=-1;
  702. end;
  703. destructor TWasmObjSymbolExtraData.Destroy;
  704. begin
  705. EncodedLocals.Free;
  706. inherited Destroy;
  707. end;
  708. procedure TWasmObjSymbolExtraData.AddLocals(alocals: TWasmLocalsDynArray);
  709. var
  710. i,
  711. rle_entries,
  712. cnt: Integer;
  713. lasttype: TWasmBasicType;
  714. begin
  715. Locals:=alocals;
  716. if Assigned(EncodedLocals) then
  717. internalerror(2024081502);
  718. EncodedLocals:=tdynamicarray.Create(64);
  719. if Length(Locals)=0 then
  720. begin
  721. WriteUleb(EncodedLocals,0);
  722. exit;
  723. end;
  724. rle_entries:=1;
  725. for i:=low(Locals)+1 to high(Locals) do
  726. if Locals[i]<>Locals[i-1] then
  727. inc(rle_entries);
  728. WriteUleb(EncodedLocals,rle_entries);
  729. lasttype:=Locals[Low(Locals)];
  730. cnt:=1;
  731. for i:=low(Locals)+1 to high(Locals) do
  732. if Locals[i]=Locals[i-1] then
  733. inc(cnt)
  734. else
  735. begin
  736. WriteUleb(EncodedLocals,cnt);
  737. WriteWasmBasicType(EncodedLocals,lasttype);
  738. lasttype:=Locals[i];
  739. cnt:=1;
  740. end;
  741. WriteUleb(EncodedLocals,cnt);
  742. WriteWasmBasicType(EncodedLocals,lasttype);
  743. end;
  744. {****************************************************************************
  745. TWasmObjSection
  746. ****************************************************************************}
  747. constructor TWasmObjSection.create(AList: TFPHashObjectList; const Aname: string; Aalign: longint; Aoptions: TObjSectionOptions);
  748. begin
  749. inherited create(AList, Aname, Aalign, Aoptions);
  750. SegIdx:=-1;
  751. SegSymIdx:=-1;
  752. CustomSectionIdx:=-1;
  753. MainFuncSymbol:=nil;
  754. end;
  755. function TWasmObjSection.IsCode: Boolean;
  756. const
  757. CodePrefix = '.text';
  758. begin
  759. result:=(Length(Name)>=Length(CodePrefix)) and
  760. (Copy(Name,1,Length(CodePrefix))=CodePrefix);
  761. end;
  762. function TWasmObjSection.IsData: Boolean;
  763. begin
  764. result:=not (IsCode or IsDebug);
  765. end;
  766. function TWasmObjSection.IsDebug: Boolean;
  767. const
  768. DebugPrefix = '.debug';
  769. begin
  770. result:=(Length(Name)>=Length(DebugPrefix)) and
  771. (Copy(Name,1,Length(DebugPrefix))=DebugPrefix);
  772. end;
  773. {****************************************************************************
  774. TWasmFuncTypeTable
  775. ****************************************************************************}
  776. function TWasmFuncTypeTable.GetCount: Integer;
  777. begin
  778. Result:=Length(FFuncTypes);
  779. end;
  780. function TWasmFuncTypeTable.GetItem(Index: Integer): TWasmFuncType;
  781. begin
  782. if (Index<Low(FFuncTypes)) or (Index>High(FFuncTypes)) then
  783. internalerror(2023123101);
  784. Result:=FFuncTypes[Index];
  785. end;
  786. destructor TWasmFuncTypeTable.Destroy;
  787. var
  788. i: Integer;
  789. begin
  790. for i:=low(FFuncTypes) to high(FFuncTypes) do
  791. begin
  792. FFuncTypes[i].free;
  793. FFuncTypes[i]:=nil;
  794. end;
  795. end;
  796. function TWasmFuncTypeTable.AddOrGetFuncType(wft: TWasmFuncType): integer;
  797. var
  798. i: Integer;
  799. begin
  800. for i:=low(FFuncTypes) to high(FFuncTypes) do
  801. if wft.Equals(FFuncTypes[i]) then
  802. exit(i);
  803. result:=Length(FFuncTypes);
  804. SetLength(FFuncTypes,result+1);
  805. FFuncTypes[result]:=TWasmFuncType.Create(wft);
  806. end;
  807. procedure TWasmFuncTypeTable.WriteTo(d: tdynamicarray);
  808. var
  809. types_count, i: Integer;
  810. begin
  811. types_count:=Count;
  812. WriteUleb(d,types_count);
  813. for i:=0 to types_count-1 do
  814. with Items[i] do
  815. begin
  816. WriteByte(d,$60);
  817. WriteWasmResultType(d,params);
  818. WriteWasmResultType(d,results);
  819. end;
  820. end;
  821. {****************************************************************************
  822. TWasmObjData
  823. ****************************************************************************}
  824. function TWasmObjData.is_smart_section(atype: TAsmSectiontype): boolean;
  825. begin
  826. { For bss we need to set some flags that are target dependent,
  827. it is easier to disable it for smartlinking. It doesn't take up
  828. filespace }
  829. result:=not(target_info.system in systems_darwin) and
  830. create_smartlink_sections and
  831. (atype<>sec_toc) and
  832. (atype<>sec_user) and
  833. { on embedded systems every byte counts, so smartlink bss too }
  834. ((atype<>sec_bss) or (target_info.system in (systems_embedded+systems_freertos)));
  835. end;
  836. function TWasmObjData.sectionname_gas(atype: TAsmSectiontype;
  837. const aname: string; aorder: TAsmSectionOrder): string;
  838. const
  839. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  840. '.text',
  841. '.data',
  842. { why doesn't .rodata work? (FK) }
  843. { sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
  844. { vtables (and anything else containing relocations), otherwise those are }
  845. { not relocated properly on e.g. linux/ppc64. g++ generates there for a }
  846. { vtable for a class called Window: }
  847. { .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
  848. { TODO: .data.ro not yet working}
  849. {$if defined(arm) or defined(riscv64) or defined(powerpc)}
  850. '.rodata',
  851. {$else defined(arm) or defined(riscv64) or defined(powerpc)}
  852. '.data',
  853. {$endif defined(arm) or defined(riscv64) or defined(powerpc)}
  854. '.rodata',
  855. '.bss',
  856. '.tbss',
  857. '.pdata',
  858. '', { stubs }
  859. '__DATA,__nl_symbol_ptr',
  860. '__DATA,__la_symbol_ptr',
  861. '__DATA,__mod_init_func',
  862. '__DATA,__mod_term_func',
  863. '.stab',
  864. '.stabstr',
  865. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  866. '.eh_frame',
  867. '.debug_frame','.debug_info','.debug_line','.debug_abbrev','.debug_aranges','.debug_ranges','.debug_loc','.debug_loclists',
  868. '.fpc',
  869. '.toc',
  870. '.init',
  871. '.fini',
  872. '.objc_class',
  873. '.objc_meta_class',
  874. '.objc_cat_cls_meth',
  875. '.objc_cat_inst_meth',
  876. '.objc_protocol',
  877. '.objc_string_object',
  878. '.objc_cls_meth',
  879. '.objc_inst_meth',
  880. '.objc_cls_refs',
  881. '.objc_message_refs',
  882. '.objc_symbols',
  883. '.objc_category',
  884. '.objc_class_vars',
  885. '.objc_instance_vars',
  886. '.objc_module_info',
  887. '.objc_class_names',
  888. '.objc_meth_var_types',
  889. '.objc_meth_var_names',
  890. '.objc_selector_strs',
  891. '.objc_protocol_ext',
  892. '.objc_class_ext',
  893. '.objc_property',
  894. '.objc_image_info',
  895. '.objc_cstring_object',
  896. '.objc_sel_fixup',
  897. '__DATA,__objc_data',
  898. '__DATA,__objc_const',
  899. '.objc_superrefs',
  900. '__DATA, __datacoal_nt,coalesced',
  901. '.objc_classlist',
  902. '.objc_nlclasslist',
  903. '.objc_catlist',
  904. '.obcj_nlcatlist',
  905. '.objc_protolist',
  906. '.stack',
  907. '.heap',
  908. '.gcc_except_table',
  909. '.ARM.attributes'
  910. );
  911. var
  912. sep : string[3];
  913. secname : string;
  914. begin
  915. secname:=secnames[atype];
  916. if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
  917. begin
  918. result:=secname+'.'+aname;
  919. exit;
  920. end;
  921. { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
  922. Thus, data which normally goes into .rodata and .rodata_norel sections must
  923. end up in .data section }
  924. if (atype in [sec_rodata,sec_rodata_norel]) and
  925. (target_info.system in [system_i386_go32v2,system_m68k_palmos]) then
  926. secname:='.data';
  927. { Windows correctly handles reallocations in readonly sections }
  928. if (atype=sec_rodata) and
  929. (target_info.system in systems_all_windows+systems_nativent-[system_i8086_win16]) then
  930. secname:='.rodata';
  931. { section type user gives the user full controll on the section name }
  932. if atype=sec_user then
  933. secname:=aname;
  934. if is_smart_section(atype) and (aname<>'') then
  935. begin
  936. case aorder of
  937. secorder_begin :
  938. sep:='.b_';
  939. secorder_end :
  940. sep:='.z_';
  941. else
  942. sep:='.n_';
  943. end;
  944. result:=secname+sep+aname
  945. end
  946. else
  947. result:=secname;
  948. end;
  949. constructor TWasmObjData.create(const n: string);
  950. begin
  951. inherited;
  952. CObjSection:=TWasmObjSection;
  953. CObjSymbol:=TWasmObjSymbol;
  954. FObjSymbolsExtraDataList:=TFPHashObjectList.Create;
  955. FFuncTypes:=TWasmFuncTypeTable.Create;
  956. end;
  957. destructor TWasmObjData.destroy;
  958. var
  959. i: Integer;
  960. begin
  961. FObjSymbolsExtraDataList.Free;
  962. FFuncTypes.Free;
  963. inherited destroy;
  964. end;
  965. function TWasmObjData.sectionname(atype: TAsmSectiontype;
  966. const aname: string; aorder: TAsmSectionOrder): string;
  967. begin
  968. if (atype=sec_fpc) or
  969. ((atype=sec_threadvar) and not (ts_wasm_threads in current_settings.targetswitches)) then
  970. atype:=sec_data;
  971. Result:=sectionname_gas(atype, aname, aorder);
  972. end;
  973. procedure TWasmObjData.writeReloc(Data: TRelocDataInt; len: aword;
  974. p: TObjSymbol; Reloctype: TObjRelocationType);
  975. const
  976. leb_zero: array[0..4] of byte=($80,$80,$80,$80,$00);
  977. var
  978. objreloc: TWasmObjRelocation;
  979. begin
  980. if CurrObjSec=nil then
  981. internalerror(200403072);
  982. { workaround crash, when generating debug info for threadvars, when multithreading is turned off.
  983. todo: ensure the debug info for threadvars is actually correct, once we've got WebAssembly debug info working in general }
  984. if (Reloctype=RELOC_DTPOFF) and not (ts_wasm_threads in current_settings.targetswitches) then
  985. Reloctype:=RELOC_ABSOLUTE;
  986. objreloc:=nil;
  987. case Reloctype of
  988. RELOC_FUNCTION_INDEX_LEB:
  989. begin
  990. if Data<>0 then
  991. internalerror(2021092502);
  992. if len<>5 then
  993. internalerror(2021092503);
  994. if not assigned(p) then
  995. internalerror(2021092504);
  996. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  997. CurrObjSec.ObjRelocations.Add(objreloc);
  998. writebytes(leb_zero,5);
  999. end;
  1000. RELOC_MEMORY_ADDR_LEB,
  1001. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1002. begin
  1003. if (Reloctype=RELOC_MEMORY_ADDR_LEB) and (Data<0) then
  1004. internalerror(2021092602);
  1005. if len<>5 then
  1006. internalerror(2021092503);
  1007. if not assigned(p) then
  1008. internalerror(2021092504);
  1009. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1010. objreloc.Addend:=Data;
  1011. CurrObjSec.ObjRelocations.Add(objreloc);
  1012. if RelocType=RELOC_MEMORY_ADDR_LEB then
  1013. WriteUleb5(CurrObjSec,Data)
  1014. else
  1015. WriteSleb5(CurrObjSec,Data);
  1016. end;
  1017. RELOC_ABSOLUTE:
  1018. begin
  1019. if len<>4 then
  1020. internalerror(2021092607);
  1021. if not assigned(p) then
  1022. internalerror(2021092608);
  1023. if (p.objsection<>nil) and TWasmObjSection(p.objsection).IsDebug and
  1024. (p.bind<>AB_COMMON) and (p.bind<>AB_EXTERNAL) then
  1025. begin
  1026. objreloc:=TWasmObjRelocation.CreateSection(CurrObjSec.Size,p.objsection,RELOC_ABSOLUTE);
  1027. objreloc.Addend:=Data+p.Address;
  1028. CurrObjSec.ObjRelocations.Add(objreloc);
  1029. {inc(data,p.address);}
  1030. data:=0;
  1031. Data:=NtoLE(Data);
  1032. writebytes(Data,4);
  1033. end
  1034. else
  1035. begin
  1036. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1037. objreloc.Addend:=Data;
  1038. CurrObjSec.ObjRelocations.Add(objreloc);
  1039. Data:=NtoLE(Data);
  1040. writebytes(Data,4);
  1041. end;
  1042. end;
  1043. RELOC_TYPE_INDEX_LEB:
  1044. begin
  1045. if len<>5 then
  1046. internalerror(2021092612);
  1047. if assigned(p) then
  1048. internalerror(2021092613);
  1049. objreloc:=TWasmObjRelocation.CreateTypeIndex(CurrObjSec.Size,Data);
  1050. CurrObjSec.ObjRelocations.Add(objreloc);
  1051. WriteUleb5(CurrObjSec,Data);
  1052. end;
  1053. RELOC_GLOBAL_INDEX_LEB:
  1054. begin
  1055. if len<>5 then
  1056. internalerror(2021092701);
  1057. if Data<>0 then
  1058. internalerror(2021092702);
  1059. if not assigned(p) then
  1060. internalerror(2021092703);
  1061. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1062. CurrObjSec.ObjRelocations.Add(objreloc);
  1063. WriteUleb5(CurrObjSec,0);
  1064. end;
  1065. RELOC_TAG_INDEX_LEB:
  1066. begin
  1067. if len<>5 then
  1068. internalerror(2021092712);
  1069. if Data<>0 then
  1070. internalerror(2021092713);
  1071. if not assigned(p) then
  1072. internalerror(2021092714);
  1073. objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
  1074. CurrObjSec.ObjRelocations.Add(objreloc);
  1075. WriteSleb5(CurrObjSec,0);
  1076. end;
  1077. else
  1078. internalerror(2021092501);
  1079. end;
  1080. end;
  1081. function TWasmObjData.AddOrCreateObjSymbolExtraData(const symname: TSymStr): TWasmObjSymbolExtraData;
  1082. begin
  1083. result:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(symname));
  1084. if not assigned(result) then
  1085. result:=TWasmObjSymbolExtraData.Create(FObjSymbolsExtraDataList,symname);
  1086. end;
  1087. function TWasmObjData.globalref(asmsym: TAsmSymbol): TObjSymbol;
  1088. begin
  1089. if assigned(asmsym) then
  1090. begin
  1091. if (asmsym.typ<>AT_WASM_GLOBAL) and (asmsym.typ<>AT_TLS) then
  1092. internalerror(2021092706);
  1093. result:=symbolref(asmsym);
  1094. result.typ:=asmsym.typ;
  1095. end
  1096. else
  1097. result:=nil;
  1098. end;
  1099. function TWasmObjData.ExceptionTagRef(asmsym: TAsmSymbol): TObjSymbol;
  1100. begin
  1101. if assigned(asmsym) then
  1102. begin
  1103. if asmsym.typ<>AT_WASM_EXCEPTION_TAG then
  1104. internalerror(2021092707);
  1105. result:=symbolref(asmsym);
  1106. result.typ:=AT_WASM_EXCEPTION_TAG;
  1107. end
  1108. else
  1109. result:=nil;
  1110. end;
  1111. procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype);
  1112. var
  1113. ObjSymExtraData: TWasmObjSymbolExtraData;
  1114. ObjSym: TObjSymbol;
  1115. begin
  1116. if not gt.is_external then
  1117. begin
  1118. ObjSym:=symboldefine(gt.sym);
  1119. ObjSym.typ:=AT_WASM_GLOBAL;
  1120. end;
  1121. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(gt.globalname);
  1122. ObjSymExtraData.GlobalType:=gt.gtype;
  1123. ObjSymExtraData.GlobalIsImmutable:=gt.immutable;
  1124. end;
  1125. procedure TWasmObjData.DeclareFuncType_Pass0(ft: tai_functype);
  1126. var
  1127. i: Integer;
  1128. ObjSymExtraData: TWasmObjSymbolExtraData;
  1129. begin
  1130. FLastFuncName:=ft.funcname;
  1131. i:=FFuncTypes.AddOrGetFuncType(ft.functype);
  1132. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ft.funcname);
  1133. ObjSymExtraData.TypeIdx:=i;
  1134. end;
  1135. procedure TWasmObjData.DeclareFuncType_Pass1(ft: tai_functype);
  1136. begin
  1137. FLastFuncName:=ft.funcname;
  1138. end;
  1139. procedure TWasmObjData.DeclareFuncType_Pass2(ft: tai_functype);
  1140. begin
  1141. FLastFuncName:=ft.funcname;
  1142. end;
  1143. procedure TWasmObjData.DeclareTagType(tt: tai_tagtype);
  1144. var
  1145. ObjSymExtraData: TWasmObjSymbolExtraData;
  1146. ft: TWasmFuncType;
  1147. i: Integer;
  1148. begin
  1149. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(tt.tagname);
  1150. ft:=TWasmFuncType.Create([],tt.params);
  1151. i:=FFuncTypes.AddOrGetFuncType(ft);
  1152. ft.free;
  1153. ObjSymExtraData.ExceptionTagTypeIdx:=i;
  1154. end;
  1155. procedure TWasmObjData.DeclareExportName(en: tai_export_name);
  1156. var
  1157. ObjSymExtraData: TWasmObjSymbolExtraData;
  1158. begin
  1159. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(en.intname);
  1160. ObjSymExtraData.ExportName:=en.extname;
  1161. end;
  1162. procedure TWasmObjData.DeclareImportModule(aim: tai_import_module);
  1163. var
  1164. ObjSymExtraData: TWasmObjSymbolExtraData;
  1165. begin
  1166. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(aim.symname);
  1167. ObjSymExtraData.ImportModule:=aim.importmodule;
  1168. end;
  1169. procedure TWasmObjData.DeclareImportName(ain: tai_import_name);
  1170. var
  1171. ObjSymExtraData: TWasmObjSymbolExtraData;
  1172. begin
  1173. ObjSymExtraData:=AddOrCreateObjSymbolExtraData(ain.symname);
  1174. ObjSymExtraData.ImportName:=ain.importname;
  1175. end;
  1176. procedure TWasmObjData.DeclareLocals_Pass0(al: tai_local);
  1177. var
  1178. ObjSymExtraData: TWasmObjSymbolExtraData;
  1179. begin
  1180. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1181. ObjSymExtraData.AddLocals(al.locals);
  1182. alloc(ObjSymExtraData.EncodedLocals.size);
  1183. end;
  1184. procedure TWasmObjData.DeclareLocals_Pass1(al: tai_local);
  1185. var
  1186. ObjSymExtraData: TWasmObjSymbolExtraData;
  1187. begin
  1188. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1189. alloc(ObjSymExtraData.EncodedLocals.size);
  1190. end;
  1191. procedure TWasmObjData.WriteLocals_Pass2(al: tai_local);
  1192. var
  1193. ObjSymExtraData: TWasmObjSymbolExtraData;
  1194. d: tdynamicarray;
  1195. buf: array [0..4095] of byte;
  1196. bs,size: Integer;
  1197. begin
  1198. ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
  1199. d:=ObjSymExtraData.EncodedLocals;
  1200. d.seek(0);
  1201. size:=d.size;
  1202. while size>0 do
  1203. begin
  1204. if size<SizeOf(buf) then
  1205. bs:=Integer(size)
  1206. else
  1207. bs:=SizeOf(buf);
  1208. d.read(buf,bs);
  1209. writebytes(buf,bs);
  1210. dec(size,bs);
  1211. end;
  1212. end;
  1213. procedure TWasmObjData.symbolpairdefine(akind: TSymbolPairKind; const asym, avalue: string);
  1214. var
  1215. valsym: TObjSymbol;
  1216. aliassym: TWasmObjSymbol;
  1217. begin
  1218. valsym:=CreateSymbol(avalue);
  1219. aliassym:=TWasmObjSymbol(symboldefine(asym,valsym.bind,valsym.typ));
  1220. aliassym.AliasOf:=valsym.Name;
  1221. end;
  1222. {****************************************************************************
  1223. TWasmObjOutput
  1224. ****************************************************************************}
  1225. procedure TWasmObjOutput.WriteWasmSection(wsid: TWasmSectionID);
  1226. var
  1227. b: byte;
  1228. begin
  1229. b:=ord(wsid);
  1230. Writer.write(b,1);
  1231. WriteUleb(Writer,FWasmSections[wsid].size);
  1232. Writer.writearray(FWasmSections[wsid]);
  1233. end;
  1234. procedure TWasmObjOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  1235. var
  1236. b: byte;
  1237. begin
  1238. b:=0;
  1239. Writer.write(b,1);
  1240. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  1241. Writer.writearray(FWasmCustomSections[wcst]);
  1242. end;
  1243. function TWasmObjOutput.IsExternalFunction(sym: TObjSymbol): Boolean;
  1244. var
  1245. ExtraData: TWasmObjSymbolExtraData;
  1246. begin
  1247. if sym.bind=AB_EXTERNAL then
  1248. begin
  1249. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  1250. result:=(ExtraData<>nil) and (ExtraData.TypeIdx<>-1);
  1251. end
  1252. else
  1253. result:=false;
  1254. end;
  1255. function TWasmObjOutput.IsExportedFunction(sym: TWasmObjSymbol): Boolean;
  1256. var
  1257. ExtraData: TWasmObjSymbolExtraData;
  1258. begin
  1259. if (sym.typ=AT_FUNCTION) and not sym.IsAlias then
  1260. begin
  1261. ExtraData:=TWasmObjSymbolExtraData(TWasmObjData(sym.ObjData).FObjSymbolsExtraDataList.Find(sym.Name));
  1262. result:=(ExtraData<>nil) and (ExtraData.ExportName<>'');
  1263. end
  1264. else
  1265. result:=false;
  1266. end;
  1267. procedure TWasmObjOutput.WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
  1268. var
  1269. ObjSymExtraData: TWasmObjSymbolExtraData;
  1270. ObjSection: TWasmObjSection;
  1271. codelen: QWord;
  1272. begin
  1273. ObjSymExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1274. ObjSection:=TWasmObjSection(objsym.objsection);
  1275. ObjSection.Data.seek(objsym.address);
  1276. codelen:=objsym.size;
  1277. WriteUleb(dest,codelen);
  1278. ObjSection.FileSectionOfs:=dest.size-objsym.offset;
  1279. CopyDynamicArray(ObjSection.Data,dest,codelen);
  1280. end;
  1281. procedure TWasmObjOutput.WriteSymbolTable;
  1282. begin
  1283. WriteUleb(FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTableEntriesCount);
  1284. FWasmSymbolTable.seek(0);
  1285. CopyDynamicArray(FWasmSymbolTable,FWasmLinkingSubsections[WASM_SYMBOL_TABLE],FWasmSymbolTable.size);
  1286. end;
  1287. procedure TWasmObjOutput.WriteRelocationCodeTable(CodeSectionIndex: Integer);
  1288. begin
  1289. WriteUleb(FWasmCustomSections[wcstRelocCode],CodeSectionIndex);
  1290. WriteUleb(FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTableEntriesCount);
  1291. FWasmRelocationCodeTable.seek(0);
  1292. CopyDynamicArray(FWasmRelocationCodeTable,FWasmCustomSections[wcstRelocCode],FWasmRelocationCodeTable.size);
  1293. end;
  1294. procedure TWasmObjOutput.WriteRelocationDataTable(DataSectionIndex: Integer);
  1295. begin
  1296. WriteUleb(FWasmCustomSections[wcstRelocData],DataSectionIndex);
  1297. WriteUleb(FWasmCustomSections[wcstRelocData],FWasmRelocationDataTableEntriesCount);
  1298. FWasmRelocationDataTable.seek(0);
  1299. CopyDynamicArray(FWasmRelocationDataTable,FWasmCustomSections[wcstRelocData],FWasmRelocationDataTable.size);
  1300. end;
  1301. procedure TWasmObjOutput.MaybeWriteRelocationDebugTable(cst: TWasmCustomSectionType; SectionIndex: Integer; EntriesCount: Integer; Table: tdynamicarray);
  1302. begin
  1303. if EntriesCount>0 then
  1304. begin
  1305. WriteUleb(FWasmCustomSections[cst],SectionIndex);
  1306. WriteUleb(FWasmCustomSections[cst],EntriesCount);
  1307. Table.seek(0);
  1308. CopyDynamicArray(Table,FWasmCustomSections[cst],Table.size);
  1309. WriteWasmCustomSection(cst);
  1310. end;
  1311. end;
  1312. procedure TWasmObjOutput.WriteLinkingSubsection(wlst: TWasmLinkingSubsectionType);
  1313. begin
  1314. if FWasmLinkingSubsections[wlst].size>0 then
  1315. begin
  1316. WriteByte(FWasmCustomSections[wcstLinking],Ord(wlst));
  1317. WriteUleb(FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1318. FWasmLinkingSubsections[wlst].seek(0);
  1319. CopyDynamicArray(FWasmLinkingSubsections[wlst],FWasmCustomSections[wcstLinking],FWasmLinkingSubsections[wlst].size);
  1320. end;
  1321. end;
  1322. procedure TWasmObjOutput.DoRelocations;
  1323. var
  1324. si, ri: Integer;
  1325. objsec: TWasmObjSection;
  1326. objrel: TWasmObjRelocation;
  1327. begin
  1328. for si:=0 to FData.ObjSectionList.Count-1 do
  1329. begin
  1330. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1331. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1332. begin
  1333. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1334. case objrel.typ of
  1335. RELOC_FUNCTION_INDEX_LEB:
  1336. begin
  1337. if not assigned(objrel.symbol) then
  1338. internalerror(2021092509);
  1339. objsec.Data.seek(objrel.DataOffset);
  1340. if TWasmObjSymbol(objrel.symbol).FuncIndex<0 then
  1341. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1342. else
  1343. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).FuncIndex);
  1344. end;
  1345. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1346. begin
  1347. if not assigned(objrel.symbol) then
  1348. internalerror(2021092605);
  1349. if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1350. begin
  1351. objsec.Data.seek(objrel.DataOffset);
  1352. AddSleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1353. end;
  1354. end;
  1355. RELOC_MEMORY_ADDR_LEB:
  1356. begin
  1357. if not assigned(objrel.symbol) then
  1358. internalerror(2021092606);
  1359. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1360. internalerror(2021092628);
  1361. if objrel.symbol.bind<>AB_EXTERNAL then
  1362. begin
  1363. objsec.Data.seek(objrel.DataOffset);
  1364. AddUleb5(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1365. end;
  1366. end;
  1367. RELOC_ABSOLUTE:
  1368. begin
  1369. if assigned(objrel.ObjSection) then
  1370. begin
  1371. { todo: should we do something here? }
  1372. //Writeln('todo: section relocation');
  1373. end
  1374. else if not (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) or (objrel.symbol.bind=AB_EXTERNAL)) then
  1375. begin
  1376. objsec.Data.seek(objrel.DataOffset);
  1377. AddInt32(objsec.Data,objrel.symbol.offset+TWasmObjSection(objrel.symbol.objsection).SegOfs);
  1378. end;
  1379. end;
  1380. RELOC_TYPE_INDEX_LEB:
  1381. ;
  1382. RELOC_GLOBAL_INDEX_LEB:
  1383. begin
  1384. if not assigned(objrel.symbol) then
  1385. internalerror(2021092509);
  1386. objsec.Data.seek(objrel.DataOffset);
  1387. if TWasmObjSymbol(objrel.symbol).GlobalIndex<0 then
  1388. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1389. else
  1390. WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
  1391. end;
  1392. RELOC_TAG_INDEX_LEB:
  1393. begin
  1394. if not assigned(objrel.symbol) then
  1395. internalerror(2021092716);
  1396. objsec.Data.seek(objrel.DataOffset);
  1397. if TWasmObjSymbol(objrel.symbol).TagIndex<0 then
  1398. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1399. else
  1400. WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
  1401. end;
  1402. else
  1403. internalerror(2021092510);
  1404. end;
  1405. end;
  1406. end;
  1407. end;
  1408. procedure TWasmObjOutput.WriteRelocations;
  1409. var
  1410. si, ri: Integer;
  1411. objsec: TWasmObjSection;
  1412. objrel: TWasmObjRelocation;
  1413. relout: tdynamicarray;
  1414. relcount: PInteger;
  1415. FuncSym: TWasmObjSymbol;
  1416. begin
  1417. for si:=0 to FData.ObjSectionList.Count-1 do
  1418. begin
  1419. objsec:=TWasmObjSection(FData.ObjSectionList[si]);
  1420. if objsec.IsCode then
  1421. begin
  1422. relout:=FWasmRelocationCodeTable;
  1423. relcount:=@FWasmRelocationCodeTableEntriesCount;
  1424. end
  1425. else if objsec.IsData then
  1426. begin
  1427. relout:=FWasmRelocationDataTable;
  1428. relcount:=@FWasmRelocationDataTableEntriesCount;
  1429. end
  1430. else if objsec.IsDebug then
  1431. begin
  1432. case objsec.Name of
  1433. '.debug_frame':
  1434. begin
  1435. relout:=FWasmRelocationDebugFrameTable;
  1436. relcount:=@FWasmRelocationDebugFrameTableEntriesCount;
  1437. end;
  1438. '.debug_info':
  1439. begin
  1440. relout:=FWasmRelocationDebugInfoTable;
  1441. relcount:=@FWasmRelocationDebugInfoTableEntriesCount;
  1442. end;
  1443. '.debug_line':
  1444. begin
  1445. relout:=FWasmRelocationDebugLineTable;
  1446. relcount:=@FWasmRelocationDebugLineTableEntriesCount;
  1447. end;
  1448. '.debug_abbrev':
  1449. begin
  1450. relout:=FWasmRelocationDebugAbbrevTable;
  1451. relcount:=@FWasmRelocationDebugAbbrevTableEntriesCount;
  1452. end;
  1453. '.debug_aranges':
  1454. begin
  1455. relout:=FWasmRelocationDebugArangesTable;
  1456. relcount:=@FWasmRelocationDebugArangesTableEntriesCount;
  1457. end;
  1458. '.debug_ranges':
  1459. begin
  1460. relout:=FWasmRelocationDebugRangesTable;
  1461. relcount:=@FWasmRelocationDebugRangesTableEntriesCount;
  1462. end;
  1463. '.debug_str':
  1464. begin
  1465. relout:=FWasmRelocationDebugStrTable;
  1466. relcount:=@FWasmRelocationDebugStrTableEntriesCount;
  1467. end;
  1468. else
  1469. internalerror(2022071601);
  1470. end;
  1471. end
  1472. else
  1473. continue;
  1474. for ri:=0 to objsec.ObjRelocations.Count-1 do
  1475. begin
  1476. objrel:=TWasmObjRelocation(objsec.ObjRelocations[ri]);
  1477. case objrel.typ of
  1478. RELOC_FUNCTION_INDEX_LEB:
  1479. begin
  1480. if not assigned(objrel.symbol) then
  1481. internalerror(2021092508);
  1482. Inc(relcount^);
  1483. WriteByte(relout,Ord(R_WASM_FUNCTION_INDEX_LEB));
  1484. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1485. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1486. end;
  1487. RELOC_MEMORY_ADDR_LEB:
  1488. begin
  1489. if not assigned(objrel.symbol) then
  1490. internalerror(2021092603);
  1491. Inc(relcount^);
  1492. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1493. internalerror(2021092628);
  1494. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_LEB));
  1495. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1496. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1497. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1498. end;
  1499. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  1500. begin
  1501. if not assigned(objrel.symbol) then
  1502. internalerror(2021092604);
  1503. Inc(relcount^);
  1504. if IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION) then
  1505. begin
  1506. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_SLEB));
  1507. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1508. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1509. end
  1510. else
  1511. begin
  1512. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_SLEB));
  1513. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1514. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1515. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1516. end;
  1517. end;
  1518. RELOC_ABSOLUTE:
  1519. begin
  1520. // todo: figure this out, why do these exist?
  1521. //if assigned(objrel.symbol) and not assigned(objrel.symbol.objsection) then
  1522. // Writeln('!!! ', objrel.symbol.name);
  1523. if assigned(objrel.objsection) then
  1524. begin
  1525. Inc(relcount^);
  1526. WriteByte(relout,Ord(R_WASM_SECTION_OFFSET_I32));
  1527. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1528. if (TWasmObjSection(objrel.objsection).SegSymIdx<0) then
  1529. message1(asmw_e_illegal_unset_index,objrel.objsection.name)
  1530. else
  1531. WriteUleb(relout,TWasmObjSection(objrel.objsection).SegSymIdx);
  1532. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1533. end
  1534. else if (IsExternalFunction(objrel.symbol) or (objrel.symbol.typ=AT_FUNCTION)) and not objsec.IsDebug then
  1535. begin
  1536. Inc(relcount^);
  1537. WriteByte(relout,Ord(R_WASM_TABLE_INDEX_I32));
  1538. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1539. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1540. end
  1541. else if assigned(objrel.symbol) and assigned(objrel.symbol.objsection) and TWasmObjSection(objrel.symbol.objsection).IsCode then
  1542. begin
  1543. Inc(relcount^);
  1544. WriteByte(relout,Ord(R_WASM_FUNCTION_OFFSET_I32));
  1545. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1546. FuncSym:=FindFunctionSymbol(TWasmObjSymbol(objrel.Symbol));
  1547. if FuncSym.SymbolIndex<0 then
  1548. message1(asmw_e_illegal_unset_index,FuncSym.Name)
  1549. else
  1550. WriteUleb(relout,FuncSym.SymbolIndex);
  1551. WriteSleb(relout,objrel.Addend+objrel.symbol.address) { addend to add to the address }
  1552. end
  1553. else if assigned(objrel.symbol) and (objrel.symbol.typ=AT_WASM_GLOBAL) then
  1554. begin
  1555. Inc(relcount^);
  1556. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_I32));
  1557. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1558. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1559. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1560. else
  1561. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1562. end
  1563. else
  1564. begin
  1565. Inc(relcount^);
  1566. WriteByte(relout,Ord(R_WASM_MEMORY_ADDR_I32));
  1567. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1568. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1569. begin
  1570. Writeln(objrel.symbol.objsection.Name, ' ', objrel.symbol.name, ' ', objsec.Name);
  1571. message1(asmw_e_illegal_unset_index,objrel.symbol.name);
  1572. end
  1573. else
  1574. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1575. WriteSleb(relout,objrel.Addend); { addend to add to the address }
  1576. end;
  1577. end;
  1578. RELOC_TYPE_INDEX_LEB:
  1579. begin
  1580. Inc(relcount^);
  1581. WriteByte(relout,Ord(R_WASM_TYPE_INDEX_LEB));
  1582. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1583. WriteUleb(relout,objrel.TypeIndex);
  1584. end;
  1585. RELOC_GLOBAL_INDEX_LEB:
  1586. begin
  1587. if not assigned(objrel.symbol) then
  1588. internalerror(2021092704);
  1589. Inc(relcount^);
  1590. WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_LEB));
  1591. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1592. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1593. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1594. else
  1595. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1596. end;
  1597. RELOC_TAG_INDEX_LEB:
  1598. begin
  1599. if not assigned(objrel.symbol) then
  1600. internalerror(2021092717);
  1601. Inc(relcount^);
  1602. WriteByte(relout,Ord(R_WASM_TAG_INDEX_LEB));
  1603. WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
  1604. if (TWasmObjSymbol(objrel.symbol).SymbolIndex<0) then
  1605. message1(asmw_e_illegal_unset_index,objrel.symbol.name)
  1606. else
  1607. WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
  1608. end;
  1609. else
  1610. internalerror(2021092507);
  1611. end;
  1612. end;
  1613. end;
  1614. end;
  1615. function TWasmObjOutput.FindFunctionSymbol(Symbol: TWasmObjSymbol): TWasmObjSymbol;
  1616. begin
  1617. Result:=TWasmObjSection(Symbol.objsection).MainFuncSymbol;
  1618. end;
  1619. function TWasmObjOutput.writeData(Data:TObjData):boolean;
  1620. var
  1621. section_nr: Integer;
  1622. procedure MaybeAddDebugSectionToSymbolTable(st: TWasmCustomDebugSectionType; var debug_section_nr: Integer);
  1623. var
  1624. objsec: TWasmObjSection;
  1625. begin
  1626. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1627. if Assigned(objsec) then
  1628. begin
  1629. debug_section_nr:=section_nr;
  1630. Inc(section_nr);
  1631. objsec.SegSymIdx:=FWasmSymbolTableEntriesCount;
  1632. objsec.CustomSectionIdx:=debug_section_nr;
  1633. Inc(FWasmSymbolTableEntriesCount);
  1634. WriteByte(FWasmSymbolTable,Ord(SYMTAB_SECTION));
  1635. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL);
  1636. WriteUleb(FWasmSymbolTable,debug_section_nr);
  1637. end;
  1638. end;
  1639. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  1640. var
  1641. objsec: TWasmObjSection;
  1642. begin
  1643. objsec:=TWasmObjSection(Data.ObjSectionList.Find(WasmCustomSectionName[st]));
  1644. if Assigned(objsec) then
  1645. begin
  1646. if oso_Data in objsec.SecOptions then
  1647. begin
  1648. objsec.Data.seek(0);
  1649. CopyDynamicArray(objsec.Data,FWasmCustomSections[st],objsec.Size);
  1650. end
  1651. else
  1652. WriteZeros(FWasmCustomSections[st],objsec.Size);
  1653. WriteWasmCustomSection(st);
  1654. end;
  1655. end;
  1656. var
  1657. i: Integer;
  1658. objsec: TWasmObjSection;
  1659. segment_count: Integer = 0;
  1660. cur_seg_ofs: qword = 0;
  1661. imports_count, NextImportFunctionIndex, NextFunctionIndex,
  1662. code_section_nr, data_section_nr,
  1663. debug_abbrev_section_nr,debug_info_section_nr,debug_str_section_nr,
  1664. debug_line_section_nr,debug_frame_section_nr,debug_aranges_section_nr,
  1665. debug_ranges_section_nr,
  1666. NextGlobalIndex, NextTagIndex: Integer;
  1667. import_globals_count: Integer = 0;
  1668. globals_count: Integer = 0;
  1669. import_functions_count: Integer = 0;
  1670. export_functions_count: Integer = 0;
  1671. functions_count: Integer = 0;
  1672. import_exception_tags_count: Integer = 0;
  1673. exception_tags_count: Integer = 0;
  1674. objsym, ObjSymAlias: TWasmObjSymbol;
  1675. cust_sec: TWasmCustomSectionType;
  1676. SegmentFlags, SymbolFlags: UInt64;
  1677. begin
  1678. FData:=TWasmObjData(Data);
  1679. { each custom sections starts with its name }
  1680. for cust_sec in TWasmCustomSectionType do
  1681. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  1682. WriteUleb(FWasmCustomSections[wcstLinking],2); { linking metadata version }
  1683. for i:=0 to Data.ObjSymbolList.Count-1 do
  1684. begin
  1685. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1686. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  1687. if objsym.bind=AB_EXTERNAL then
  1688. Inc(import_exception_tags_count)
  1689. else
  1690. Inc(exception_tags_count);
  1691. if objsym.typ=AT_WASM_GLOBAL then
  1692. if objsym.bind=AB_EXTERNAL then
  1693. Inc(import_globals_count)
  1694. else
  1695. Inc(globals_count);
  1696. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1697. Inc(import_globals_count);
  1698. if IsExternalFunction(objsym) then
  1699. Inc(import_functions_count);
  1700. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1701. begin
  1702. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  1703. Inc(functions_count);
  1704. end;
  1705. if IsExportedFunction(objsym) then
  1706. Inc(export_functions_count);
  1707. end;
  1708. FData.FFuncTypes.WriteTo(FWasmSections[wsiType]);
  1709. for i:=0 to Data.ObjSectionList.Count-1 do
  1710. begin
  1711. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  1712. if objsec.IsCode then
  1713. objsec.SegIdx:=-1
  1714. else if objsec.IsData then
  1715. begin
  1716. objsec.SegIdx:=segment_count;
  1717. objsec.SegOfs:=cur_seg_ofs;
  1718. Inc(segment_count);
  1719. Inc(cur_seg_ofs,objsec.Size);
  1720. end;
  1721. end;
  1722. imports_count:=2+import_globals_count+import_functions_count+import_exception_tags_count;
  1723. WriteUleb(FWasmSections[wsiImport],imports_count);
  1724. { import memories }
  1725. WriteName(FWasmSections[wsiImport],'env');
  1726. WriteName(FWasmSections[wsiImport],'__linear_memory');
  1727. WriteByte(FWasmSections[wsiImport],$02); { mem }
  1728. WriteByte(FWasmSections[wsiImport],$00); { min }
  1729. WriteUleb(FWasmSections[wsiImport],1); { 1 page }
  1730. { import globals }
  1731. NextGlobalIndex:=0;
  1732. for i:=0 to Data.ObjSymbolList.Count-1 do
  1733. begin
  1734. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1735. if (objsym.bind=AB_EXTERNAL) and (objsym.typ=AT_WASM_GLOBAL) then
  1736. begin
  1737. objsym.GlobalIndex:=NextGlobalIndex;
  1738. Inc(NextGlobalIndex);
  1739. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1740. if objsym.ExtraData.ImportModule<>'' then
  1741. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1742. else
  1743. WriteName(FWasmSections[wsiImport],'env');
  1744. WriteName(FWasmSections[wsiImport],objsym.Name);
  1745. WriteByte(FWasmSections[wsiImport],$03); { global }
  1746. WriteWasmBasicType(FWasmSections[wsiImport],objsym.ExtraData.GlobalType);
  1747. if objsym.ExtraData.GlobalIsImmutable then
  1748. WriteByte(FWasmSections[wsiImport],$00) { const }
  1749. else
  1750. WriteByte(FWasmSections[wsiImport],$01); { var }
  1751. end
  1752. else if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  1753. begin
  1754. objsym.GlobalIndex:=NextGlobalIndex;
  1755. Inc(NextGlobalIndex);
  1756. objsym.ExtraData:=nil;
  1757. WriteName(FWasmSections[wsiImport],'GOT.mem');
  1758. WriteName(FWasmSections[wsiImport],objsym.Name);
  1759. WriteByte(FWasmSections[wsiImport],$03); { global }
  1760. WriteWasmBasicType(FWasmSections[wsiImport],wbt_i32); { i32 }
  1761. WriteByte(FWasmSections[wsiImport],$01); { var }
  1762. end;
  1763. end;
  1764. { import functions }
  1765. NextImportFunctionIndex:=0;
  1766. for i:=0 to Data.ObjSymbolList.Count-1 do
  1767. begin
  1768. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1769. if IsExternalFunction(objsym) then
  1770. begin
  1771. objsym.FuncIndex:=NextImportFunctionIndex;
  1772. Inc(NextImportFunctionIndex);
  1773. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1774. if objsym.ExtraData.ImportModule<>'' then
  1775. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1776. else
  1777. WriteName(FWasmSections[wsiImport],'env');
  1778. WriteName(FWasmSections[wsiImport],objsym.Name);
  1779. WriteByte(FWasmSections[wsiImport],$00); { func }
  1780. WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1781. end;
  1782. end;
  1783. { import tables }
  1784. WriteName(FWasmSections[wsiImport],'env');
  1785. WriteName(FWasmSections[wsiImport],'__indirect_function_table');
  1786. WriteByte(FWasmSections[wsiImport],$01); { table }
  1787. WriteByte(FWasmSections[wsiImport],$70); { funcref }
  1788. WriteByte(FWasmSections[wsiImport],$00); { min }
  1789. WriteUleb(FWasmSections[wsiImport],1); { 1 }
  1790. { import tags }
  1791. NextTagIndex:=0;
  1792. for i:=0 to Data.ObjSymbolList.Count-1 do
  1793. begin
  1794. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1795. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind=AB_EXTERNAL) then
  1796. begin
  1797. objsym.TagIndex:=NextTagIndex;
  1798. Inc(NextTagIndex);
  1799. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1800. if objsym.ExtraData.ImportModule<>'' then
  1801. WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
  1802. else
  1803. WriteName(FWasmSections[wsiImport],'env');
  1804. WriteName(FWasmSections[wsiImport],objsym.Name);
  1805. WriteByte(FWasmSections[wsiImport],$04); { tag }
  1806. WriteByte(FWasmSections[wsiImport],$00); { exception }
  1807. WriteUleb(FWasmSections[wsiImport],objsym.ExtraData.ExceptionTagTypeIdx);
  1808. end;
  1809. end;
  1810. WriteUleb(FWasmSections[wsiFunction],functions_count);
  1811. NextFunctionIndex:=NextImportFunctionIndex;
  1812. for i:=0 to Data.ObjSymbolList.Count-1 do
  1813. begin
  1814. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1815. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  1816. begin
  1817. objsym.FuncIndex:=NextFunctionIndex;
  1818. Inc(NextFunctionIndex);
  1819. WriteUleb(FWasmSections[wsiFunction],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
  1820. end;
  1821. end;
  1822. if exception_tags_count>0 then
  1823. begin
  1824. WriteUleb(FWasmSections[wsiTag],exception_tags_count);
  1825. for i:=0 to Data.ObjSymbolList.Count-1 do
  1826. begin
  1827. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1828. if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind<>AB_EXTERNAL) then
  1829. begin
  1830. objsym.TagIndex:=NextTagIndex;
  1831. Inc(NextTagIndex);
  1832. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1833. WriteByte(FWasmSections[wsiTag],$00); { exception }
  1834. WriteUleb(FWasmSections[wsiTag],objsym.ExtraData.ExceptionTagTypeIdx);
  1835. end;
  1836. end;
  1837. end;
  1838. if globals_count>0 then
  1839. begin
  1840. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  1841. for i:=0 to Data.ObjSymbolList.Count-1 do
  1842. begin
  1843. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1844. if (objsym.typ=AT_WASM_GLOBAL) and (objsym.bind<>AB_EXTERNAL) then
  1845. begin
  1846. objsym.GlobalIndex:=NextGlobalIndex;
  1847. Inc(NextGlobalIndex);
  1848. objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
  1849. WriteWasmBasicType(FWasmSections[wsiGlobal],objsym.ExtraData.GlobalType);
  1850. if objsym.ExtraData.GlobalIsImmutable then
  1851. WriteByte(FWasmSections[wsiGlobal],$00) { const }
  1852. else
  1853. WriteByte(FWasmSections[wsiGlobal],$01); { var }
  1854. { init expr }
  1855. case objsym.ExtraData.GlobalType of
  1856. wbt_i32:
  1857. begin
  1858. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  1859. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1860. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1861. end;
  1862. wbt_i64:
  1863. begin
  1864. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  1865. WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) }
  1866. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1867. end;
  1868. wbt_f32:
  1869. begin
  1870. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  1871. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE single precision floating point format) }
  1872. WriteByte(FWasmSections[wsiGlobal],$00);
  1873. WriteByte(FWasmSections[wsiGlobal],$00);
  1874. WriteByte(FWasmSections[wsiGlobal],$00);
  1875. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1876. end;
  1877. wbt_f64:
  1878. begin
  1879. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  1880. WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE double precision floating point format) }
  1881. WriteByte(FWasmSections[wsiGlobal],$00);
  1882. WriteByte(FWasmSections[wsiGlobal],$00);
  1883. WriteByte(FWasmSections[wsiGlobal],$00);
  1884. WriteByte(FWasmSections[wsiGlobal],$00);
  1885. WriteByte(FWasmSections[wsiGlobal],$00);
  1886. WriteByte(FWasmSections[wsiGlobal],$00);
  1887. WriteByte(FWasmSections[wsiGlobal],$00);
  1888. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1889. end;
  1890. wbt_externref:
  1891. begin
  1892. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null extern }
  1893. WriteByte(FWasmSections[wsiGlobal],$6F);
  1894. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1895. end;
  1896. wbt_funcref:
  1897. begin
  1898. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null func }
  1899. WriteByte(FWasmSections[wsiGlobal],$70);
  1900. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  1901. end;
  1902. else
  1903. internalerror(2022052801);
  1904. end;
  1905. end;
  1906. end;
  1907. end;
  1908. if export_functions_count>0 then
  1909. begin
  1910. WriteUleb(FWasmSections[wsiExport],export_functions_count);
  1911. for i:=0 to Data.ObjSymbolList.Count-1 do
  1912. begin
  1913. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  1914. if IsExportedFunction(objsym) then
  1915. begin
  1916. WriteName(FWasmSections[wsiExport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).ExportName);
  1917. WriteByte(FWasmSections[wsiExport],0); { func }
  1918. if (objsym.FuncIndex<0) then
  1919. message1(asmw_e_illegal_unset_index,objsym.name)
  1920. else
  1921. WriteUleb(FWasmSections[wsiExport],objsym.FuncIndex);
  1922. end;
  1923. end;
  1924. end;
  1925. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  1926. Writer.write(WasmVersion,SizeOf(WasmVersion));
  1927. if ts_wasm_threads in current_settings.targetswitches then
  1928. begin
  1929. WriteUleb(FWasmCustomSections[wcstTargetFeatures],4);
  1930. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1931. WriteName(FWasmCustomSections[wcstTargetFeatures],'atomics');
  1932. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1933. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1934. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1935. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1936. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1937. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1938. end
  1939. else
  1940. begin
  1941. WriteUleb(FWasmCustomSections[wcstTargetFeatures],3);
  1942. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1943. WriteName(FWasmCustomSections[wcstTargetFeatures],'bulk-memory');
  1944. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1945. WriteName(FWasmCustomSections[wcstTargetFeatures],'mutable-globals');
  1946. WriteUleb(FWasmCustomSections[wcstTargetFeatures],$2B);
  1947. WriteName(FWasmCustomSections[wcstTargetFeatures],'sign-ext');
  1948. end;
  1949. { Write the producers section:
  1950. https://github.com/WebAssembly/tool-conventions/blob/main/ProducersSection.md }
  1951. WriteUleb(FWasmCustomSections[wcstProducers],2);
  1952. WriteName(FWasmCustomSections[wcstProducers],'language');
  1953. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1954. WriteName(FWasmCustomSections[wcstProducers],'Pascal');
  1955. WriteName(FWasmCustomSections[wcstProducers],'');
  1956. WriteName(FWasmCustomSections[wcstProducers],'processed-by');
  1957. WriteUleb(FWasmCustomSections[wcstProducers],1);
  1958. WriteName(FWasmCustomSections[wcstProducers],'Free Pascal Compiler (FPC)');
  1959. WriteName(FWasmCustomSections[wcstProducers],full_version_string+' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname);
  1960. code_section_nr:=-1;
  1961. data_section_nr:=-1;
  1962. debug_abbrev_section_nr:=-1;
  1963. debug_info_section_nr:=-1;
  1964. debug_str_section_nr:=-1;
  1965. debug_line_section_nr:=-1;
  1966. debug_frame_section_nr:=-1;
  1967. debug_aranges_section_nr:=-1;
  1968. debug_ranges_section_nr:=-1;
  1969. section_nr:=0;
  1970. WriteWasmSection(wsiType);
  1971. Inc(section_nr);
  1972. WriteWasmSection(wsiImport);
  1973. Inc(section_nr);
  1974. WriteWasmSection(wsiFunction);
  1975. Inc(section_nr);
  1976. if exception_tags_count>0 then
  1977. begin
  1978. WriteWasmSection(wsiTag);
  1979. Inc(section_nr);
  1980. end;
  1981. if globals_count>0 then
  1982. begin
  1983. WriteWasmSection(wsiGlobal);
  1984. Inc(section_nr);
  1985. end;
  1986. if export_functions_count>0 then
  1987. begin
  1988. WriteWasmSection(wsiExport);
  1989. Inc(section_nr);
  1990. end;
  1991. { determine the section numbers for the datacount, code, data and debug sections ahead of time }
  1992. if segment_count>0 then
  1993. Inc(section_nr); { the DataCount section }
  1994. code_section_nr:=section_nr; { the Code section }
  1995. Inc(section_nr);
  1996. if segment_count>0 then
  1997. begin
  1998. data_section_nr:=section_nr; { the Data section }
  1999. Inc(section_nr);
  2000. end;
  2001. { the debug sections }
  2002. MaybeAddDebugSectionToSymbolTable(wcstDebugAbbrev,debug_abbrev_section_nr);
  2003. MaybeAddDebugSectionToSymbolTable(wcstDebugInfo,debug_info_section_nr);
  2004. MaybeAddDebugSectionToSymbolTable(wcstDebugStr,debug_str_section_nr);
  2005. MaybeAddDebugSectionToSymbolTable(wcstDebugLine,debug_line_section_nr);
  2006. MaybeAddDebugSectionToSymbolTable(wcstDebugFrame,debug_frame_section_nr);
  2007. MaybeAddDebugSectionToSymbolTable(wcstDebugAranges,debug_aranges_section_nr);
  2008. MaybeAddDebugSectionToSymbolTable(wcstDebugRanges,debug_ranges_section_nr);
  2009. for i:=0 to Data.ObjSymbolList.Count-1 do
  2010. begin
  2011. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  2012. if objsym.typ=AT_WASM_EXCEPTION_TAG then
  2013. begin
  2014. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2015. Inc(FWasmSymbolTableEntriesCount);
  2016. WriteByte(FWasmSymbolTable,Ord(SYMTAB_EVENT));
  2017. if objsym.bind=AB_GLOBAL then
  2018. WriteUleb(FWasmSymbolTable,0)
  2019. else if objsym.bind=AB_LOCAL then
  2020. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL)
  2021. else if objsym.bind=AB_EXTERNAL then
  2022. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED)
  2023. else if objsym.bind=AB_WEAK then
  2024. WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_WEAK)
  2025. else
  2026. internalerror(2021092715);
  2027. if (objsym.TagIndex<0) then
  2028. message1(asmw_e_illegal_unset_index,objsym.name)
  2029. else
  2030. WriteUleb(FWasmSymbolTable,objsym.TagIndex);
  2031. if objsym.bind<>AB_EXTERNAL then
  2032. WriteName(FWasmSymbolTable,objsym.Name);
  2033. end
  2034. else if objsym.typ=AT_WASM_GLOBAL then
  2035. begin
  2036. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2037. Inc(FWasmSymbolTableEntriesCount);
  2038. WriteByte(FWasmSymbolTable,Ord(SYMTAB_GLOBAL));
  2039. if objsym.bind=AB_EXTERNAL then
  2040. begin
  2041. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  2042. if (objsym.GlobalIndex<0) then
  2043. message1(asmw_e_illegal_unset_index,objsym.name)
  2044. else
  2045. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  2046. end
  2047. else
  2048. begin
  2049. WriteUleb(FWasmSymbolTable,0);
  2050. if (objsym.GlobalIndex<0) then
  2051. message1(asmw_e_illegal_unset_index,objsym.name)
  2052. else
  2053. WriteUleb(FWasmSymbolTable,objsym.GlobalIndex);
  2054. WriteName(FWasmSymbolTable,objsym.Name);
  2055. end;
  2056. end
  2057. else if IsExternalFunction(objsym) then
  2058. begin
  2059. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2060. Inc(FWasmSymbolTableEntriesCount);
  2061. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  2062. if objsym.ExtraData.ImportModule<>'' then
  2063. begin
  2064. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED or WASM_SYM_EXPLICIT_NAME);
  2065. if (objsym.FuncIndex<0) then
  2066. message1(asmw_e_illegal_unset_index,objsym.name)
  2067. else
  2068. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2069. WriteName(FWasmSymbolTable,objsym.Name);
  2070. end
  2071. else
  2072. begin
  2073. WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED);
  2074. if (objsym.FuncIndex<0) then
  2075. message1(asmw_e_illegal_unset_index,objsym.name)
  2076. else
  2077. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2078. end;
  2079. end
  2080. else if objsym.typ=AT_FUNCTION then
  2081. begin
  2082. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2083. Inc(FWasmSymbolTableEntriesCount);
  2084. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FUNCTION));
  2085. if objsym.IsAlias then
  2086. begin
  2087. ObjSymAlias:=TWasmObjSymbol(Data.ObjSymbolList.Find(objsym.AliasOf));
  2088. ObjSym.FuncIndex:=ObjSymAlias.FuncIndex;
  2089. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPLICIT_NAME or WASM_SYM_NO_STRIP);
  2090. WriteUleb(FWasmSymbolTable,ObjSymAlias.FuncIndex);
  2091. end
  2092. else
  2093. begin
  2094. if IsExportedFunction(objsym) then
  2095. WriteUleb(FWasmSymbolTable,WASM_SYM_EXPORTED)
  2096. else
  2097. WriteUleb(FWasmSymbolTable,0);
  2098. if (objsym.FuncIndex<0) then
  2099. message1(asmw_e_illegal_unset_index,objsym.name)
  2100. else
  2101. WriteUleb(FWasmSymbolTable,objsym.FuncIndex);
  2102. end;
  2103. WriteName(FWasmSymbolTable,objsym.Name);
  2104. end
  2105. else if (objsym.typ in [AT_DATA,AT_TLS,AT_METADATA]) or ((objsym.typ=AT_NONE) and (objsym.bind=AB_EXTERNAL)) then
  2106. begin
  2107. if (objsym.bind<>AB_EXTERNAL) and TWasmObjSection(objsym.objsection).IsDebug then
  2108. begin
  2109. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2110. Inc(FWasmSymbolTableEntriesCount);
  2111. WriteByte(FWasmSymbolTable,Ord(SYMTAB_FPC_CUSTOM));
  2112. if objsym.bind=AB_GLOBAL then
  2113. SymbolFlags:=0
  2114. else if objsym.bind=AB_LOCAL then
  2115. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  2116. else if objsym.bind=AB_EXTERNAL then
  2117. SymbolFlags:=WASM_SYM_UNDEFINED
  2118. else
  2119. internalerror(2024090701);
  2120. WriteUleb(FWasmSymbolTable,SymbolFlags);
  2121. WriteName(FWasmSymbolTable,objsym.Name);
  2122. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).CustomSectionIdx);
  2123. WriteUleb(FWasmSymbolTable,objsym.offset);
  2124. WriteUleb(FWasmSymbolTable,objsym.size);
  2125. end
  2126. else
  2127. begin
  2128. objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
  2129. Inc(FWasmSymbolTableEntriesCount);
  2130. WriteByte(FWasmSymbolTable,Ord(SYMTAB_DATA));
  2131. if objsym.bind=AB_GLOBAL then
  2132. SymbolFlags:=0
  2133. else if objsym.bind=AB_LOCAL then
  2134. SymbolFlags:=WASM_SYM_BINDING_LOCAL
  2135. else if objsym.bind=AB_EXTERNAL then
  2136. SymbolFlags:=WASM_SYM_UNDEFINED
  2137. else
  2138. internalerror(2021092506);
  2139. if (objsym.typ=AT_TLS) and (ts_wasm_threads in current_settings.targetswitches) then
  2140. SymbolFlags:=(SymbolFlags and not WASM_SYM_BINDING_LOCAL) or WASM_SYM_TLS;
  2141. WriteUleb(FWasmSymbolTable,SymbolFlags);
  2142. WriteName(FWasmSymbolTable,objsym.Name);
  2143. if objsym.bind<>AB_EXTERNAL then
  2144. begin
  2145. WriteUleb(FWasmSymbolTable,TWasmObjSection(objsym.objsection).SegIdx);
  2146. WriteUleb(FWasmSymbolTable,objsym.offset);
  2147. WriteUleb(FWasmSymbolTable,objsym.size);
  2148. end;
  2149. end;
  2150. end;
  2151. end;
  2152. DoRelocations;
  2153. if segment_count>0 then
  2154. begin
  2155. WriteUleb(FWasmSections[wsiData],segment_count);
  2156. WriteUleb(FWasmSections[wsiDataCount],segment_count);
  2157. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],segment_count);
  2158. for i:=0 to Data.ObjSectionList.Count-1 do
  2159. begin
  2160. objsec:=TWasmObjSection(Data.ObjSectionList[i]);
  2161. if objsec.IsData then
  2162. begin
  2163. WriteName(FWasmLinkingSubsections[WASM_SEGMENT_INFO],objsec.Name);
  2164. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],BsrQWord(objsec.SecAlign));
  2165. SegmentFlags:=0;
  2166. if (ts_wasm_threads in current_settings.targetswitches) and
  2167. (oso_threadvar in objsec.SecOptions) then
  2168. SegmentFlags:=SegmentFlags or WASM_SEG_FLAG_TLS;
  2169. WriteUleb(FWasmLinkingSubsections[WASM_SEGMENT_INFO],SegmentFlags); { flags }
  2170. WriteByte(FWasmSections[wsiData],0);
  2171. WriteByte(FWasmSections[wsiData],$41);
  2172. WriteSleb(FWasmSections[wsiData],objsec.SegOfs);
  2173. WriteByte(FWasmSections[wsiData],$0b);
  2174. WriteUleb(FWasmSections[wsiData],objsec.Size);
  2175. objsec.FileSectionOfs:=FWasmSections[wsiData].size;
  2176. if oso_Data in objsec.SecOptions then
  2177. begin
  2178. objsec.Data.seek(0);
  2179. CopyDynamicArray(objsec.Data,FWasmSections[wsiData],objsec.Size);
  2180. end
  2181. else
  2182. begin
  2183. WriteZeros(FWasmSections[wsiData],objsec.Size);
  2184. end;
  2185. end;
  2186. end;
  2187. end;
  2188. WriteUleb(FWasmSections[wsiCode],functions_count);
  2189. for i:=0 to Data.ObjSymbolList.Count-1 do
  2190. begin
  2191. objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
  2192. if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
  2193. WriteFunctionCode(FWasmSections[wsiCode],objsym);
  2194. end;
  2195. if segment_count>0 then
  2196. WriteWasmSection(wsiDataCount);
  2197. WriteWasmSection(wsiCode);
  2198. if segment_count>0 then
  2199. WriteWasmSection(wsiData);
  2200. MaybeWriteDebugSection(wcstDebugAbbrev);
  2201. MaybeWriteDebugSection(wcstDebugInfo);
  2202. MaybeWriteDebugSection(wcstDebugStr);
  2203. MaybeWriteDebugSection(wcstDebugLine);
  2204. MaybeWriteDebugSection(wcstDebugFrame);
  2205. MaybeWriteDebugSection(wcstDebugAranges);
  2206. MaybeWriteDebugSection(wcstDebugRanges);
  2207. WriteRelocations;
  2208. WriteSymbolTable;
  2209. WriteLinkingSubsection(WASM_SYMBOL_TABLE);
  2210. if segment_count>0 then
  2211. WriteLinkingSubsection(WASM_SEGMENT_INFO);
  2212. WriteRelocationCodeTable(code_section_nr);
  2213. if segment_count>0 then
  2214. WriteRelocationDataTable(data_section_nr);
  2215. WriteWasmCustomSection(wcstLinking);
  2216. Inc(section_nr);
  2217. WriteWasmCustomSection(wcstRelocCode);
  2218. Inc(section_nr);
  2219. if segment_count>0 then
  2220. begin
  2221. WriteWasmCustomSection(wcstRelocData);
  2222. Inc(section_nr);
  2223. end;
  2224. MaybeWriteRelocationDebugTable(wcstRelocDebugAbbrev,debug_abbrev_section_nr,FWasmRelocationDebugAbbrevTableEntriesCount,FWasmRelocationDebugAbbrevTable);
  2225. MaybeWriteRelocationDebugTable(wcstRelocDebugInfo,debug_info_section_nr,FWasmRelocationDebugInfoTableEntriesCount,FWasmRelocationDebugInfoTable);
  2226. MaybeWriteRelocationDebugTable(wcstRelocDebugStr,debug_str_section_nr,FWasmRelocationDebugStrTableEntriesCount,FWasmRelocationDebugStrTable);
  2227. MaybeWriteRelocationDebugTable(wcstRelocDebugLine,debug_line_section_nr,FWasmRelocationDebugLineTableEntriesCount,FWasmRelocationDebugLineTable);
  2228. MaybeWriteRelocationDebugTable(wcstRelocDebugFrame,debug_frame_section_nr,FWasmRelocationDebugFrameTableEntriesCount,FWasmRelocationDebugFrameTable);
  2229. MaybeWriteRelocationDebugTable(wcstRelocDebugAranges,debug_aranges_section_nr,FWasmRelocationDebugArangesTableEntriesCount,FWasmRelocationDebugArangesTable);
  2230. MaybeWriteRelocationDebugTable(wcstRelocDebugRanges,debug_ranges_section_nr,FWasmRelocationDebugRangesTableEntriesCount,FWasmRelocationDebugRangesTable);
  2231. WriteWasmCustomSection(wcstProducers);
  2232. Inc(section_nr);
  2233. WriteWasmCustomSection(wcstTargetFeatures);
  2234. Inc(section_nr);
  2235. result:=true;
  2236. end;
  2237. constructor TWasmObjOutput.create(AWriter: TObjectWriter);
  2238. var
  2239. i: TWasmSectionID;
  2240. j: TWasmCustomSectionType;
  2241. k: TWasmLinkingSubsectionType;
  2242. begin
  2243. inherited;
  2244. cobjdata:=TWasmObjData;
  2245. for i in TWasmSectionID do
  2246. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  2247. for j in TWasmCustomSectionType do
  2248. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  2249. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  2250. FWasmLinkingSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  2251. FWasmSymbolTable:=tdynamicarray.create(SectionDataMaxGrow);
  2252. FWasmSymbolTableEntriesCount:=0;
  2253. FWasmRelocationCodeTable:=tdynamicarray.create(SectionDataMaxGrow);
  2254. FWasmRelocationCodeTableEntriesCount:=0;
  2255. FWasmRelocationDataTable:=tdynamicarray.create(SectionDataMaxGrow);
  2256. FWasmRelocationDataTableEntriesCount:=0;
  2257. FWasmRelocationDebugFrameTable:=tdynamicarray.create(SectionDataMaxGrow);
  2258. FWasmRelocationDebugFrameTableEntriesCount:=0;
  2259. FWasmRelocationDebugInfoTable:=tdynamicarray.create(SectionDataMaxGrow);
  2260. FWasmRelocationDebugInfoTableEntriesCount:=0;
  2261. FWasmRelocationDebugLineTable:=tdynamicarray.create(SectionDataMaxGrow);
  2262. FWasmRelocationDebugLineTableEntriesCount:=0;
  2263. FWasmRelocationDebugAbbrevTable:=tdynamicarray.create(SectionDataMaxGrow);
  2264. FWasmRelocationDebugAbbrevTableEntriesCount:=0;
  2265. FWasmRelocationDebugArangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  2266. FWasmRelocationDebugArangesTableEntriesCount:=0;
  2267. FWasmRelocationDebugRangesTable:=tdynamicarray.create(SectionDataMaxGrow);
  2268. FWasmRelocationDebugRangesTableEntriesCount:=0;
  2269. FWasmRelocationDebugStrTable:=tdynamicarray.create(SectionDataMaxGrow);
  2270. FWasmRelocationDebugStrTableEntriesCount:=0;
  2271. end;
  2272. destructor TWasmObjOutput.destroy;
  2273. var
  2274. i: TWasmSectionID;
  2275. j: TWasmCustomSectionType;
  2276. k: TWasmLinkingSubsectionType;
  2277. begin
  2278. for i in TWasmSectionID do
  2279. FWasmSections[i].Free;
  2280. for j in TWasmCustomSectionType do
  2281. FWasmCustomSections[j].Free;
  2282. for k:=low(TWasmLinkingSubsectionType) to high(TWasmLinkingSubsectionType) do
  2283. FWasmLinkingSubsections[k].Free;
  2284. FWasmSymbolTable.Free;
  2285. FWasmRelocationCodeTable.Free;
  2286. FWasmRelocationDataTable.Free;
  2287. FWasmRelocationDebugFrameTable.Free;
  2288. FWasmRelocationDebugInfoTable.Free;
  2289. FWasmRelocationDebugLineTable.Free;
  2290. FWasmRelocationDebugAbbrevTable.Free;
  2291. FWasmRelocationDebugArangesTable.Free;
  2292. FWasmRelocationDebugRangesTable.Free;
  2293. FWasmRelocationDebugStrTable.Free;
  2294. inherited destroy;
  2295. end;
  2296. {****************************************************************************
  2297. TWasmObjInput
  2298. ****************************************************************************}
  2299. constructor TWasmObjInput.create;
  2300. begin
  2301. inherited create;
  2302. cobjdata:=TWasmObjData;
  2303. end;
  2304. destructor TWasmObjInput.Destroy;
  2305. var
  2306. i: Integer;
  2307. begin
  2308. for i:=low(FFuncTypes) to high(FFuncTypes) do
  2309. begin
  2310. FFuncTypes[i].free;
  2311. FFuncTypes[i]:=nil;
  2312. end;
  2313. inherited Destroy;
  2314. end;
  2315. class function TWasmObjInput.CanReadObjData(AReader: TObjectreader): boolean;
  2316. var
  2317. ModuleMagic: array [0..3] of Byte;
  2318. ModuleVersion: array [0..3] of Byte;
  2319. i: Integer;
  2320. begin
  2321. result:=false;
  2322. if not AReader.read(ModuleMagic,4) then
  2323. exit;
  2324. for i:=0 to 3 do
  2325. if ModuleMagic[i]<>WasmModuleMagic[i] then
  2326. exit;
  2327. if not AReader.read(ModuleVersion,4) then
  2328. exit;
  2329. for i:=0 to 3 do
  2330. if ModuleVersion[i]<>WasmVersion[i] then
  2331. exit;
  2332. result:=true;
  2333. end;
  2334. function TWasmObjInput.ReadObjData(AReader: TObjectreader; out ObjData: TObjData): boolean;
  2335. type
  2336. TLimits = record
  2337. Min, Max: uint32;
  2338. HasMax: Boolean;
  2339. end;
  2340. var
  2341. SectionIndex: Integer = -1;
  2342. SectionId: Byte;
  2343. SectionSize: uint32;
  2344. SectionStart: LongInt;
  2345. CheckSectionBounds: Boolean;
  2346. TypeSectionRead: Boolean = false;
  2347. ImportSectionRead: Boolean = false;
  2348. FunctionSectionRead: Boolean = false;
  2349. GlobalSectionRead: Boolean = false;
  2350. ExportSectionRead: Boolean = false;
  2351. ElementSectionRead: Boolean = false;
  2352. TagSectionRead: Boolean = false;
  2353. CodeSectionRead: Boolean = false;
  2354. DataSectionRead: Boolean = false;
  2355. DataCountSectionRead: Boolean = false;
  2356. SegmentInfoSectionRead: Boolean = false;
  2357. SymbolTableSectionRead: Boolean = false;
  2358. CodeSectionIndex: Integer = -1;
  2359. DataSectionIndex: Integer = -1;
  2360. DebugSectionIndex: array [TWasmCustomDebugSectionType] of Integer = (-1,-1,-1,-1,-1,-1,-1);
  2361. FuncTypes: array of record
  2362. IsImport: Boolean;
  2363. ImportName: ansistring;
  2364. ImportModName: ansistring;
  2365. typidx: uint32;
  2366. IsExported: Boolean;
  2367. ExportName: ansistring;
  2368. end;
  2369. FuncTypeImportsCount: uint32;
  2370. TableTypes: array of record
  2371. IsImport: Boolean;
  2372. ImportName: ansistring;
  2373. ImportModName: ansistring;
  2374. reftype: TWasmBAsicType;
  2375. limits: TLimits;
  2376. IsExported: Boolean;
  2377. ExportName: ansistring;
  2378. end;
  2379. TableTypeImportsCount: uint32;
  2380. MemTypes: array of record
  2381. IsImport: Boolean;
  2382. ImportName: ansistring;
  2383. ImportModName: ansistring;
  2384. limits: TLimits;
  2385. IsExported: Boolean;
  2386. ExportName: ansistring;
  2387. end;
  2388. MemTypeImportsCount: uint32;
  2389. GlobalTypes: array of record
  2390. IsImport: Boolean;
  2391. ImportName: ansistring;
  2392. ImportModName: ansistring;
  2393. valtype: TWasmBasicType;
  2394. IsMutable: Boolean;
  2395. IsExported: Boolean;
  2396. ExportName: ansistring;
  2397. GlobalInit: TGlobalInitializer;
  2398. end;
  2399. GlobalTypeImportsCount: uint32;
  2400. TagTypes: array of record
  2401. IsImport: Boolean;
  2402. ImportName: ansistring;
  2403. ImportModName: ansistring;
  2404. TagAttr: Byte;
  2405. TagTypeIdx: uint32;
  2406. IsExported: Boolean;
  2407. ExportName: ansistring;
  2408. end;
  2409. TagTypeImportsCount: uint32;
  2410. CodeSegments: array of record
  2411. CodeSectionOffset: uint32;
  2412. CodeSize: uint32;
  2413. DataPos: LongInt;
  2414. SegName: ansistring;
  2415. SegIsExported: Boolean;
  2416. end;
  2417. DataSegments: array of record
  2418. DataSectionOffset: uint32;
  2419. Active: Boolean;
  2420. MemIdx: uint32;
  2421. Len: uint32;
  2422. Offset: int32;
  2423. DataPos: LongInt;
  2424. SegName: ansistring;
  2425. SegAlignment: uint32;
  2426. SegFlags: uint32;
  2427. end;
  2428. SymbolTable: array of record
  2429. SymFlags: uint32;
  2430. TargetSection: uint32;
  2431. SymIndex: uint32;
  2432. SymOffset: uint32;
  2433. SymSize: uint32;
  2434. SymCustomSectionIndex: uint32;
  2435. SymCustomSectionType: TWasmCustomDebugSectionType;
  2436. SymKind: TWasmSymbolType;
  2437. SymName: ansistring;
  2438. ObjSym: TWasmObjSymbol;
  2439. ObjSec: TWasmObjSection;
  2440. end;
  2441. { meaning of first index: }
  2442. { table 0 is code relocs }
  2443. { table 1 is data relocs }
  2444. { tables 2.. are custom section relocs for debug sections }
  2445. RelocationTable: array of array of record
  2446. RelocType: TWasmRelocationType;
  2447. RelocOffset: uint32;
  2448. RelocIndex: uint32;
  2449. RelocAddend: int32;
  2450. end;
  2451. function FindDebugSectionByIndex(SectionIndex: Integer; out res: TWasmCustomDebugSectionType): Boolean;
  2452. var
  2453. ds: TWasmCustomDebugSectionType;
  2454. begin
  2455. for ds in TWasmCustomDebugSectionType do
  2456. if DebugSectionIndex[ds]=SectionIndex then
  2457. begin
  2458. Res:=ds;
  2459. Result:=True;
  2460. exit;
  2461. end;
  2462. Res:=low(TWasmCustomDebugSectionType);
  2463. Result:=False;
  2464. end;
  2465. function ReadSection: Boolean;
  2466. function read(out b;len:longint):boolean;
  2467. begin
  2468. result:=false;
  2469. if not CheckSectionBounds or ((AReader.Pos+len)<=(SectionStart+SectionSize)) then
  2470. result:=AReader.read(b,len)
  2471. else
  2472. begin
  2473. { trying to read beyond the end of the section }
  2474. AReader.read(b,SectionStart+SectionSize-AReader.Pos);
  2475. result:=false;
  2476. end;
  2477. end;
  2478. function ReadUleb(out v: uint64): boolean;
  2479. var
  2480. b: byte;
  2481. shift:integer;
  2482. begin
  2483. result:=false;
  2484. b:=0;
  2485. v:=0;
  2486. shift:=0;
  2487. repeat
  2488. if not read(b,1) then
  2489. exit;
  2490. v:=v or (uint64(b and 127) shl shift);
  2491. inc(shift,7);
  2492. until (b and 128)=0;
  2493. result:=true;
  2494. end;
  2495. function ReadUleb32(out v: uint32): boolean;
  2496. var
  2497. vv: uint64;
  2498. begin
  2499. result:=false;
  2500. v:=default(uint32);
  2501. if not ReadUleb(vv) then
  2502. exit;
  2503. if vv>high(uint32) then
  2504. exit;
  2505. v:=vv;
  2506. result:=true;
  2507. end;
  2508. function ReadSleb(out v: int64): boolean;
  2509. var
  2510. b: byte;
  2511. shift:integer;
  2512. begin
  2513. result:=false;
  2514. b:=0;
  2515. v:=0;
  2516. shift:=0;
  2517. repeat
  2518. if not read(b,1) then
  2519. exit;
  2520. v:=v or (uint64(b and 127) shl shift);
  2521. inc(shift,7);
  2522. until (b and 128)=0;
  2523. {$ifopt Q+}
  2524. {$define overflowon}
  2525. {$Q-}
  2526. {$endif}
  2527. {$ifopt R+}
  2528. {$define rangeon}
  2529. {$R-}
  2530. {$endif}
  2531. if (b and 64)<>0 then
  2532. v:=v or (high(uint64) shl shift);
  2533. result:=true;
  2534. end;
  2535. {$ifdef overflowon}
  2536. {$Q+}
  2537. {$undef overflowon}
  2538. {$endif}
  2539. {$ifdef rangeon}
  2540. {$R+}
  2541. {$undef rangeon}
  2542. {$endif}
  2543. function ReadSleb32(out v: int32): boolean;
  2544. var
  2545. vv: int64;
  2546. begin
  2547. result:=false;
  2548. v:=default(int32);
  2549. if not ReadSleb(vv) then
  2550. exit;
  2551. if (vv>high(int32)) or (vv<low(int32)) then
  2552. exit;
  2553. v:=vv;
  2554. result:=true;
  2555. end;
  2556. function ReadName(out v: ansistring): boolean;
  2557. var
  2558. len: uint32;
  2559. begin
  2560. result:=false;
  2561. if not ReadUleb32(len) then
  2562. exit;
  2563. SetLength(v,len);
  2564. if len>0 then
  2565. result:=read(v[1],len)
  2566. else
  2567. result:=true;
  2568. end;
  2569. function ReadCustomSection: Boolean;
  2570. function ReadRelocationSection: Boolean;
  2571. var
  2572. TargetSection, RelocCount: uint32;
  2573. i: Integer;
  2574. RelocTableIndex: Integer;
  2575. ds: TWasmCustomDebugSectionType;
  2576. begin
  2577. Result:=False;
  2578. if not ReadUleb32(TargetSection) then
  2579. begin
  2580. InputError('Error reading the index of the target section of a relocation section');
  2581. exit;
  2582. end;
  2583. if TargetSection=CodeSectionIndex then
  2584. RelocTableIndex:=0
  2585. else if TargetSection=DataSectionIndex then
  2586. RelocTableIndex:=1
  2587. else
  2588. begin
  2589. RelocTableIndex:=-1;
  2590. for ds:=Low(DebugSectionIndex) to High(DebugSectionIndex) do
  2591. if DebugSectionIndex[ds]=TargetSection then
  2592. begin
  2593. RelocTableIndex:=2+(Ord(ds)-Ord(Low(TWasmCustomDebugSectionType)));
  2594. break;
  2595. end;
  2596. if RelocTableIndex=-1 then
  2597. begin
  2598. InputError('Relocation found for a custom section, that is not supported');
  2599. exit;
  2600. end;
  2601. end;
  2602. if not ReadUleb32(RelocCount) then
  2603. begin
  2604. InputError('Error reading the relocation entries count from a relocation section');
  2605. exit;
  2606. end;
  2607. SetLength(RelocationTable[RelocTableIndex],RelocCount);
  2608. for i:=0 to RelocCount-1 do
  2609. with RelocationTable[RelocTableIndex,i] do
  2610. begin
  2611. if not Read(RelocType,1) then
  2612. begin
  2613. InputError('Error reading the relocation type of a relocation entry');
  2614. exit;
  2615. end;
  2616. if not (RelocType in [R_WASM_FUNCTION_INDEX_LEB,
  2617. R_WASM_MEMORY_ADDR_LEB,
  2618. R_WASM_TABLE_INDEX_SLEB,
  2619. R_WASM_MEMORY_ADDR_SLEB,
  2620. R_WASM_SECTION_OFFSET_I32,
  2621. R_WASM_TABLE_INDEX_I32,
  2622. R_WASM_FUNCTION_OFFSET_I32,
  2623. R_WASM_MEMORY_ADDR_I32,
  2624. R_WASM_TYPE_INDEX_LEB,
  2625. R_WASM_GLOBAL_INDEX_LEB,
  2626. R_WASM_TAG_INDEX_LEB,
  2627. R_WASM_GLOBAL_INDEX_I32]) then
  2628. begin
  2629. InputError('Unsupported relocation type: ' + tostr(Ord(RelocType)));
  2630. exit;
  2631. end;
  2632. if not ReadUleb32(RelocOffset) then
  2633. begin
  2634. InputError('Error reading the relocation offset of a relocation entry');
  2635. exit;
  2636. end;
  2637. if not ReadUleb32(RelocIndex) then
  2638. begin
  2639. InputError('Error reading the relocation index of a relocation entry');
  2640. exit;
  2641. end;
  2642. if RelocType in [R_WASM_FUNCTION_OFFSET_I32,R_WASM_SECTION_OFFSET_I32,R_WASM_MEMORY_ADDR_LEB,R_WASM_MEMORY_ADDR_SLEB,R_WASM_MEMORY_ADDR_I32] then
  2643. begin
  2644. if not ReadSleb32(RelocAddend) then
  2645. begin
  2646. InputError('Error reading the relocation addend of a relocation entry');
  2647. exit;
  2648. end;
  2649. end;
  2650. if (RelocType in [
  2651. R_WASM_SECTION_OFFSET_I32,
  2652. R_WASM_FUNCTION_INDEX_LEB,
  2653. R_WASM_TABLE_INDEX_SLEB,
  2654. R_WASM_TABLE_INDEX_I32,
  2655. R_WASM_MEMORY_ADDR_LEB,
  2656. R_WASM_MEMORY_ADDR_SLEB,
  2657. R_WASM_MEMORY_ADDR_I32,
  2658. R_WASM_FUNCTION_OFFSET_I32,
  2659. R_WASM_GLOBAL_INDEX_LEB,
  2660. R_WASM_GLOBAL_INDEX_I32]) and (RelocIndex>High(SymbolTable)) then
  2661. begin
  2662. InputError('Relocation index outside the bounds of the symbol table');
  2663. exit;
  2664. end;
  2665. if (RelocType=R_WASM_TYPE_INDEX_LEB) and (RelocIndex>High(FFuncTypes)) then
  2666. begin
  2667. InputError('Relocation index of R_WASM_TYPE_INDEX_LEB outside the bounds of the func types, defined in the func section of the module');
  2668. exit;
  2669. end;
  2670. if (RelocType=R_WASM_SECTION_OFFSET_I32) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_SECTION) then
  2671. begin
  2672. InputError('R_WASM_SECTION_OFFSET_I32 must point to a SYMTAB_SECTION symbol');
  2673. exit;
  2674. end;
  2675. if (RelocType in [R_WASM_GLOBAL_INDEX_LEB,R_WASM_GLOBAL_INDEX_I32]) and
  2676. not ((SymbolTable[RelocIndex].SymKind=SYMTAB_GLOBAL) or
  2677. ((ts_wasm_threads in current_settings.targetswitches) and
  2678. (SymbolTable[RelocIndex].SymKind=SYMTAB_DATA) and
  2679. ((SymbolTable[RelocIndex].SymFlags and WASM_SYM_TLS)<>0))) then
  2680. begin
  2681. if ts_wasm_threads in current_settings.targetswitches then
  2682. InputError('Relocation must point to a SYMTAB_GLOBAL symbol or a SYMTAB_DATA symbol with the WASM_SYM_TLS flag set')
  2683. else
  2684. InputError('Relocation must point to a SYMTAB_GLOBAL symbol');
  2685. exit;
  2686. end;
  2687. if (RelocType=R_WASM_TAG_INDEX_LEB) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_EVENT) then
  2688. begin
  2689. InputError('Relocation must point to a SYMTAB_EVENT symbol');
  2690. exit;
  2691. end;
  2692. if (RelocType in [
  2693. R_WASM_FUNCTION_INDEX_LEB,
  2694. R_WASM_TABLE_INDEX_SLEB,
  2695. R_WASM_TABLE_INDEX_I32,
  2696. R_WASM_FUNCTION_OFFSET_I32]) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_FUNCTION) then
  2697. begin
  2698. InputError('Relocation must point to a SYMTAB_FUNCTION symbol');
  2699. exit;
  2700. end;
  2701. if (RelocType in [
  2702. R_WASM_MEMORY_ADDR_LEB,
  2703. R_WASM_MEMORY_ADDR_SLEB,
  2704. R_WASM_MEMORY_ADDR_I32]) and (SymbolTable[RelocIndex].SymKind<>SYMTAB_DATA) then
  2705. begin
  2706. InputError('Relocation must point to a SYMTAB_DATA symbol');
  2707. exit;
  2708. end;
  2709. end;
  2710. if AReader.Pos<>(SectionStart+SectionSize) then
  2711. begin
  2712. InputError('Unexpected relocation section size');
  2713. exit;
  2714. end;
  2715. Result:=True;
  2716. end;
  2717. function ReadLinkingSection: Boolean;
  2718. function ReadSegmentInfo: Boolean;
  2719. var
  2720. SegmentCount: uint32;
  2721. i: Integer;
  2722. begin
  2723. Result:=False;
  2724. if SegmentInfoSectionRead then
  2725. begin
  2726. InputError('The WASM_SEGMENT_INFO subsection is duplicated');
  2727. exit;
  2728. end;
  2729. SegmentInfoSectionRead:=True;
  2730. if not ReadUleb32(SegmentCount) then
  2731. begin
  2732. InputError('Error reading the segment count from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2733. exit;
  2734. end;
  2735. if SegmentCount<>Length(DataSegments) then
  2736. begin
  2737. InputError('Segment count in the WASM_SEGMENT_INFO subsection does not match the data count in the data section');
  2738. exit;
  2739. end;
  2740. for i:=0 to SegmentCount-1 do
  2741. with DataSegments[i] do
  2742. begin
  2743. if not ReadName(SegName) then
  2744. begin
  2745. InputError('Error reading segment name from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2746. exit;
  2747. end;
  2748. if not ReadUleb32(SegAlignment) then
  2749. begin
  2750. InputError('Error reading segment alignment from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2751. exit;
  2752. end;
  2753. if not ReadUleb32(SegFlags) then
  2754. begin
  2755. InputError('Error reading segment flags from the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2756. exit;
  2757. end;
  2758. end;
  2759. if AReader.Pos<>(SectionStart+SectionSize) then
  2760. begin
  2761. InputError('Unexpected WASM_SEGMENT_INFO section size');
  2762. exit;
  2763. end;
  2764. Result:=True;
  2765. end;
  2766. function ReadSymbolTable: Boolean;
  2767. var
  2768. SymCount: uint32;
  2769. i: Integer;
  2770. SymKindName: string;
  2771. SymKindB: Byte;
  2772. begin
  2773. Result:=False;
  2774. if SymbolTableSectionRead then
  2775. begin
  2776. InputError('The WASM_SYMBOL_TABLE subsection is duplicated');
  2777. exit;
  2778. end;
  2779. SymbolTableSectionRead:=True;
  2780. if not ReadUleb32(SymCount) then
  2781. begin
  2782. InputError('Error reading the symbol count from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2783. exit;
  2784. end;
  2785. SetLength(SymbolTable,SymCount);
  2786. for i:=0 to SymCount-1 do
  2787. with SymbolTable[i] do
  2788. begin
  2789. if not Read(SymKindB,1) then
  2790. begin
  2791. InputError('Error reading symbol type from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2792. exit;
  2793. end;
  2794. if SymKindB>Ord(High(TWasmSymbolType)) then
  2795. begin
  2796. InputError('Unsupported symbol type from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2797. exit;
  2798. end;
  2799. SymKind:=TWasmSymbolType(SymKindB);
  2800. if not ReadUleb32(SymFlags) then
  2801. begin
  2802. InputError('Error reading symbol flags from the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2803. exit;
  2804. end;
  2805. case SymKind of
  2806. SYMTAB_FUNCTION,
  2807. SYMTAB_GLOBAL,
  2808. SYMTAB_EVENT,
  2809. SYMTAB_TABLE:
  2810. begin
  2811. WriteStr(SymKindName, SymKind);
  2812. if not ReadUleb32(SymIndex) then
  2813. begin
  2814. InputError('Error reading the index of a ' + SymKindName + ' symbol');
  2815. exit;
  2816. end;
  2817. if ((SymKind=SYMTAB_FUNCTION) and (SymIndex>high(FuncTypes))) or
  2818. ((SymKind=SYMTAB_EVENT) and (SymIndex>high(TagTypes))) then
  2819. begin
  2820. InputError('Symbol index too high');
  2821. exit;
  2822. end;
  2823. if ((SymFlags and WASM_SYM_EXPLICIT_NAME)<>0) or
  2824. ((SymFlags and WASM_SYM_UNDEFINED)=0) then
  2825. begin
  2826. if not ReadName(SymName) then
  2827. begin
  2828. InputError('Error reading symbol name of a ' + SymKindName + ' symbol');
  2829. exit;
  2830. end;
  2831. end;
  2832. end;
  2833. SYMTAB_DATA:
  2834. begin
  2835. if not ReadName(SymName) then
  2836. begin
  2837. InputError('Error reading symbol name of a SYMTAB_DATA symbol');
  2838. exit;
  2839. end;
  2840. if (SymFlags and WASM_SYM_UNDEFINED)=0 then
  2841. begin
  2842. if not ReadUleb32(SymIndex) then
  2843. begin
  2844. InputError('Error reading the data segment index of a SYMTAB_DATA symbol');
  2845. exit;
  2846. end;
  2847. if SymIndex>high(DataSegments) then
  2848. begin
  2849. InputError('Data segment index of SYMTAB_DATA symbol out of bounds');
  2850. exit;
  2851. end;
  2852. if not ReadUleb32(SymOffset) then
  2853. begin
  2854. InputError('Error reading the offset of a SYMTAB_DATA symbol');
  2855. exit;
  2856. end;
  2857. if not ReadUleb32(SymSize) then
  2858. begin
  2859. InputError('Error reading the size of a SYMTAB_DATA symbol');
  2860. exit;
  2861. end;
  2862. end;
  2863. end;
  2864. SYMTAB_FPC_CUSTOM:
  2865. begin
  2866. if not ReadName(SymName) then
  2867. begin
  2868. InputError('Error reading symbol name of a SYMTAB_FPC_CUSTOM symbol');
  2869. exit;
  2870. end;
  2871. if (SymFlags and WASM_SYM_UNDEFINED)=0 then
  2872. begin
  2873. if not ReadUleb32(SymCustomSectionIndex) then
  2874. begin
  2875. InputError('Error reading the custom section index of a SYMTAB_FPC_CUSTOM symbol');
  2876. exit;
  2877. end;
  2878. if not FindDebugSectionByIndex(SymCustomSectionIndex,SymCustomSectionType) then
  2879. begin
  2880. InputError('Custom section index of SYMTAB_FPC_CUSTOM symbol not pointing to a debug section');
  2881. exit;
  2882. end;
  2883. if not ReadUleb32(SymOffset) then
  2884. begin
  2885. InputError('Error reading the offset of a SYMTAB_FPC_CUSTOM symbol');
  2886. exit;
  2887. end;
  2888. if not ReadUleb32(SymSize) then
  2889. begin
  2890. InputError('Error reading the size of a SYMTAB_FPC_CUSTOM symbol');
  2891. exit;
  2892. end;
  2893. end;
  2894. end;
  2895. SYMTAB_SECTION:
  2896. begin
  2897. if not ReadUleb32(TargetSection) then
  2898. begin
  2899. InputError('Error reading the target section of a SYMTAB_SECTION symbol');
  2900. exit;
  2901. end;
  2902. end;
  2903. end;
  2904. end;
  2905. if AReader.Pos<>(SectionStart+SectionSize) then
  2906. begin
  2907. InputError('Unexpected WASM_SYMBOL_TABLE section size');
  2908. exit;
  2909. end;
  2910. Result:=True;
  2911. end;
  2912. const
  2913. ExpectedVersion = 2;
  2914. var
  2915. Version, SubsectionSize, SaveSectionSize: uint32;
  2916. SubsectionType: Byte;
  2917. SaveSectionStart: LongInt;
  2918. begin
  2919. Result:=False;
  2920. if not ReadUleb32(Version) then
  2921. begin
  2922. InputError('Error reading the version of the ''linking'' section');
  2923. exit;
  2924. end;
  2925. if Version<>ExpectedVersion then
  2926. begin
  2927. InputError('The ''linking'' section has an unsupported version (expected version ' + tostr(ExpectedVersion) + ', got version ' + tostr(Version) + ')');
  2928. exit;
  2929. end;
  2930. while AReader.Pos<(SectionStart+SectionSize) do
  2931. begin
  2932. if not read(SubsectionType, 1) then
  2933. begin
  2934. InputError('Error reading subsection type in the ''linking'' section');
  2935. exit;
  2936. end;
  2937. if not ReadUleb32(SubsectionSize) then
  2938. begin
  2939. InputError('Error reading subsection size in the ''linking'' section');
  2940. exit;
  2941. end;
  2942. if (AReader.Pos+SubsectionSize)>(SectionStart+SectionSize) then
  2943. begin
  2944. InputError('Subsection size exceeds bounds of its parent ''linking'' section');
  2945. exit;
  2946. end;
  2947. SaveSectionStart:=SectionStart;
  2948. SaveSectionSize:=SectionSize;
  2949. SectionStart:=AReader.Pos;
  2950. SectionSize:=SubsectionSize;
  2951. case SubsectionType of
  2952. Byte(WASM_SEGMENT_INFO):
  2953. if not ReadSegmentInfo then
  2954. begin
  2955. InputError('Error reading the WASM_SEGMENT_INFO subsection of the ''linking'' section');
  2956. exit;
  2957. end;
  2958. Byte(WASM_SYMBOL_TABLE):
  2959. if not ReadSymbolTable then
  2960. begin
  2961. InputError('Error reading the WASM_SYMBOL_TABLE subsection of the ''linking'' section');
  2962. exit;
  2963. end;
  2964. else
  2965. begin
  2966. InputError('Unsupported ''linking'' section subsection type ' + tostr(SubsectionType));
  2967. exit;
  2968. end;
  2969. end;
  2970. AReader.Seek(SectionStart+SectionSize);
  2971. SectionStart:=SaveSectionStart;
  2972. SectionSize:=SaveSectionSize;
  2973. end;
  2974. result:=True;
  2975. end;
  2976. function ReadProducersSection: Boolean;
  2977. begin
  2978. Result:=False;
  2979. end;
  2980. function ReadTargetFeaturesSection: Boolean;
  2981. begin
  2982. Result:=False;
  2983. end;
  2984. function ReadDebugSection(const SectionName: string; SectionType: TWasmCustomDebugSectionType): Boolean;
  2985. var
  2986. ObjSec: TObjSection;
  2987. begin
  2988. Result:=False;
  2989. if DebugSectionIndex[SectionType]<>-1 then
  2990. begin
  2991. InputError('Duplicated debug section: ' + SectionName);
  2992. exit;
  2993. end;
  2994. DebugSectionIndex[SectionType]:=SectionIndex;
  2995. ObjSec:=ObjData.createsection(SectionName,1,[oso_Data,oso_debug],false);
  2996. ObjSec.DataPos:=AReader.Pos;
  2997. ObjSec.Size:=SectionStart+SectionSize-AReader.Pos;
  2998. Result:=True;
  2999. end;
  3000. const
  3001. RelocationSectionPrefix = 'reloc.';
  3002. var
  3003. SectionName: ansistring;
  3004. begin
  3005. Result:=False;
  3006. ReadName(SectionName);
  3007. if Copy(SectionName,1,Length(RelocationSectionPrefix)) = RelocationSectionPrefix then
  3008. begin
  3009. if not ReadRelocationSection then
  3010. begin
  3011. InputError('Error reading the relocation section ''' + SectionName + '''');
  3012. exit;
  3013. end;
  3014. end
  3015. else
  3016. case SectionName of
  3017. 'linking':
  3018. if not ReadLinkingSection then
  3019. begin
  3020. InputError('Error reading the ''linking'' section');
  3021. exit;
  3022. end;
  3023. 'producers':
  3024. Result:=ReadProducersSection;
  3025. 'target_features':
  3026. Result:=ReadTargetFeaturesSection;
  3027. '.debug_frame':
  3028. if not ReadDebugSection(SectionName, wcstDebugFrame) then
  3029. begin
  3030. InputError('Error reading section ' + SectionName);
  3031. exit;
  3032. end;
  3033. '.debug_info':
  3034. if not ReadDebugSection(SectionName, wcstDebugInfo) then
  3035. begin
  3036. InputError('Error reading section ' + SectionName);
  3037. exit;
  3038. end;
  3039. '.debug_line':
  3040. if not ReadDebugSection(SectionName, wcstDebugLine) then
  3041. begin
  3042. InputError('Error reading section ' + SectionName);
  3043. exit;
  3044. end;
  3045. '.debug_abbrev':
  3046. if not ReadDebugSection(SectionName, wcstDebugAbbrev) then
  3047. begin
  3048. InputError('Error reading section ' + SectionName);
  3049. exit;
  3050. end;
  3051. '.debug_aranges':
  3052. if not ReadDebugSection(SectionName, wcstDebugAranges) then
  3053. begin
  3054. InputError('Error reading section ' + SectionName);
  3055. exit;
  3056. end;
  3057. '.debug_ranges':
  3058. if not ReadDebugSection(SectionName, wcstDebugRanges) then
  3059. begin
  3060. InputError('Error reading section ' + SectionName);
  3061. exit;
  3062. end;
  3063. '.debug_str':
  3064. if not ReadDebugSection(SectionName, wcstDebugStr) then
  3065. begin
  3066. InputError('Error reading section ' + SectionName);
  3067. exit;
  3068. end;
  3069. else
  3070. InputError('Unsupported custom section: ''' + SectionName + '''');
  3071. end;
  3072. Result:=True;
  3073. end;
  3074. function ReadTypeSection: Boolean;
  3075. var
  3076. FuncTypesCount, ParamsCount, ResultsCount: uint32;
  3077. FuncTypeId, WasmTypeId: Byte;
  3078. i, j: Integer;
  3079. wbt: TWasmBasicType;
  3080. begin
  3081. Result:=False;
  3082. if TypeSectionRead then
  3083. begin
  3084. InputError('Type section is duplicated');
  3085. exit;
  3086. end;
  3087. TypeSectionRead:=True;
  3088. if not ReadUleb32(FuncTypesCount) then
  3089. begin
  3090. InputError('Error reading the func types count');
  3091. exit;
  3092. end;
  3093. SetLength(FFuncTypes,FuncTypesCount);
  3094. for i:=0 to FuncTypesCount - 1 do
  3095. begin
  3096. FFuncTypes[i]:=TWasmFuncType.Create([],[]);
  3097. if not AReader.read(FuncTypeId,1) then
  3098. begin
  3099. InputError('Error reading the function type identifier');
  3100. exit;
  3101. end;
  3102. if FuncTypeId<>$60 then
  3103. begin
  3104. InputError('Incorrect function type identifier (expected $60, got $' + HexStr(FuncTypeId,2) + ')');
  3105. exit;
  3106. end;
  3107. if not ReadUleb32(ParamsCount) then
  3108. begin
  3109. InputError('Error reading the function parameters count');
  3110. exit;
  3111. end;
  3112. for j:=0 to ParamsCount-1 do
  3113. begin
  3114. if not AReader.read(WasmTypeId,1) then
  3115. begin
  3116. InputError('Error reading a function parameter basic type');
  3117. exit;
  3118. end;
  3119. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  3120. begin
  3121. InputError('Unknown function parameter basic type: $' + HexStr(WasmTypeId,2));
  3122. exit;
  3123. end;
  3124. FFuncTypes[i].add_param(wbt);
  3125. end;
  3126. if not ReadUleb32(ResultsCount) then
  3127. begin
  3128. InputError('Error reading the function results count');
  3129. exit;
  3130. end;
  3131. for j:=0 to ResultsCount-1 do
  3132. begin
  3133. if not AReader.read(WasmTypeId,1) then
  3134. begin
  3135. InputError('Error reading a function result basic type');
  3136. exit;
  3137. end;
  3138. if not decode_wasm_basic_type(WasmTypeId,wbt) then
  3139. begin
  3140. InputError('Unknown function result basic type: $' + HexStr(WasmTypeId,2));
  3141. exit;
  3142. end;
  3143. FFuncTypes[i].add_result(wbt);
  3144. end;
  3145. end;
  3146. if AReader.Pos<>(SectionStart+SectionSize) then
  3147. begin
  3148. InputError('Unexpected type section size');
  3149. exit;
  3150. end;
  3151. Result:=true;
  3152. end;
  3153. function ReadImportSection: Boolean;
  3154. var
  3155. ImportsCount: uint32;
  3156. i: Integer;
  3157. ModName, Name: ansistring;
  3158. ImportType, TableElemTyp, TableLimitsKind, MemoryLimitsKind,
  3159. GlobalType, GlobalMutabilityType: Byte;
  3160. begin
  3161. Result:=False;
  3162. if ImportSectionRead then
  3163. begin
  3164. InputError('Import section is duplicated');
  3165. exit;
  3166. end;
  3167. ImportSectionRead:=True;
  3168. if not ReadUleb32(ImportsCount) then
  3169. begin
  3170. InputError('Error reading the imports count');
  3171. exit;
  3172. end;
  3173. for i:=0 to ImportsCount-1 do
  3174. begin
  3175. if not ReadName(ModName) then
  3176. begin
  3177. InputError('Error reading import module name');
  3178. exit;
  3179. end;
  3180. if not ReadName(Name) then
  3181. begin
  3182. InputError('Error import name');
  3183. exit;
  3184. end;
  3185. if not AReader.Read(ImportType,1) then
  3186. begin
  3187. InputError('Error reading import type');
  3188. exit;
  3189. end;
  3190. case ImportType of
  3191. $00: { func }
  3192. begin
  3193. Inc(FuncTypeImportsCount);
  3194. SetLength(FuncTypes,FuncTypeImportsCount);
  3195. with FuncTypes[FuncTypeImportsCount-1] do
  3196. begin
  3197. IsImport:=True;
  3198. ImportName:=Name;
  3199. ImportModName:=ModName;
  3200. if not ReadUleb32(typidx) then
  3201. begin
  3202. InputError('Error reading type index for func import');
  3203. exit;
  3204. end;
  3205. if typidx>high(FFuncTypes) then
  3206. begin
  3207. InputError('Type index in func import exceeds bounds of the types table');
  3208. exit;
  3209. end;
  3210. end;
  3211. end;
  3212. $01: { table }
  3213. begin
  3214. Inc(TableTypeImportsCount);
  3215. SetLength(TableTypes,TableTypeImportsCount);
  3216. with TableTypes[TableTypeImportsCount-1] do
  3217. begin
  3218. IsImport:=True;
  3219. ImportName:=Name;
  3220. ImportModName:=ModName;
  3221. if not AReader.read(TableElemTyp,1) then
  3222. begin
  3223. InputError('Error reading table element type for table import');
  3224. exit;
  3225. end;
  3226. if not decode_wasm_basic_type(TableElemTyp,reftype) then
  3227. begin
  3228. InputError('Invalid table element type for table import: $' + HexStr(TableElemTyp,2));
  3229. exit;
  3230. end;
  3231. if not (reftype in WasmReferenceTypes) then
  3232. begin
  3233. InputError('Table element type for table import must be a reference type');
  3234. exit;
  3235. end;
  3236. if not AReader.read(TableLimitsKind,1) then
  3237. begin
  3238. InputError('Error reading table limits kind for table import');
  3239. exit;
  3240. end;
  3241. case TableLimitsKind of
  3242. $00:
  3243. begin
  3244. limits.HasMax:=False;
  3245. limits.Max:=high(limits.Max);
  3246. if not ReadUleb32(limits.min) then
  3247. begin
  3248. InputError('Error reading table limits min for table import');
  3249. exit;
  3250. end;
  3251. end;
  3252. $01:
  3253. begin
  3254. limits.HasMax:=True;
  3255. if not ReadUleb32(limits.min) then
  3256. begin
  3257. InputError('Error reading table limits min for table import');
  3258. exit;
  3259. end;
  3260. if not ReadUleb32(limits.max) then
  3261. begin
  3262. InputError('Error reading table limits max for table import');
  3263. exit;
  3264. end;
  3265. if limits.min>limits.max then
  3266. begin
  3267. InputError('Table limits min exceed table limits max in table import');
  3268. exit;
  3269. end;
  3270. end;
  3271. else
  3272. begin
  3273. InputError('Unsupported table limits kind for table import: $' + HexStr(TableLimitsKind,2));
  3274. exit;
  3275. end;
  3276. end;
  3277. end;
  3278. end;
  3279. $02: { mem }
  3280. begin
  3281. Inc(MemTypeImportsCount);
  3282. SetLength(MemTypes,MemTypeImportsCount);
  3283. with MemTypes[MemTypeImportsCount-1] do
  3284. begin
  3285. IsImport:=True;
  3286. ImportName:=Name;
  3287. ImportModName:=ModName;
  3288. if not AReader.read(MemoryLimitsKind,1) then
  3289. begin
  3290. InputError('Error reading memory limits kind for memory import');
  3291. exit;
  3292. end;
  3293. case MemoryLimitsKind of
  3294. $00:
  3295. begin
  3296. limits.HasMax:=False;
  3297. limits.Max:=high(limits.Max);
  3298. if not ReadUleb32(limits.min) then
  3299. begin
  3300. InputError('Error reading memory limits min for memory import');
  3301. exit;
  3302. end;
  3303. end;
  3304. $01:
  3305. begin
  3306. limits.HasMax:=True;
  3307. if not ReadUleb32(limits.min) then
  3308. begin
  3309. InputError('Error reading memory limits min for memory import');
  3310. exit;
  3311. end;
  3312. if not ReadUleb32(limits.max) then
  3313. begin
  3314. InputError('Error reading memory limits max for memory import');
  3315. exit;
  3316. end;
  3317. if limits.Min>limits.Max then
  3318. begin
  3319. InputError('Memory limits min exceed memory limits max in memory import');
  3320. exit;
  3321. end;
  3322. end;
  3323. else
  3324. begin
  3325. InputError('Unsupported memory limits kind for memory import: $' + HexStr(MemoryLimitsKind,2));
  3326. exit;
  3327. end;
  3328. end;
  3329. end;
  3330. end;
  3331. $03: { global }
  3332. begin
  3333. Inc(GlobalTypeImportsCount);
  3334. SetLength(GlobalTypes,GlobalTypeImportsCount);
  3335. with GlobalTypes[GlobalTypeImportsCount-1] do
  3336. begin
  3337. IsImport:=True;
  3338. ImportName:=Name;
  3339. ImportModName:=ModName;
  3340. if not AReader.read(GlobalType,1) then
  3341. begin
  3342. InputError('Error reading global type for global import');
  3343. exit;
  3344. end;
  3345. if not decode_wasm_basic_type(GlobalType,valtype) then
  3346. begin
  3347. InputError('Unsupported global type for global import: ' + HexStr(GlobalType,2));
  3348. exit;
  3349. end;
  3350. if not AReader.read(GlobalMutabilityType,1) then
  3351. begin
  3352. InputError('Error reading global mutability flag for global import');
  3353. exit;
  3354. end;
  3355. case GlobalMutabilityType of
  3356. $00:
  3357. IsMutable:=False;
  3358. $01:
  3359. IsMutable:=True;
  3360. else
  3361. begin
  3362. InputError('Unknown global mutability flag for global import: $' + HexStr(GlobalMutabilityType,2));
  3363. exit;
  3364. end;
  3365. end;
  3366. end;
  3367. end;
  3368. $04: { tag }
  3369. begin
  3370. Inc(TagTypeImportsCount);
  3371. SetLength(TagTypes,TagTypeImportsCount);
  3372. with TagTypes[TagTypeImportsCount-1] do
  3373. begin
  3374. IsImport:=True;
  3375. ImportName:=Name;
  3376. ImportModName:=ModName;
  3377. if not Read(TagAttr,1) then
  3378. begin
  3379. InputError('Error reading import tag attribute');
  3380. exit;
  3381. end;
  3382. if not ReadUleb32(TagTypeIdx) then
  3383. begin
  3384. InputError('Error reading import tag type index');
  3385. exit;
  3386. end;
  3387. if TagTypeIdx>high(FFuncTypes) then
  3388. begin
  3389. InputError('Type index in tag import exceeds bounds of the types table');
  3390. exit;
  3391. end;
  3392. end;
  3393. end;
  3394. else
  3395. begin
  3396. InputError('Unknown import type: $' + HexStr(ImportType,2));
  3397. exit;
  3398. end;
  3399. end;
  3400. end;
  3401. if AReader.Pos<>(SectionStart+SectionSize) then
  3402. begin
  3403. InputError('Unexpected import section size');
  3404. exit;
  3405. end;
  3406. Result:=true;
  3407. end;
  3408. function ReadFunctionSection: Boolean;
  3409. var
  3410. FunctionsCount: uint32;
  3411. i: Integer;
  3412. begin
  3413. Result:=False;
  3414. if FunctionSectionRead then
  3415. begin
  3416. InputError('Function section is duplicated');
  3417. exit;
  3418. end;
  3419. FunctionSectionRead:=True;
  3420. if not ReadUleb32(FunctionsCount) then
  3421. begin
  3422. InputError('Error reading the functions count');
  3423. exit;
  3424. end;
  3425. SetLength(FuncTypes, FuncTypeImportsCount + FunctionsCount);
  3426. for i:=0 to FunctionsCount-1 do
  3427. with FuncTypes[i + FuncTypeImportsCount] do
  3428. begin
  3429. IsImport:=False;
  3430. if not ReadUleb32(typidx) then
  3431. begin
  3432. InputError('Error reading type index for function');
  3433. exit;
  3434. end;
  3435. if typidx>high(FFuncTypes) then
  3436. begin
  3437. InputError('Type index in the function section exceeds bounds of the types table');
  3438. exit;
  3439. end;
  3440. end;
  3441. if AReader.Pos<>(SectionStart+SectionSize) then
  3442. begin
  3443. InputError('Unexpected function section size');
  3444. exit;
  3445. end;
  3446. Result:=true;
  3447. end;
  3448. function ReadGlobalSection: Boolean;
  3449. function ParseExpr(out Init: TGlobalInitializer): Boolean;
  3450. var
  3451. B, B2: Byte;
  3452. tmpU32: UInt32;
  3453. tmpU64: UInt64;
  3454. begin
  3455. Result:=False;
  3456. repeat
  3457. if not Read(B, 1) then
  3458. exit;
  3459. case B of
  3460. $0B: { end }
  3461. ;
  3462. $41: { i32.const }
  3463. begin
  3464. Init.typ:=wbt_i32;
  3465. if not ReadSleb32(Init.init_i32) then
  3466. exit;
  3467. end;
  3468. $42: { i64.const }
  3469. begin
  3470. Init.typ:=wbt_i64;
  3471. if not ReadSleb(Init.init_i64) then
  3472. exit;
  3473. end;
  3474. $43: { f32.const }
  3475. begin
  3476. Init.typ:=wbt_f32;
  3477. if not Read(tmpU32, 4) then
  3478. exit;
  3479. {$ifdef FPC_BIG_ENDIAN}
  3480. tmpU32:=SwapEndian(tmpU32);
  3481. {$endif FPC_BIG_ENDIAN}
  3482. Move(tmpU32,Init.init_f32,4);
  3483. end;
  3484. $44: { f64.const }
  3485. begin
  3486. Init.typ:=wbt_f64;
  3487. if not Read(tmpU64, 8) then
  3488. exit;
  3489. {$ifdef FPC_BIG_ENDIAN}
  3490. tmpU64:=SwapEndian(tmpU64);
  3491. {$endif FPC_BIG_ENDIAN}
  3492. Move(tmpU64,Init.init_f64,8);
  3493. end;
  3494. $D0: { ref.null }
  3495. begin
  3496. if not Read(B2, 1) then
  3497. exit;
  3498. if not decode_wasm_basic_type(B2, Init.typ) then
  3499. exit;
  3500. if not (Init.typ in WasmReferenceTypes) then
  3501. exit;
  3502. end;
  3503. else
  3504. begin
  3505. InputError('Unsupported opcode in global initializer');
  3506. exit;
  3507. end;
  3508. end;
  3509. until b = $0B;
  3510. Result:=True;
  3511. end;
  3512. var
  3513. GlobalsCount: uint32;
  3514. i: Integer;
  3515. vt: Byte;
  3516. mut: Byte;
  3517. begin
  3518. Result:=False;
  3519. if GlobalSectionRead then
  3520. begin
  3521. InputError('Global section is duplicated');
  3522. exit;
  3523. end;
  3524. GlobalSectionRead:=True;
  3525. if not ReadUleb32(GlobalsCount) then
  3526. begin
  3527. InputError('Error reading the globals count from the global section');
  3528. exit;
  3529. end;
  3530. SetLength(GlobalTypes,Length(GlobalTypes)+GlobalsCount);
  3531. for i:=0 to GlobalsCount-1 do
  3532. with GlobalTypes[i + GlobalTypeImportsCount] do
  3533. begin
  3534. if not read(vt,1) then
  3535. begin
  3536. InputError('Error reading the type of a global from the global section');
  3537. exit;
  3538. end;
  3539. if not decode_wasm_basic_type(vt,valtype) then
  3540. begin
  3541. InputError('Unsupported type of global in the global section');
  3542. exit;
  3543. end;
  3544. if not read(mut,1) then
  3545. begin
  3546. InputError('Error reading the mutability flag of a global in the global section');
  3547. exit;
  3548. end;
  3549. case mut of
  3550. $00:
  3551. IsMutable:=False;
  3552. $01:
  3553. IsMutable:=True;
  3554. else
  3555. begin
  3556. InputError('Unsupported value (' + tostr(mut) + ') for the mutability flag of a global in the global section');
  3557. exit;
  3558. end;
  3559. end;
  3560. if not ParseExpr(GlobalInit) then
  3561. begin
  3562. InputError('Error parsing the global initializer expression in the global section');
  3563. exit;
  3564. end;
  3565. if GlobalInit.typ<>valtype then
  3566. begin
  3567. InputError('Initializer expression for global produces a type, which does not match the type of the global');
  3568. exit;
  3569. end;
  3570. end;
  3571. if AReader.Pos<>(SectionStart+SectionSize) then
  3572. begin
  3573. InputError('Unexpected global section size');
  3574. exit;
  3575. end;
  3576. Result:=True;
  3577. end;
  3578. function ReadExportSection: Boolean;
  3579. var
  3580. ExportsCount, FuncIdx, TableIdx, MemIdx, GlobalIdx, TagIdx: uint32;
  3581. i: Integer;
  3582. Name: ansistring;
  3583. ExportType: Byte;
  3584. begin
  3585. Result:=False;
  3586. if ExportSectionRead then
  3587. begin
  3588. InputError('Export section is duplicated');
  3589. exit;
  3590. end;
  3591. ExportSectionRead:=True;
  3592. if not ReadUleb32(ExportsCount) then
  3593. begin
  3594. InputError('Error reading the exports count from the export section');
  3595. exit;
  3596. end;
  3597. for i:=0 to ExportsCount-1 do
  3598. begin
  3599. if not ReadName(Name) then
  3600. begin
  3601. InputError('Error reading an export name from the export section');
  3602. exit;
  3603. end;
  3604. if not Read(ExportType,1) then
  3605. begin
  3606. InputError('Error reading an export type from the export section');
  3607. exit;
  3608. end;
  3609. case ExportType of
  3610. $00: { func }
  3611. begin
  3612. if not ReadUleb32(FuncIdx) then
  3613. begin
  3614. InputError('Error reading a func index from the export section');
  3615. exit;
  3616. end;
  3617. if FuncIdx>high(FuncTypes) then
  3618. begin
  3619. InputError('Func index too high in the export section');
  3620. exit;
  3621. end;
  3622. with FuncTypes[FuncIdx] do
  3623. begin
  3624. IsExported:=True;
  3625. ExportName:=Name;
  3626. end;
  3627. end;
  3628. $01: { table }
  3629. begin
  3630. if not ReadUleb32(TableIdx) then
  3631. begin
  3632. InputError('Error reading a table index from the export section');
  3633. exit;
  3634. end;
  3635. if TableIdx>high(TableTypes) then
  3636. begin
  3637. InputError('Table index too high in the export section');
  3638. exit;
  3639. end;
  3640. with TableTypes[TableIdx] do
  3641. begin
  3642. IsExported:=True;
  3643. ExportName:=Name;
  3644. end;
  3645. end;
  3646. $02: { mem }
  3647. begin
  3648. if not ReadUleb32(MemIdx) then
  3649. begin
  3650. InputError('Error reading a mem index from the export section');
  3651. exit;
  3652. end;
  3653. if MemIdx>high(MemTypes) then
  3654. begin
  3655. InputError('Mem index too high in the export section');
  3656. exit;
  3657. end;
  3658. with MemTypes[MemIdx] do
  3659. begin
  3660. IsExported:=True;
  3661. ExportName:=Name;
  3662. end;
  3663. end;
  3664. $03: { global }
  3665. begin
  3666. if not ReadUleb32(GlobalIdx) then
  3667. begin
  3668. InputError('Error reading a global index from the export section');
  3669. exit;
  3670. end;
  3671. if GlobalIdx>high(GlobalTypes) then
  3672. begin
  3673. InputError('Global index too high in the export section');
  3674. exit;
  3675. end;
  3676. with GlobalTypes[GlobalIdx] do
  3677. begin
  3678. IsExported:=True;
  3679. ExportName:=Name;
  3680. end;
  3681. end;
  3682. $04: { tag }
  3683. begin
  3684. if not ReadUleb32(TagIdx) then
  3685. begin
  3686. InputError('Error reading a tag index from the export section');
  3687. exit;
  3688. end;
  3689. if TagIdx>high(TagTypes) then
  3690. begin
  3691. InputError('Tag index too high in the export section');
  3692. exit;
  3693. end;
  3694. with TagTypes[TagIdx] do
  3695. begin
  3696. IsExported:=True;
  3697. ExportName:=Name;
  3698. end;
  3699. end;
  3700. else
  3701. begin
  3702. InputError('Unsupported export type in the export section: ' + tostr(ExportType));
  3703. exit;
  3704. end;
  3705. end;
  3706. end;
  3707. if AReader.Pos<>(SectionStart+SectionSize) then
  3708. begin
  3709. InputError('Unexpected export section size');
  3710. exit;
  3711. end;
  3712. Result:=True;
  3713. end;
  3714. function ReadElementSection: Boolean;
  3715. begin
  3716. Result:=False;
  3717. if ElementSectionRead then
  3718. begin
  3719. InputError('Element section is duplicated');
  3720. exit;
  3721. end;
  3722. ElementSectionRead:=True;
  3723. { We skip the element section for now }
  3724. { TODO: implement reading it (and linking of tables) }
  3725. Result:=True;
  3726. end;
  3727. function ReadTagSection: Boolean;
  3728. var
  3729. TagCount: uint32;
  3730. i: Integer;
  3731. begin
  3732. Result:=False;
  3733. if TagSectionRead then
  3734. begin
  3735. InputError('Tag section is duplicated');
  3736. exit;
  3737. end;
  3738. TagSectionRead:=True;
  3739. if not ReadUleb32(TagCount) then
  3740. begin
  3741. InputError('Error reading the tag count from the tag section');
  3742. exit;
  3743. end;
  3744. SetLength(TagTypes,Length(TagTypes)+TagCount);
  3745. for i:=0 to TagCount-1 do
  3746. with TagTypes[i + TagTypeImportsCount] do
  3747. begin
  3748. if not Read(TagAttr,1) then
  3749. begin
  3750. InputError('Error reading tag attribute');
  3751. exit;
  3752. end;
  3753. if not ReadUleb32(TagTypeIdx) then
  3754. begin
  3755. InputError('Error reading tag type index');
  3756. exit;
  3757. end;
  3758. if TagTypeIdx>high(FFuncTypes) then
  3759. begin
  3760. InputError('Type index in tag import exceeds bounds of the types table');
  3761. exit;
  3762. end;
  3763. end;
  3764. if AReader.Pos<>(SectionStart+SectionSize) then
  3765. begin
  3766. InputError('Unexpected tag section size');
  3767. exit;
  3768. end;
  3769. Result:=True;
  3770. end;
  3771. function ReadCodeSection: Boolean;
  3772. var
  3773. CodeEntriesCount: uint32;
  3774. i: Integer;
  3775. begin
  3776. Result:=False;
  3777. if CodeSectionRead then
  3778. begin
  3779. InputError('Code section is duplicated');
  3780. exit;
  3781. end;
  3782. CodeSectionRead:=True;
  3783. CodeSectionIndex:=SectionIndex;
  3784. if not ReadUleb32(CodeEntriesCount) then
  3785. begin
  3786. InputError('Error reading the code entries cound from the code section');
  3787. exit;
  3788. end;
  3789. if CodeEntriesCount <> (Length(FuncTypes) - FuncTypeImportsCount) then
  3790. begin
  3791. InputError('Code segment count in the code section does not match the function definition count in the function section');
  3792. exit;
  3793. end;
  3794. SetLength(CodeSegments,CodeEntriesCount);
  3795. for i:=0 to CodeEntriesCount-1 do
  3796. with CodeSegments[i] do
  3797. begin
  3798. if not ReadUleb32(CodeSize) then
  3799. begin
  3800. InputError('Error reading the code size of an entry in the code section');
  3801. exit;
  3802. end;
  3803. if (AReader.Pos+CodeSize)>(SectionStart+SectionSize) then
  3804. begin
  3805. InputError('Code segment exceeds the bounds of the code section');
  3806. exit;
  3807. end;
  3808. DataPos:=AReader.Pos;
  3809. CodeSectionOffset:=AReader.Pos-SectionStart;
  3810. AReader.Seek(AReader.Pos+CodeSize);
  3811. end;
  3812. if AReader.Pos<>(SectionStart+SectionSize) then
  3813. begin
  3814. InputError('Unexpected code section size');
  3815. exit;
  3816. end;
  3817. Result:=true;
  3818. end;
  3819. function ReadDataSection: Boolean;
  3820. function ReadExpr(out ExprV: int32): Boolean;
  3821. var
  3822. b: Byte;
  3823. begin
  3824. Result:=False;
  3825. if not Read(b,1) then
  3826. exit;
  3827. if b<>$41 then
  3828. begin
  3829. InputError('Only i32.const expressions supported');
  3830. exit;
  3831. end;
  3832. if not ReadSleb32(ExprV) then
  3833. exit;
  3834. if not Read(b,1) then
  3835. exit;
  3836. if b<>$0B then
  3837. begin
  3838. InputError('Only single const expressions supported');
  3839. exit;
  3840. end;
  3841. Result:=True;
  3842. end;
  3843. var
  3844. DataCount: uint32;
  3845. DataType: Byte;
  3846. i: Integer;
  3847. begin
  3848. Result:=False;
  3849. if DataSectionRead then
  3850. begin
  3851. InputError('Data section is duplicated');
  3852. exit;
  3853. end;
  3854. DataSectionRead:=True;
  3855. DataSectionIndex:=SectionIndex;
  3856. if not ReadUleb32(DataCount) then
  3857. begin
  3858. InputError('Error reading the data entries count from the data section');
  3859. exit;
  3860. end;
  3861. if DataCountSectionRead then
  3862. begin
  3863. if Length(DataSegments)<>DataCount then
  3864. begin
  3865. InputError('Data entries count in the data section do not match the number, specified in the data count section');
  3866. exit;
  3867. end;
  3868. end
  3869. else
  3870. SetLength(DataSegments,DataCount);
  3871. for i:=0 to DataCount-1 do
  3872. with DataSegments[i] do
  3873. begin
  3874. if not read(DataType, 1) then
  3875. begin
  3876. InputError('Error reading data type of segment from the data section');
  3877. exit;
  3878. end;
  3879. case DataType of
  3880. 0:
  3881. begin
  3882. Active:=True;
  3883. MemIdx:=0;
  3884. if not ReadExpr(Offset) then
  3885. begin
  3886. InputError('Error reading memory offset of segment from the data section');
  3887. exit;
  3888. end;
  3889. end;
  3890. 1:
  3891. Active:=False;
  3892. 2:
  3893. begin
  3894. Active:=True;
  3895. if not ReadUleb32(MemIdx) then
  3896. begin
  3897. InputError('Error reading MemIdx of segment from the data section');
  3898. exit;
  3899. end;
  3900. if not ReadExpr(Offset) then
  3901. begin
  3902. InputError('Error reading memory offset of segment from the data section');
  3903. exit;
  3904. end;
  3905. end;
  3906. else
  3907. begin
  3908. InputError('Unsupported data type of segment in the data section: ' + tostr(DataType));
  3909. exit;
  3910. end;
  3911. end;
  3912. if MemIdx<>0 then
  3913. begin
  3914. InputError('Memory index other than 0 not supported (got ' + tostr(MemIdx) + ')');
  3915. exit;
  3916. end;
  3917. if not Active then
  3918. begin
  3919. InputError('Passive memory segments not supported');
  3920. exit;
  3921. end;
  3922. if not ReadUleb32(Len) then
  3923. begin
  3924. InputError('Error reading data segment length');
  3925. exit;
  3926. end;
  3927. if (AReader.Pos+Len)>(SectionStart+SectionSize) then
  3928. begin
  3929. InputError('Data segment exceeds the bounds of the data section');
  3930. exit;
  3931. end;
  3932. DataPos:=AReader.Pos;
  3933. DataSectionOffset:=AReader.Pos-SectionStart;
  3934. AReader.Seek(AReader.Pos+Len);
  3935. end;
  3936. if AReader.Pos<>(SectionStart+SectionSize) then
  3937. begin
  3938. InputError('Unexpected data section size');
  3939. exit;
  3940. end;
  3941. Result:=true;
  3942. end;
  3943. function ReadDataCountSection: Boolean;
  3944. var
  3945. DataCount: uint32;
  3946. begin
  3947. Result:=False;
  3948. if DataCountSectionRead then
  3949. begin
  3950. InputError('Data count section is duplicated');
  3951. exit;
  3952. end;
  3953. DataCountSectionRead:=True;
  3954. if DataSectionRead then
  3955. begin
  3956. InputError('The data count section must occur before the data section');
  3957. exit;
  3958. end;
  3959. if not ReadUleb32(DataCount) then
  3960. begin
  3961. InputError('Error reading the data count from the data count section');
  3962. exit;
  3963. end;
  3964. if AReader.Pos<>(SectionStart+SectionSize) then
  3965. begin
  3966. InputError('Unexpected data count section size');
  3967. exit;
  3968. end;
  3969. SetLength(DataSegments, DataCount);
  3970. Result:=true;
  3971. end;
  3972. begin
  3973. Result:=False;
  3974. Inc(SectionIndex);
  3975. if not AReader.read(SectionId,1) then
  3976. begin
  3977. InputError('Error reading section ID');
  3978. exit;
  3979. end;
  3980. CheckSectionBounds:=false;
  3981. if not ReadUleb32(SectionSize) then
  3982. begin
  3983. InputError('Error reading section size');
  3984. exit;
  3985. end;
  3986. if (AReader.Pos+SectionSize)>AReader.size then
  3987. begin
  3988. InputError('Section exceeds beyond the end of file');
  3989. exit;
  3990. end;
  3991. SectionStart:=AReader.Pos;
  3992. CheckSectionBounds:=true;
  3993. case SectionId of
  3994. Byte(wsiCustom):
  3995. if not ReadCustomSection then
  3996. begin
  3997. InputError('Error encountered, while reading a custom section');
  3998. exit;
  3999. end;
  4000. Byte(wsiType):
  4001. if not ReadTypeSection then
  4002. begin
  4003. InputError('Error reading the type section');
  4004. exit;
  4005. end;
  4006. Byte(wsiImport):
  4007. if not ReadImportSection then
  4008. begin
  4009. InputError('Error reading the import section');
  4010. exit;
  4011. end;
  4012. Byte(wsiFunction):
  4013. if not ReadFunctionSection then
  4014. begin
  4015. InputError('Error reading the function section');
  4016. exit;
  4017. end;
  4018. Byte(wsiGlobal):
  4019. if not ReadGlobalSection then
  4020. begin
  4021. InputError('Error reading the global section');
  4022. exit;
  4023. end;
  4024. Byte(wsiExport):
  4025. if not ReadExportSection then
  4026. begin
  4027. InputError('Error reading the export section');
  4028. exit;
  4029. end;
  4030. Byte(wsiElement):
  4031. if not ReadElementSection then
  4032. begin
  4033. InputError('Error reading the element section');
  4034. exit;
  4035. end;
  4036. Byte(wsiTag):
  4037. if not ReadTagSection then
  4038. begin
  4039. InputError('Error reading the tag section');
  4040. exit;
  4041. end;
  4042. Byte(wsiCode):
  4043. if not ReadCodeSection then
  4044. begin
  4045. InputError('Error reading the code section');
  4046. exit;
  4047. end;
  4048. Byte(wsiData):
  4049. if not ReadDataSection then
  4050. begin
  4051. InputError('Error reading the data section');
  4052. exit;
  4053. end;
  4054. Byte(wsiDataCount):
  4055. begin
  4056. if not ReadDataCountSection then
  4057. begin
  4058. InputError('Error reading the data count section');
  4059. exit;
  4060. end;
  4061. end
  4062. else
  4063. begin
  4064. InputError('Unknown section: ' + ToStr(SectionId));
  4065. exit;
  4066. end;
  4067. end;
  4068. if SectionSize>0 then
  4069. AReader.seek(SectionStart+SectionSize);
  4070. Result:=True;
  4071. end;
  4072. function FindCodeSegment(Ofs: uint32): Integer;
  4073. var
  4074. L, R, M: Integer;
  4075. begin
  4076. L:=Low(CodeSegments);
  4077. R:=High(CodeSegments);
  4078. while L<=R do
  4079. begin
  4080. M:=(L+R) div 2;
  4081. if (CodeSegments[M].CodeSectionOffset+CodeSegments[M].CodeSize-1) < Ofs then
  4082. L:=M+1
  4083. else if CodeSegments[M].CodeSectionOffset > Ofs then
  4084. R:=M-1
  4085. else
  4086. begin
  4087. Result:=M;
  4088. exit;
  4089. end;
  4090. end;
  4091. Result:=-1;
  4092. end;
  4093. function FindDataSegment(Ofs: uint32): Integer;
  4094. var
  4095. L, R, M: Integer;
  4096. begin
  4097. L:=Low(DataSegments);
  4098. R:=High(DataSegments);
  4099. while L<=R do
  4100. begin
  4101. M:=(L+R) div 2;
  4102. if (DataSegments[M].DataSectionOffset+DataSegments[M].Len-1) < Ofs then
  4103. L:=M+1
  4104. else if DataSegments[M].DataSectionOffset > Ofs then
  4105. R:=M-1
  4106. else
  4107. begin
  4108. Result:=M;
  4109. exit;
  4110. end;
  4111. end;
  4112. Result:=-1;
  4113. end;
  4114. var
  4115. ModuleMagic: array [0..3] of Byte;
  4116. ModuleVersion: array [0..3] of Byte;
  4117. i, j, FirstCodeSegmentIdx, FirstDataSegmentIdx, SegI: Integer;
  4118. CurrSec, ObjSec: TObjSection;
  4119. BaseSectionOffset: UInt32;
  4120. ObjReloc: TWasmObjRelocation;
  4121. ds: TWasmCustomDebugSectionType;
  4122. begin
  4123. FReader:=AReader;
  4124. InputFileName:=AReader.FileName;
  4125. objdata:=CObjData.Create(InputFileName);
  4126. result:=false;
  4127. CodeSegments:=nil;
  4128. DataSegments:=nil;
  4129. SymbolTable:=nil;
  4130. RelocationTable:=nil;
  4131. SetLength(RelocationTable,2+(Ord(High(TWasmCustomDebugSectionType))-Ord(Low(TWasmCustomDebugSectionType))+1));
  4132. FuncTypes:=nil;
  4133. FuncTypeImportsCount:=0;
  4134. TableTypes:=nil;
  4135. TableTypeImportsCount:=0;
  4136. MemTypes:=nil;
  4137. MemTypeImportsCount:=0;
  4138. GlobalTypes:=nil;
  4139. GlobalTypeImportsCount:=0;
  4140. TagTypes:=nil;
  4141. TagTypeImportsCount:=0;
  4142. if not AReader.read(ModuleMagic,4) then
  4143. exit;
  4144. for i:=0 to 3 do
  4145. if ModuleMagic[i]<>WasmModuleMagic[i] then
  4146. exit;
  4147. if not AReader.read(ModuleVersion,4) then
  4148. exit;
  4149. for i:=0 to 3 do
  4150. if ModuleVersion[i]<>WasmVersion[i] then
  4151. exit;
  4152. while AReader.Pos<AReader.size do
  4153. if not ReadSection then
  4154. exit;
  4155. { fill the code segment names }
  4156. for i:=low(SymbolTable) to high(SymbolTable) do
  4157. with SymbolTable[i] do
  4158. if (SymKind=SYMTAB_FUNCTION) and ((SymFlags and WASM_SYM_UNDEFINED)=0) then
  4159. begin
  4160. if FuncTypes[SymIndex].IsImport then
  4161. begin
  4162. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_FUNCTION symbol, that is an import');
  4163. exit;
  4164. end;
  4165. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4166. begin
  4167. with CodeSegments[SymIndex-FuncTypeImportsCount] do
  4168. begin
  4169. SegName:='.text.n_'+SymName;
  4170. SegIsExported:=FuncTypes[SymIndex].IsExported;
  4171. end;
  4172. end;
  4173. end;
  4174. { create segments }
  4175. FirstCodeSegmentIdx:=ObjData.ObjSectionList.Count;
  4176. for i:=low(CodeSegments) to high(CodeSegments) do
  4177. with CodeSegments[i] do
  4178. begin
  4179. if SegName='' then
  4180. begin
  4181. InputError('Code section ' + tostr(i) + ' does not have a main symbol defined in the symbol table');
  4182. exit;
  4183. end;
  4184. if SegIsExported or not (cs_link_smart in current_settings.globalswitches) then
  4185. CurrSec:=ObjData.createsection(SegName,1,[oso_executable,oso_Data,oso_load,oso_keep],false)
  4186. else
  4187. CurrSec:=ObjData.createsection(SegName,1,[oso_executable,oso_Data,oso_load],false);
  4188. CurrSec.DataPos:=DataPos;
  4189. CurrSec.Size:=CodeSize;
  4190. end;
  4191. FirstDataSegmentIdx:=ObjData.ObjSectionList.Count;
  4192. for i:=low(DataSegments) to high(DataSegments) do
  4193. with DataSegments[i] do
  4194. if Active then
  4195. begin
  4196. if not (cs_link_smart in current_settings.globalswitches) then
  4197. CurrSec:=ObjData.createsection(SegName,1 shl SegAlignment,[oso_Data,oso_load,oso_write,oso_keep],false)
  4198. else
  4199. CurrSec:=ObjData.createsection(SegName,1 shl SegAlignment,[oso_Data,oso_load,oso_write],false);
  4200. CurrSec.DataPos:=DataPos;
  4201. CurrSec.MemPos:=Offset;
  4202. CurrSec.Size:=Len;
  4203. end;
  4204. ReadSectionContent(ObjData);
  4205. for i:=low(SymbolTable) to high(SymbolTable) do
  4206. with SymbolTable[i] do
  4207. case SymKind of
  4208. SYMTAB_DATA:
  4209. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4210. begin
  4211. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4212. objsym.bind:=AB_EXTERNAL;
  4213. if (SymFlags and WASM_SYM_TLS)<>0 then
  4214. begin
  4215. objsym.typ:=AT_TLS;
  4216. objsym.TlsGlobalSym:=TWasmObjSymbol(ObjData.CreateSymbol('GOT.mem.'+SymName));
  4217. objsym.TlsGlobalSym.TlsDataSym:=objsym;
  4218. objsym.TlsGlobalSym.bind:=AB_EXTERNAL;
  4219. objsym.TlsGlobalSym.typ:=AT_WASM_GLOBAL;
  4220. objsym.TlsGlobalSym.objsection:=nil;
  4221. objsym.TlsGlobalSym.offset:=0;
  4222. objsym.TlsGlobalSym.size:=1;
  4223. objsym.TlsGlobalSym.LinkingData.GlobalType:=wbt_i32;
  4224. objsym.TlsGlobalSym.LinkingData.GlobalIsMutable:=true;
  4225. end
  4226. else
  4227. objsym.typ:=AT_DATA;
  4228. objsym.objsection:=nil;
  4229. objsym.offset:=0;
  4230. objsym.size:=0;
  4231. end
  4232. else
  4233. begin
  4234. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4235. if (SymFlags and WASM_SYM_BINDING_LOCAL)<> 0 then
  4236. objsym.bind:=AB_LOCAL
  4237. else
  4238. objsym.bind:=AB_GLOBAL;
  4239. if (SymFlags and WASM_SYM_TLS)<>0 then
  4240. begin
  4241. objsym.typ:=AT_TLS;
  4242. objsym.TlsGlobalSym:=TWasmObjSymbol(ObjData.CreateSymbol('GOT.mem.'+SymName));
  4243. objsym.TlsGlobalSym.TlsDataSym:=objsym;
  4244. objsym.TlsGlobalSym.bind:=objsym.bind;
  4245. objsym.TlsGlobalSym.typ:=AT_WASM_GLOBAL;
  4246. objsym.TlsGlobalSym.objsection:=ObjData.createsection('.wasm_globals.n_'+objsym.TlsGlobalSym.Name,1,[oso_Data,oso_load],true);
  4247. if objsym.TlsGlobalSym.objsection.Size=0 then
  4248. objsym.TlsGlobalSym.objsection.WriteZeros(1);
  4249. TWasmObjSection(objsym.TlsGlobalSym.objsection).MainFuncSymbol:=objsym.TlsGlobalSym;
  4250. objsym.TlsGlobalSym.offset:=0;
  4251. objsym.TlsGlobalSym.size:=1;
  4252. objsym.TlsGlobalSym.LinkingData.GlobalType:=wbt_i32;
  4253. objsym.TlsGlobalSym.LinkingData.GlobalIsMutable:=true;
  4254. end
  4255. else
  4256. objsym.typ:=AT_DATA;
  4257. objsym.objsection:=TObjSection(ObjData.ObjSectionList[FirstDataSegmentIdx+SymIndex]);
  4258. objsym.offset:=SymOffset;
  4259. objsym.size:=SymSize;
  4260. end;
  4261. SYMTAB_FPC_CUSTOM:
  4262. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4263. begin
  4264. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4265. objsym.bind:=AB_EXTERNAL;
  4266. if (SymFlags and WASM_SYM_TLS)<>0 then
  4267. internalerror(2024080702);
  4268. objsym.typ:=AT_DATA;
  4269. objsym.objsection:=nil;
  4270. objsym.offset:=0;
  4271. objsym.size:=0;
  4272. end
  4273. else
  4274. begin
  4275. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4276. if (SymFlags and WASM_SYM_BINDING_LOCAL)<> 0 then
  4277. objsym.bind:=AB_LOCAL
  4278. else
  4279. objsym.bind:=AB_GLOBAL;
  4280. if (SymFlags and WASM_SYM_TLS)<>0 then
  4281. internalerror(2024080703);
  4282. objsym.typ:=AT_DATA;
  4283. objsym.objsection:=TObjSection(ObjData.ObjSectionList.Find(WasmCustomSectionName[SymCustomSectionType]));
  4284. objsym.offset:=SymOffset;
  4285. objsym.size:=SymSize;
  4286. end;
  4287. SYMTAB_FUNCTION:
  4288. begin
  4289. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4290. begin
  4291. if not FuncTypes[SymIndex].IsImport then
  4292. begin
  4293. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_FUNCTION symbol, that is not an import');
  4294. exit;
  4295. end;
  4296. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4297. begin
  4298. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4299. objsym.bind:=AB_EXTERNAL;
  4300. objsym.typ:=AT_FUNCTION;
  4301. objsym.objsection:=nil;
  4302. objsym.offset:=0;
  4303. objsym.size:=0;
  4304. objsym.LinkingData.ImportModule:=FuncTypes[SymIndex].ImportModName;
  4305. objsym.LinkingData.ImportName:=FuncTypes[SymIndex].ImportName;
  4306. end
  4307. else
  4308. begin
  4309. if FuncTypes[SymIndex].ImportModName = 'env' then
  4310. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(FuncTypes[SymIndex].ImportName))
  4311. else
  4312. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(FuncTypes[SymIndex].ImportModName + '.' + FuncTypes[SymIndex].ImportName));
  4313. objsym.bind:=AB_EXTERNAL;
  4314. objsym.typ:=AT_FUNCTION;
  4315. objsym.objsection:=nil;
  4316. objsym.offset:=0;
  4317. objsym.size:=0;
  4318. end;
  4319. end
  4320. else
  4321. begin
  4322. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4323. objsym.bind:=AB_GLOBAL;
  4324. objsym.typ:=AT_FUNCTION;
  4325. objsym.objsection:=TObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SymIndex-FuncTypeImportsCount]);
  4326. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4327. TWasmObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SymIndex-FuncTypeImportsCount]).MainFuncSymbol:=objsym;
  4328. objsym.offset:=0;
  4329. objsym.size:=objsym.objsection.Size;
  4330. end;
  4331. objsym.LinkingData.FuncType:=TWasmFuncType.Create(FFuncTypes[FuncTypes[SymIndex].typidx]);
  4332. objsym.LinkingData.IsExported:=FuncTypes[SymIndex].IsExported;
  4333. objsym.LinkingData.ExportName:=FuncTypes[SymIndex].ExportName;
  4334. end;
  4335. SYMTAB_GLOBAL:
  4336. begin
  4337. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4338. begin
  4339. if not GlobalTypes[SymIndex].IsImport then
  4340. begin
  4341. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_GLOBAL symbol, that is not an import');
  4342. exit;
  4343. end;
  4344. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4345. begin
  4346. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4347. objsym.bind:=AB_EXTERNAL;
  4348. objsym.typ:=AT_WASM_GLOBAL;
  4349. objsym.objsection:=nil;
  4350. objsym.offset:=0;
  4351. objsym.size:=1;
  4352. objsym.LinkingData.ImportModule:=GlobalTypes[SymIndex].ImportModName;
  4353. objsym.LinkingData.ImportName:=GlobalTypes[SymIndex].ImportName;
  4354. end
  4355. else
  4356. begin
  4357. if GlobalTypes[SymIndex].ImportModName = 'env' then
  4358. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportName))
  4359. else
  4360. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportModName + '.' + GlobalTypes[SymIndex].ImportName));
  4361. objsym.bind:=AB_EXTERNAL;
  4362. objsym.typ:=AT_WASM_GLOBAL;
  4363. objsym.objsection:=nil;
  4364. objsym.offset:=0;
  4365. objsym.size:=1;
  4366. end;
  4367. end
  4368. else
  4369. begin
  4370. if GlobalTypes[SymIndex].IsImport then
  4371. begin
  4372. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_GLOBAL symbol, that is an import');
  4373. exit;
  4374. end;
  4375. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4376. objsym.bind:=AB_GLOBAL;
  4377. objsym.typ:=AT_WASM_GLOBAL;
  4378. objsym.objsection:=ObjData.createsection('.wasm_globals.n_'+SymName,1,[oso_Data,oso_load],true);
  4379. if objsym.objsection.Size=0 then
  4380. objsym.objsection.WriteZeros(1);
  4381. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4382. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  4383. objsym.offset:=0;
  4384. objsym.size:=1;
  4385. objsym.LinkingData.GlobalInitializer:=GlobalTypes[SymIndex].GlobalInit;
  4386. end;
  4387. objsym.LinkingData.GlobalType:=GlobalTypes[SymIndex].valtype;
  4388. objsym.LinkingData.GlobalIsMutable:=GlobalTypes[SymIndex].IsMutable;
  4389. objsym.LinkingData.IsExported:=GlobalTypes[SymIndex].IsExported;
  4390. objsym.LinkingData.ExportName:=GlobalTypes[SymIndex].ExportName;
  4391. end;
  4392. SYMTAB_SECTION:
  4393. begin
  4394. for ds:=Low(DebugSectionIndex) to High(DebugSectionIndex) do
  4395. if DebugSectionIndex[ds]=TargetSection then
  4396. begin
  4397. ObjSec:=TWasmObjSection(ObjData.findsection(WasmCustomSectionName[ds]));
  4398. break;
  4399. end;
  4400. if ObjSec=nil then
  4401. begin
  4402. InputError('SYMTAB_SECTION entry points to an unsupported section');
  4403. exit;
  4404. end;
  4405. end;
  4406. SYMTAB_EVENT:
  4407. begin
  4408. if (SymFlags and WASM_SYM_UNDEFINED)<>0 then
  4409. begin
  4410. if not TagTypes[SymIndex].IsImport then
  4411. begin
  4412. InputError('WASM_SYM_UNDEFINED set on a SYMTAB_EVENT symbol, that is not an import');
  4413. exit;
  4414. end;
  4415. if (SymFlags and WASM_SYM_EXPLICIT_NAME)<>0 then
  4416. begin
  4417. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4418. objsym.bind:=AB_EXTERNAL;
  4419. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4420. objsym.objsection:=nil;
  4421. objsym.offset:=0;
  4422. objsym.size:=1;
  4423. objsym.LinkingData.ImportModule:=TagTypes[SymIndex].ImportModName;
  4424. objsym.LinkingData.ImportName:=TagTypes[SymIndex].ImportName;
  4425. end
  4426. else
  4427. begin
  4428. if GlobalTypes[SymIndex].ImportModName = 'env' then
  4429. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportName))
  4430. else
  4431. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(GlobalTypes[SymIndex].ImportModName + '.' + GlobalTypes[SymIndex].ImportName));
  4432. objsym.bind:=AB_EXTERNAL;
  4433. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4434. objsym.objsection:=nil;
  4435. objsym.offset:=0;
  4436. objsym.size:=1;
  4437. end;
  4438. end
  4439. else
  4440. begin
  4441. if TagTypes[SymIndex].IsImport then
  4442. begin
  4443. InputError('WASM_SYM_UNDEFINED not set on a SYMTAB_EVENT symbol, that is an import');
  4444. exit;
  4445. end;
  4446. objsym:=TWasmObjSymbol(ObjData.CreateSymbol(SymName));
  4447. if (symflags and WASM_SYM_BINDING_WEAK) <> 0 then
  4448. objsym.bind:=AB_WEAK_EXTERNAL
  4449. else if (symflags and WASM_SYM_BINDING_LOCAL) <> 0 then
  4450. objsym.bind:=AB_LOCAL
  4451. else
  4452. objsym.bind:=AB_GLOBAL;
  4453. objsym.typ:=AT_WASM_EXCEPTION_TAG;
  4454. objsym.objsection:=ObjData.createsection('.wasm_tags.n_'+SymName,1,[oso_Data,oso_load],true);
  4455. if objsym.objsection.Size=0 then
  4456. objsym.objsection.WriteZeros(1);
  4457. if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
  4458. TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
  4459. objsym.offset:=0;
  4460. objsym.size:=1;
  4461. end;
  4462. objsym.LinkingData.FuncType:=TWasmFuncType.Create(FFuncTypes[TagTypes[SymIndex].TagTypeIdx]);
  4463. objsym.LinkingData.IsExported:=TagTypes[SymIndex].IsExported;
  4464. objsym.LinkingData.ExportName:=TagTypes[SymIndex].ExportName;
  4465. end;
  4466. SYMTAB_TABLE:
  4467. {TODO};
  4468. end;
  4469. for j:=0 to high(RelocationTable) do
  4470. for i:=0 to high(RelocationTable[j]) do
  4471. with RelocationTable[j,i] do
  4472. begin
  4473. case j of
  4474. 0:
  4475. begin
  4476. SegI:=FindCodeSegment(RelocOffset);
  4477. if SegI=-1 then
  4478. begin
  4479. InputError('Relocation offset not found in code segment');
  4480. Exit;
  4481. end;
  4482. BaseSectionOffset:=CodeSegments[SegI].CodeSectionOffset;
  4483. ObjSec:=TObjSection(ObjData.ObjSectionList[FirstCodeSegmentIdx+SegI]);
  4484. end;
  4485. 1:
  4486. begin
  4487. SegI:=FindDataSegment(RelocOffset);
  4488. if SegI=-1 then
  4489. begin
  4490. InputError('Relocation offset not found in data segment');
  4491. Exit;
  4492. end;
  4493. BaseSectionOffset:=DataSegments[SegI].DataSectionOffset;
  4494. ObjSec:=TObjSection(ObjData.ObjSectionList[FirstDataSegmentIdx+SegI]);
  4495. end;
  4496. 2..2+(Ord(High(TWasmCustomDebugSectionType))-Ord(Low(TWasmCustomDebugSectionType))):
  4497. begin
  4498. BaseSectionOffset:=0;
  4499. ObjSec:=ObjData.findsection(WasmCustomSectionName[TWasmCustomSectionType((j-2)+Ord(Low(TWasmCustomDebugSectionType)))]);
  4500. end;
  4501. else
  4502. internalerror(2023122801);
  4503. end;
  4504. case RelocType of
  4505. R_WASM_FUNCTION_INDEX_LEB:
  4506. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_FUNCTION_INDEX_LEB));
  4507. R_WASM_TABLE_INDEX_SLEB:
  4508. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB));
  4509. R_WASM_TABLE_INDEX_I32:
  4510. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE));
  4511. R_WASM_MEMORY_ADDR_LEB:
  4512. begin
  4513. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_LEB);
  4514. ObjReloc.Addend:=RelocAddend;
  4515. ObjSec.ObjRelocations.Add(ObjReloc);
  4516. end;
  4517. R_WASM_MEMORY_ADDR_SLEB:
  4518. begin
  4519. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB);
  4520. ObjReloc.Addend:=RelocAddend;
  4521. ObjSec.ObjRelocations.Add(ObjReloc);
  4522. end;
  4523. R_WASM_MEMORY_ADDR_I32:
  4524. begin
  4525. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE);
  4526. ObjReloc.Addend:=RelocAddend;
  4527. ObjSec.ObjRelocations.Add(ObjReloc);
  4528. end;
  4529. R_WASM_TYPE_INDEX_LEB:
  4530. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateFuncType(RelocOffset-BaseSectionOffset,FFuncTypes[RelocIndex]));
  4531. R_WASM_FUNCTION_OFFSET_I32:
  4532. begin
  4533. ObjReloc:=TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE);
  4534. ObjReloc.Addend:=RelocAddend;
  4535. ObjReloc.IsFunctionOffsetI32:=True;
  4536. ObjSec.ObjRelocations.Add(ObjReloc);
  4537. end;
  4538. R_WASM_SECTION_OFFSET_I32:
  4539. begin
  4540. ObjReloc:=TWasmObjRelocation.CreateSection(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSec,RELOC_ABSOLUTE);
  4541. ObjReloc.Addend:=RelocAddend;
  4542. ObjSec.ObjRelocations.Add(ObjReloc);
  4543. end;
  4544. R_WASM_GLOBAL_INDEX_LEB:
  4545. begin
  4546. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_GLOBAL_INDEX_LEB));
  4547. if Assigned(SymbolTable[RelocIndex].ObjSym.TlsGlobalSym) then
  4548. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym.TlsGlobalSym,RELOC_GLOBAL_INDEX_LEB));
  4549. end;
  4550. R_WASM_GLOBAL_INDEX_I32:
  4551. begin
  4552. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_ABSOLUTE));
  4553. if Assigned(SymbolTable[RelocIndex].ObjSym.TlsGlobalSym) then
  4554. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym.TlsGlobalSym,RELOC_ABSOLUTE));
  4555. end;
  4556. R_WASM_TAG_INDEX_LEB:
  4557. ObjSec.ObjRelocations.Add(TWasmObjRelocation.CreateSymbol(RelocOffset-BaseSectionOffset,SymbolTable[RelocIndex].ObjSym,RELOC_TAG_INDEX_LEB));
  4558. else
  4559. internalerror(2023122802);
  4560. end;
  4561. end;
  4562. Result:=True;
  4563. end;
  4564. {****************************************************************************
  4565. TWasmExeOutput
  4566. ****************************************************************************}
  4567. procedure TWasmExeOutput.AddToNameMap(var nm: TCustomSectionNameMap; aidx: UInt32; const aname: string);
  4568. begin
  4569. SetLength(nm,Length(nm)+1);
  4570. with nm[High(nm)] do
  4571. begin
  4572. idx:=aidx;
  4573. name:=aname;
  4574. end;
  4575. end;
  4576. procedure TWasmExeOutput.AddToFunctionNameMap(aidx: UInt32; const aname: string);
  4577. begin
  4578. AddToNameMap(FFunctionNameMap,aidx,aname);
  4579. end;
  4580. procedure TWasmExeOutput.AddToGlobalNameMap(aidx: UInt32; const aname: string);
  4581. begin
  4582. AddToNameMap(FGlobalNameMap,aidx,aname);
  4583. end;
  4584. procedure TWasmExeOutput.AddToDataNameMap(aidx: UInt32; const aname: string);
  4585. begin
  4586. AddToNameMap(FDataNameMap,aidx,aname);
  4587. end;
  4588. procedure TWasmExeOutput.AddToTagNameMap(aidx: UInt32; const aname: string);
  4589. begin
  4590. AddToNameMap(FTagNameMap,aidx,aname);
  4591. end;
  4592. procedure TWasmExeOutput.WriteWasmSection(wsid: TWasmSectionID);
  4593. var
  4594. b: byte;
  4595. begin
  4596. b:=ord(wsid);
  4597. Writer.write(b,1);
  4598. WriteUleb(Writer,FWasmSections[wsid].size);
  4599. Writer.writearray(FWasmSections[wsid]);
  4600. end;
  4601. procedure TWasmExeOutput.WriteWasmSectionIfNotEmpty(wsid: TWasmSectionID);
  4602. begin
  4603. if FWasmSections[wsid].size>0 then
  4604. WriteWasmSection(wsid);
  4605. end;
  4606. procedure TWasmExeOutput.WriteWasmCustomSection(wcst: TWasmCustomSectionType);
  4607. var
  4608. b: byte;
  4609. begin
  4610. b:=0;
  4611. Writer.write(b,1);
  4612. WriteUleb(Writer,FWasmCustomSections[wcst].size);
  4613. Writer.writearray(FWasmCustomSections[wcst]);
  4614. end;
  4615. function TWasmExeOutput.writeData: boolean;
  4616. procedure WriteImportSection;
  4617. var
  4618. imports_count,
  4619. i: Integer;
  4620. begin
  4621. if assigned(exemap) then
  4622. exemap.AddHeader('Import section');
  4623. imports_count:=Length(FImportedMemories)+Length(FFunctionImports);
  4624. WriteUleb(FWasmSections[wsiImport],imports_count);
  4625. for i:=0 to Length(FImportedMemories)-1 do
  4626. with FImportedMemories[i] do
  4627. begin
  4628. WriteName(FWasmSections[wsiImport],ModName);
  4629. WriteName(FWasmSections[wsiImport],Name);
  4630. WriteByte(FWasmSections[wsiImport],$02); { mem }
  4631. WriteMemoryTo(FWasmSections[wsiImport],MemType);
  4632. if assigned(exemap) then
  4633. exemap.Add(' Memory['+tostr(i)+'] '+Memory2String(MemType)+' <- '+ModName+'.'+Name);
  4634. end;
  4635. for i:=0 to Length(FFunctionImports)-1 do
  4636. with FFunctionImports[i] do
  4637. begin
  4638. WriteName(FWasmSections[wsiImport],ModName);
  4639. WriteName(FWasmSections[wsiImport],Name);
  4640. WriteByte(FWasmSections[wsiImport],$00); { func }
  4641. WriteUleb(FWasmSections[wsiImport],TypeIdx);
  4642. if assigned(exemap) then
  4643. exemap.Add(' Function['+tostr(i)+'] sig='+tostr(TypeIdx)+' <- '+ModName+'.'+Name);
  4644. end;
  4645. end;
  4646. procedure WriteCodeSegments;
  4647. var
  4648. i: Integer;
  4649. exesec: TExeSection;
  4650. objsec: TWasmObjSection;
  4651. begin
  4652. exesec:=FindExeSection('.text');
  4653. if not assigned(exesec) then
  4654. internalerror(2023123102);
  4655. if not (oso_Data in exesec.SecOptions) then
  4656. internalerror(2023123103);
  4657. WriteUleb(FWasmSections[wsiFunction],exesec.ObjSectionList.Count);
  4658. WriteUleb(FWasmSections[wsiCode],exesec.ObjSectionList.Count);
  4659. for i:=0 to exesec.ObjSectionList.Count-1 do
  4660. begin
  4661. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4662. if not (oso_data in objsec.secoptions) then
  4663. internalerror(2023123104);
  4664. if not assigned(objsec.data) then
  4665. internalerror(2023123105);
  4666. if objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex<>(i+Length(FFunctionImports)) then
  4667. internalerror(2024010101);
  4668. WriteUleb(FWasmSections[wsiFunction],objsec.MainFuncSymbol.LinkingData.ExeTypeIndex);
  4669. WriteUleb(FWasmSections[wsiCode],objsec.Data.size);
  4670. objsec.Data.seek(0);
  4671. CopyDynamicArray(objsec.Data,FWasmSections[wsiCode],objsec.Data.size);
  4672. end;
  4673. end;
  4674. procedure WriteDataSegments;
  4675. procedure WriteExeSection(exesec: TExeSection);
  4676. var
  4677. i: Integer;
  4678. objsec: TObjSection;
  4679. exesecdatapos: LongWord;
  4680. dpos, pad: QWord;
  4681. begin
  4682. AddToDataNameMap(Length(FDataNameMap),exesec.Name);
  4683. if ts_wasm_threads in current_settings.targetswitches then
  4684. WriteByte(FWasmSections[wsiData],1) { mode passive }
  4685. else
  4686. begin
  4687. WriteByte(FWasmSections[wsiData],0); { mode active, memory 0, offset e }
  4688. WriteByte(FWasmSections[wsiData],$41); { i32.const }
  4689. WriteSleb(FWasmSections[wsiData],longint(exesec.MemPos));
  4690. WriteByte(FWasmSections[wsiData],$0B); { end }
  4691. end;
  4692. WriteUleb(FWasmSections[wsiData],exesec.Size);
  4693. exesecdatapos:=FWasmSections[wsiData].size;
  4694. for i:=0 to exesec.ObjSectionList.Count-1 do
  4695. begin
  4696. objsec:=TObjSection(exesec.ObjSectionList[i]);
  4697. if not (oso_data in objsec.secoptions) then
  4698. internalerror(2024010104);
  4699. if not assigned(objsec.data) then
  4700. internalerror(2024010105);
  4701. dpos:=objsec.MemPos-exesec.MemPos+exesecdatapos;
  4702. pad:=dpos-FWasmSections[wsiData].size;
  4703. { objsection must be within SecAlign bytes from the previous one }
  4704. if (dpos<FWasmSections[wsiData].Size) or
  4705. (pad>=max(objsec.SecAlign,1)) then
  4706. internalerror(2024010106);
  4707. writeZeros(FWasmSections[wsiData],pad);
  4708. objsec.data.seek(0);
  4709. CopyDynamicArray(objsec.data,FWasmSections[wsiData],objsec.data.size);
  4710. end;
  4711. if (FWasmSections[wsiData].size-exesecdatapos)<>exesec.Size then
  4712. internalerror(2024010107);
  4713. end;
  4714. var
  4715. DataCount: Integer;
  4716. DataSecName: string;
  4717. ExeSec: TExeSection;
  4718. begin
  4719. DataCount:=0;
  4720. for DataSecName in DataSections do
  4721. begin
  4722. ExeSec:=FindExeSection(DataSecName);
  4723. if Assigned(ExeSec) and (ExeSec.Size>0) then
  4724. Inc(DataCount);
  4725. end;
  4726. WriteUleb(FWasmSections[wsiDataCount],DataCount);
  4727. WriteUleb(FWasmSections[wsiData],DataCount);
  4728. for DataSecName in DataSections do
  4729. begin
  4730. ExeSec:=FindExeSection(DataSecName);
  4731. if Assigned(ExeSec) and (ExeSec.Size>0) then
  4732. WriteExeSection(ExeSec);
  4733. end;
  4734. end;
  4735. procedure WriteTableAndElemSections;
  4736. const
  4737. TableCount=1;
  4738. var
  4739. i: Integer;
  4740. begin
  4741. { Table section }
  4742. WriteUleb(FWasmSections[wsiTable],TableCount);
  4743. { table 0 }
  4744. { table type }
  4745. WriteByte(FWasmSections[wsiTable],encode_wasm_basic_type(wbt_funcref));
  4746. { table limits }
  4747. WriteByte(FWasmSections[wsiTable],$01); { has min & max }
  4748. WriteUleb(FWasmSections[wsiTable],Length(FIndirectFunctionTable)); { min }
  4749. WriteUleb(FWasmSections[wsiTable],Length(FIndirectFunctionTable)); { max }
  4750. { Elem section }
  4751. WriteUleb(FWasmSections[wsiElement],1); { 1 element segment }
  4752. { element segment 0 }
  4753. WriteByte(FWasmSections[wsiElement],0); { type funcref, init((ref.func y) end)*, mode active <table 0, offset e> }
  4754. { e:expr }
  4755. WriteByte(FWasmSections[wsiElement],$41); { i32.const }
  4756. WriteSleb(FWasmSections[wsiElement],1); { starting from 1 (table entry 0 is ref.null) }
  4757. WriteByte(FWasmSections[wsiElement],$0B); { end }
  4758. { y*:vec(funcidx) }
  4759. WriteUleb(FWasmSections[wsiElement],Length(FIndirectFunctionTable)-1);
  4760. for i:=1 to Length(FIndirectFunctionTable)-1 do
  4761. WriteUleb(FWasmSections[wsiElement],FIndirectFunctionTable[i].FuncIdx);
  4762. end;
  4763. procedure WriteGlobalSection;
  4764. var
  4765. exesec: TExeSection;
  4766. globals_count, i: Integer;
  4767. objsec: TWasmObjSection;
  4768. mapstr: string='';
  4769. begin
  4770. if assigned(exemap) then
  4771. exemap.AddHeader('Global section');
  4772. exesec:=FindExeSection('.wasm_globals');
  4773. if not assigned(exesec) then
  4774. internalerror(2024010112);
  4775. globals_count:=exesec.ObjSectionList.Count;
  4776. if globals_count<>exesec.Size then
  4777. internalerror(2024010113);
  4778. WriteUleb(FWasmSections[wsiGlobal],globals_count);
  4779. for i:=0 to exesec.ObjSectionList.Count-1 do
  4780. begin
  4781. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4782. WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(objsec.MainFuncSymbol.LinkingData.GlobalType));
  4783. if objsec.MainFuncSymbol.LinkingData.GlobalIsMutable then
  4784. WriteByte(FWasmSections[wsiGlobal],1)
  4785. else
  4786. WriteByte(FWasmSections[wsiGlobal],0);
  4787. if assigned(exemap) then
  4788. WriteStr(mapstr,' Global[',i,'] ',wasm_basic_type_str[objsec.MainFuncSymbol.LinkingData.GlobalType],' mutable=',objsec.MainFuncSymbol.LinkingData.GlobalIsMutable,' <',objsec.MainFuncSymbol.Name,'> - init ');
  4789. { initializer expr }
  4790. with objsec.MainFuncSymbol.LinkingData.GlobalInitializer do
  4791. case typ of
  4792. wbt_i32:
  4793. begin
  4794. WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
  4795. WriteSleb(FWasmSections[wsiGlobal],init_i32);
  4796. if assigned(exemap) then
  4797. mapstr:=mapstr+'i32='+tostr(init_i32);
  4798. end;
  4799. wbt_i64:
  4800. begin
  4801. WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
  4802. WriteSleb(FWasmSections[wsiGlobal],init_i64);
  4803. if assigned(exemap) then
  4804. mapstr:=mapstr+'i64='+tostr(init_i64);
  4805. end;
  4806. wbt_f32:
  4807. begin
  4808. WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
  4809. WriteF32LE(FWasmSections[wsiGlobal],init_f32);
  4810. if assigned(exemap) then
  4811. WriteStr(mapstr,mapstr+'f32=',init_f32);
  4812. end;
  4813. wbt_f64:
  4814. begin
  4815. WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
  4816. WriteF64LE(FWasmSections[wsiGlobal],init_f64);
  4817. if assigned(exemap) then
  4818. WriteStr(mapstr,mapstr+'f64=',init_f64);
  4819. end;
  4820. wbt_funcref,
  4821. wbt_externref:
  4822. begin
  4823. WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null }
  4824. WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(typ));
  4825. if assigned(exemap) then
  4826. mapstr:=mapstr+'ref.null '+wasm_basic_type_str[typ];
  4827. end;
  4828. else
  4829. internalerror(2024010114);
  4830. end;
  4831. WriteByte(FWasmSections[wsiGlobal],$0B); { end }
  4832. { add entry for the name section }
  4833. AddToGlobalNameMap(i,objsec.MainFuncSymbol.Name);
  4834. if assigned(exemap) then
  4835. exemap.Add(mapstr);
  4836. end;
  4837. end;
  4838. procedure WriteTagSection;
  4839. var
  4840. exesec: TExeSection;
  4841. tags_count, i: Integer;
  4842. objsec: TWasmObjSection;
  4843. begin
  4844. exesec:=FindExeSection('.wasm_tags');
  4845. if not assigned(exesec) then
  4846. exit;
  4847. tags_count:=exesec.ObjSectionList.Count;
  4848. if tags_count<>exesec.Size then
  4849. internalerror(2024010702);
  4850. if tags_count=0 then
  4851. exit;
  4852. WriteUleb(FWasmSections[wsiTag],tags_count);
  4853. for i:=0 to exesec.ObjSectionList.Count-1 do
  4854. begin
  4855. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  4856. WriteByte(FWasmSections[wsiTag],0);
  4857. WriteUleb(FWasmSections[wsiTag],objsec.MainFuncSymbol.LinkingData.ExeTypeIndex);
  4858. AddToTagNameMap(i,objsec.MainFuncSymbol.Name);
  4859. end;
  4860. end;
  4861. procedure WriteExportSection;
  4862. const
  4863. MemoryExportsCount=1;
  4864. var
  4865. FunctionExportsCount: Integer;
  4866. ExportsCount: Integer;
  4867. textsec: TExeSection;
  4868. i: Integer;
  4869. objsec: TWasmObjSection;
  4870. begin
  4871. if assigned(exemap) then
  4872. exemap.AddHeader('Export section');
  4873. FunctionExportsCount:=0;
  4874. textsec:=FindExeSection('.text');
  4875. if not assigned(textsec) then
  4876. internalerror(2024010115);
  4877. for i:=0 to textsec.ObjSectionList.Count-1 do
  4878. begin
  4879. objsec:=TWasmObjSection(textsec.ObjSectionList[i]);
  4880. if objsec.MainFuncSymbol.LinkingData.IsExported then
  4881. Inc(FunctionExportsCount)
  4882. end;
  4883. ExportsCount:=MemoryExportsCount+FunctionExportsCount;
  4884. WriteUleb(FWasmSections[wsiExport],ExportsCount);
  4885. { export 0 }
  4886. WriteName(FWasmSections[wsiExport],'memory');
  4887. WriteByte(FWasmSections[wsiExport],$02); { mem }
  4888. WriteUleb(FWasmSections[wsiExport],0); { memidx = 0 }
  4889. if assigned(exemap) then
  4890. exemap.Add(' Memory[0] -> "memory"');
  4891. for i:=0 to textsec.ObjSectionList.Count-1 do
  4892. begin
  4893. objsec:=TWasmObjSection(textsec.ObjSectionList[i]);
  4894. if objsec.MainFuncSymbol.LinkingData.IsExported then
  4895. begin
  4896. WriteName(FWasmSections[wsiExport],objsec.MainFuncSymbol.LinkingData.ExportName);
  4897. WriteByte(FWasmSections[wsiExport],$00); { func }
  4898. WriteUleb(FWasmSections[wsiExport],objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex); { funcidx }
  4899. if assigned(exemap) then
  4900. exemap.Add(' Function['+tostr(objsec.MainFuncSymbol.LinkingData.ExeFunctionIndex)+'] -> "'+objsec.MainFuncSymbol.LinkingData.ExportName+'"');
  4901. end;
  4902. end;
  4903. end;
  4904. procedure MaybeWriteDebugSection(st: TWasmCustomDebugSectionType);
  4905. var
  4906. exesec: TExeSection;
  4907. begin
  4908. exesec:=FindExeSection(WasmCustomSectionName[st]);
  4909. if assigned(exesec) then
  4910. begin
  4911. WriteExeSectionToDynArray(exesec,FWasmCustomSections[st]);
  4912. WriteWasmCustomSection(st);
  4913. end;
  4914. end;
  4915. procedure WriteNameMap(const nm: TCustomSectionNameMap; dest: tdynamicarray);
  4916. var
  4917. i: Integer;
  4918. begin
  4919. WriteUleb(dest,Length(nm));
  4920. for i:=low(nm) to high(nm) do
  4921. with nm[i] do
  4922. begin
  4923. WriteUleb(dest,idx);
  4924. WriteName(dest,name);
  4925. end;
  4926. end;
  4927. procedure WriteNameSubsection(wnst: TWasmNameSubsectionType);
  4928. begin
  4929. if FWasmNameSubsections[wnst].size>0 then
  4930. begin
  4931. WriteByte(FWasmCustomSections[wcstName],Ord(wnst));
  4932. WriteUleb(FWasmCustomSections[wcstName],FWasmNameSubsections[wnst].size);
  4933. FWasmNameSubsections[wnst].seek(0);
  4934. CopyDynamicArray(FWasmNameSubsections[wnst],FWasmCustomSections[wcstName],FWasmNameSubsections[wnst].size);
  4935. end;
  4936. end;
  4937. procedure WriteNameSection;
  4938. begin
  4939. WriteName(FWasmNameSubsections[wnstModuleName],current_module.exefilename);
  4940. WriteNameSubsection(wnstModuleName);
  4941. WriteNameMap(FFunctionNameMap,FWasmNameSubsections[wnstFunctionNames]);
  4942. WriteNameSubsection(wnstFunctionNames);
  4943. WriteNameMap(FGlobalNameMap,FWasmNameSubsections[wnstGlobalNames]);
  4944. WriteNameSubsection(wnstGlobalNames);
  4945. WriteNameMap(FDataNameMap,FWasmNameSubsections[wnstDataNames]);
  4946. WriteNameSubsection(wnstDataNames);
  4947. if Length(FTagNameMap)>0 then
  4948. begin
  4949. WriteNameMap(FTagNameMap,FWasmNameSubsections[wnstTagNames]);
  4950. WriteNameSubsection(wnstTagNames);
  4951. end;
  4952. end;
  4953. procedure WriteMemorySection;
  4954. var
  4955. i: Integer;
  4956. begin
  4957. if assigned(exemap) then
  4958. exemap.AddHeader('Memory section');
  4959. WriteUleb(FWasmSections[wsiMemory],Length(FMemories));
  4960. for i:=low(FMemories) to high(FMemories) do
  4961. begin
  4962. WriteMemoryTo(FWasmSections[wsiMemory],FMemories[i]);
  4963. if assigned(exemap) then
  4964. exemap.Add(' Memory['+tostr(i+Length(FImportedMemories))+'] '+Memory2String(FMemories[i]));
  4965. end;
  4966. end;
  4967. var
  4968. cust_sec: TWasmCustomSectionType;
  4969. begin
  4970. result:=false;
  4971. FMaxMemoryPages:=align(maxheapsize,WasmPageSize) div WasmPageSize;
  4972. { each custom sections starts with its name }
  4973. for cust_sec in TWasmCustomSectionType do
  4974. WriteName(FWasmCustomSections[cust_sec],WasmCustomSectionName[cust_sec]);
  4975. SetStackPointer;
  4976. SetTlsSizeAlignAndBase;
  4977. SetThreadVarGlobalsInitValues;
  4978. GenerateCode_InitTls;
  4979. GenerateCode_InitSharedMemory;
  4980. if ts_wasm_threads in current_settings.targetswitches then
  4981. begin
  4982. SetLength(FImportedMemories,1);
  4983. with FImportedMemories[0] do
  4984. begin
  4985. ModName:='env';
  4986. Name:='memory';
  4987. with MemType do
  4988. begin
  4989. Flags:=[wmfShared,wmfHasMaximumBound];
  4990. MinPages:=FMinMemoryPages;
  4991. MaxPages:=Max(FMinMemoryPages,FMaxMemoryPages);
  4992. end;
  4993. end;
  4994. end
  4995. else
  4996. begin
  4997. SetLength(FMemories,1);
  4998. with FMemories[0] do
  4999. begin
  5000. Flags:=[];
  5001. MinPages:=FMinMemoryPages;
  5002. if FMaxMemoryPages>=FMinMemoryPages then
  5003. begin
  5004. Include(Flags,wmfHasMaximumBound);
  5005. MaxPages:=FMaxMemoryPages;
  5006. end;
  5007. end;
  5008. end;
  5009. FFuncTypes.WriteTo(FWasmSections[wsiType]);
  5010. WriteImportSection;
  5011. WriteCodeSegments;
  5012. WriteDataSegments;
  5013. WriteTableAndElemSections;
  5014. WriteGlobalSection;
  5015. WriteTagSection;
  5016. if Length(FMemories)>0 then
  5017. WriteMemorySection;
  5018. WriteExportSection;
  5019. if ts_wasm_threads in current_settings.targetswitches then
  5020. WriteUleb(FWasmSections[wsiStart],FInitSharedMemoryFunctionSym.LinkingData.ExeFunctionIndex);
  5021. WriteNameSection;
  5022. Writer.write(WasmModuleMagic,SizeOf(WasmModuleMagic));
  5023. Writer.write(WasmVersion,SizeOf(WasmVersion));
  5024. WriteWasmSection(wsiType);
  5025. WriteWasmSection(wsiImport);
  5026. WriteWasmSection(wsiFunction);
  5027. WriteWasmSection(wsiTable);
  5028. if not (ts_wasm_threads in current_settings.targetswitches) then
  5029. WriteWasmSection(wsiMemory);
  5030. WriteWasmSectionIfNotEmpty(wsiTag);
  5031. WriteWasmSection(wsiGlobal);
  5032. WriteWasmSection(wsiExport);
  5033. if ts_wasm_threads in current_settings.targetswitches then
  5034. WriteWasmSection(wsiStart);
  5035. WriteWasmSection(wsiElement);
  5036. WriteWasmSection(wsiDataCount);
  5037. WriteWasmSection(wsiCode);
  5038. WriteWasmSection(wsiData);
  5039. MaybeWriteDebugSection(wcstDebugAbbrev);
  5040. MaybeWriteDebugSection(wcstDebugInfo);
  5041. MaybeWriteDebugSection(wcstDebugStr);
  5042. MaybeWriteDebugSection(wcstDebugLine);
  5043. MaybeWriteDebugSection(wcstDebugFrame);
  5044. MaybeWriteDebugSection(wcstDebugAranges);
  5045. MaybeWriteDebugSection(wcstDebugRanges);
  5046. WriteWasmCustomSection(wcstName);
  5047. result := true;
  5048. end;
  5049. procedure TWasmExeOutput.DoRelocationFixup(objsec: TObjSection);
  5050. procedure writeUInt32LE(v: uint32);
  5051. begin
  5052. {$ifdef FPC_BIG_ENDIAN}
  5053. v:=SwapEndian(v);
  5054. {$endif FPC_BIG_ENDIAN}
  5055. objsec.data.write(v,4);
  5056. end;
  5057. var
  5058. i: Integer;
  5059. objreloc: TWasmObjRelocation;
  5060. objsym: TWasmObjSymbol;
  5061. begin
  5062. for i:=0 to objsec.ObjRelocations.Count-1 do
  5063. begin
  5064. objreloc:=TWasmObjRelocation(objsec.ObjRelocations[i]);
  5065. if assigned(objreloc.symbol) then
  5066. begin
  5067. objsym:=TWasmObjSymbol(objreloc.symbol);
  5068. case objreloc.typ of
  5069. RELOC_FUNCTION_INDEX_LEB:
  5070. begin
  5071. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5072. internalerror(2024010103);
  5073. if FRelocationPass=2 then
  5074. begin
  5075. objsec.Data.seek(objreloc.DataOffset);
  5076. WriteUleb5(objsec.Data,objsym.LinkingData.ExeFunctionIndex);
  5077. end;
  5078. end;
  5079. RELOC_ABSOLUTE:
  5080. begin
  5081. case objsym.typ of
  5082. AT_FUNCTION:
  5083. begin
  5084. if objreloc.IsFunctionOffsetI32 then
  5085. begin
  5086. { R_WASM_FUNCTION_OFFSET_I32 }
  5087. if FRelocationPass=2 then
  5088. begin
  5089. objsec.Data.seek(objreloc.DataOffset);
  5090. writeUInt32LE(UInt32(objsym.objsection.MemPos+objreloc.Addend));
  5091. end;
  5092. end
  5093. else
  5094. begin
  5095. { R_WASM_TABLE_INDEX_I32 }
  5096. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5097. internalerror(2024010103);
  5098. case FRelocationPass of
  5099. 1:
  5100. if objsym.LinkingData.ExeIndirectFunctionTableIndex=-1 then
  5101. objsym.LinkingData.ExeIndirectFunctionTableIndex:=AddOrGetIndirectFunctionTableIndex(objsym.LinkingData.ExeFunctionIndex);
  5102. 2:
  5103. begin
  5104. objsec.Data.seek(objreloc.DataOffset);
  5105. writeUInt32LE(UInt32(objsym.LinkingData.ExeIndirectFunctionTableIndex));
  5106. end;
  5107. end;
  5108. end;
  5109. end;
  5110. AT_DATA:
  5111. begin
  5112. if objreloc.IsFunctionOffsetI32 then
  5113. internalerror(2024010602);
  5114. if FRelocationPass=2 then
  5115. begin
  5116. objsec.Data.seek(objreloc.DataOffset);
  5117. writeUInt32LE(UInt32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5118. end;
  5119. end;
  5120. AT_TLS:
  5121. begin
  5122. if objreloc.IsFunctionOffsetI32 then
  5123. internalerror(2024010602);
  5124. if FRelocationPass=2 then
  5125. begin
  5126. objsec.Data.seek(objreloc.DataOffset);
  5127. writeUInt32LE(UInt32((objsym.offset+objsym.objsection.MemPos-objsym.objsection.ExeSection.MemPos)+objreloc.Addend));
  5128. end;
  5129. end;
  5130. AT_WASM_GLOBAL:
  5131. begin
  5132. if objreloc.IsFunctionOffsetI32 then
  5133. internalerror(2024010602);
  5134. if FRelocationPass=2 then
  5135. begin
  5136. objsec.Data.seek(objreloc.DataOffset);
  5137. writeUInt32LE(UInt32(objsym.offset+objsym.objsection.MemPos));
  5138. end;
  5139. end;
  5140. else
  5141. internalerror(2024010108);
  5142. end;
  5143. end;
  5144. RELOC_MEMORY_ADDR_LEB:
  5145. begin
  5146. if objsym.typ<>AT_DATA then
  5147. internalerror(2024010109);
  5148. if FRelocationPass=2 then
  5149. begin
  5150. objsec.Data.seek(objreloc.DataOffset);
  5151. WriteUleb5(objsec.Data,UInt32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5152. end;
  5153. end;
  5154. RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB:
  5155. begin
  5156. case objsym.typ of
  5157. AT_FUNCTION:
  5158. begin
  5159. if objsym.LinkingData.ExeFunctionIndex=-1 then
  5160. internalerror(2024010103);
  5161. case FRelocationPass of
  5162. 1:
  5163. if objsym.LinkingData.ExeIndirectFunctionTableIndex=-1 then
  5164. objsym.LinkingData.ExeIndirectFunctionTableIndex:=AddOrGetIndirectFunctionTableIndex(objsym.LinkingData.ExeFunctionIndex);
  5165. 2:
  5166. begin
  5167. objsec.Data.seek(objreloc.DataOffset);
  5168. WriteSleb5(objsec.Data,Int32(objsym.LinkingData.ExeIndirectFunctionTableIndex));
  5169. end;
  5170. end;
  5171. end;
  5172. AT_DATA:
  5173. begin
  5174. if FRelocationPass=2 then
  5175. begin
  5176. objsec.Data.seek(objreloc.DataOffset);
  5177. WriteSleb5(objsec.Data,Int32((objsym.offset+objsym.objsection.MemPos)+objreloc.Addend));
  5178. end;
  5179. end;
  5180. else
  5181. internalerror(2024010110);
  5182. end;
  5183. end;
  5184. RELOC_GLOBAL_INDEX_LEB:
  5185. if objsym.typ=AT_WASM_GLOBAL then
  5186. begin
  5187. if FRelocationPass=2 then
  5188. begin
  5189. objsec.Data.seek(objreloc.DataOffset);
  5190. WriteUleb5(objsec.Data,UInt32(objsym.offset+objsym.objsection.MemPos));
  5191. end;
  5192. end
  5193. else if (ts_wasm_threads in current_settings.targetswitches) and
  5194. (objsym.typ=AT_TLS) then
  5195. begin
  5196. { Nothing to do here. A second RELOC_GLOBAL_INDEX_LEB
  5197. relocation, overlaid on top of this one, pointing to
  5198. an AT_WASM_GLOBAL should have already done the job. }
  5199. end
  5200. else
  5201. internalerror(2024010111);
  5202. RELOC_TAG_INDEX_LEB:
  5203. begin
  5204. if objsym.typ<>AT_WASM_EXCEPTION_TAG then
  5205. internalerror(2024010708);
  5206. if FRelocationPass=2 then
  5207. begin
  5208. objsec.Data.seek(objreloc.DataOffset);
  5209. WriteUleb5(objsec.Data,UInt32(objsym.offset+objsym.objsection.MemPos));
  5210. end;
  5211. end;
  5212. else
  5213. internalerror(2024010109);
  5214. end;
  5215. end
  5216. else if assigned(objreloc.objsection) then
  5217. begin
  5218. if objreloc.typ<>RELOC_ABSOLUTE then
  5219. internalerror(2024010601);
  5220. if FRelocationPass=2 then
  5221. begin
  5222. objsec.Data.seek(objreloc.DataOffset);
  5223. writeUInt32LE(UInt32((objreloc.objsection.MemPos)+objreloc.Addend));
  5224. end;
  5225. end
  5226. else if objreloc.typ=RELOC_TYPE_INDEX_LEB then
  5227. begin
  5228. case FRelocationPass of
  5229. 1:
  5230. objreloc.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(objreloc.FuncType);
  5231. 2:
  5232. begin
  5233. objsec.Data.seek(objreloc.DataOffset);
  5234. WriteUleb5(objsec.Data,objreloc.ExeTypeIndex);
  5235. end;
  5236. end;
  5237. end
  5238. else
  5239. internalerror(2024010110);
  5240. {$ifdef EXTDEBUG_WASM}
  5241. if (FRelocationPass=2) and assigned(objsec.data) and (objsec.data.size<>objsec.size) then
  5242. internalerror(2025100101,'relocation increased section''s data size: '+objreloc.ToString);
  5243. {$endif}
  5244. end;
  5245. end;
  5246. constructor TWasmExeOutput.create;
  5247. var
  5248. i: TWasmSectionID;
  5249. j: TWasmCustomSectionType;
  5250. k: TWasmNameSubsectionType;
  5251. begin
  5252. inherited create;
  5253. CObjData:=TWasmObjData;
  5254. SectionMemAlign:=16;
  5255. MaxMemPos:=$FFFFFFFF;
  5256. FFuncTypes:=TWasmFuncTypeTable.Create;
  5257. for i in TWasmSectionID do
  5258. FWasmSections[i] := tdynamicarray.create(SectionDataMaxGrow);
  5259. for j in TWasmCustomSectionType do
  5260. FWasmCustomSections[j] := tdynamicarray.create(SectionDataMaxGrow);
  5261. for k:=low(FWasmNameSubsections) to high(FWasmNameSubsections) do
  5262. FWasmNameSubsections[k] := tdynamicarray.create(SectionDataMaxGrow);
  5263. SetLength(FIndirectFunctionTable,1);
  5264. FIndirectFunctionTable[0].FuncIdx:=-1;
  5265. end;
  5266. destructor TWasmExeOutput.destroy;
  5267. var
  5268. i: TWasmSectionID;
  5269. j: TWasmCustomSectionType;
  5270. k: TWasmNameSubsectionType;
  5271. begin
  5272. for i in TWasmSectionID do
  5273. FWasmSections[i].Free;
  5274. for j in TWasmCustomSectionType do
  5275. FWasmCustomSections[j].Free;
  5276. for k:=low(FWasmNameSubsections) to high(FWasmNameSubsections) do
  5277. FWasmNameSubsections[k].Free;
  5278. FFuncTypes.Free;
  5279. inherited destroy;
  5280. end;
  5281. procedure TWasmExeOutput.GenerateLibraryImports(ImportLibraryList: TFPHashObjectList);
  5282. var
  5283. i, j: Integer;
  5284. ImportLibrary: TImportLibrary;
  5285. ImportSymbol: TImportSymbol;
  5286. exesym: TExeSymbol;
  5287. begin
  5288. { Here map import symbols to exe symbols and create necessary sections.
  5289. Actual import generation is done after unused sections (and symbols) are removed. }
  5290. FImports:=ImportLibraryList;
  5291. for i:=0 to ImportLibraryList.Count-1 do
  5292. begin
  5293. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  5294. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  5295. begin
  5296. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  5297. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  5298. if assigned(exesym) and
  5299. (exesym.State<>symstate_defined) then
  5300. begin
  5301. ImportSymbol.CachedExeSymbol:=exesym;
  5302. exesym.State:=symstate_defined;
  5303. end;
  5304. end;
  5305. end;
  5306. PackUnresolvedExeSymbols('after module imports');
  5307. end;
  5308. procedure TWasmExeOutput.AfterUnusedSectionRemoval;
  5309. begin
  5310. PrepareImports;
  5311. PrepareFunctions;
  5312. PrepareTags;
  5313. if Assigned(exemap) then
  5314. WriteMap_TypeSection;
  5315. { we do an extra preliminary relocation pass, in order to prepare the
  5316. indices for the Type section and the Table section. This is required
  5317. by GenerateCode_InvokeHelper. }
  5318. FRelocationPass:=1;
  5319. FixupRelocations;
  5320. { in pass 2, we do the actual relocation fixups. No need to call
  5321. FixupRelocations here, since it'll be called in
  5322. TInternalLinker.RunLinkScript, after this method finishes. We only
  5323. set the FRelocationPass variable here, so DoRelocationFixup knows
  5324. which pass it is. }
  5325. FRelocationPass:=2;
  5326. { This needs to be done before pass 2 of the relocation fixups, because
  5327. it'll generate code, thus it'll move the offsets of the functions that
  5328. follow it in the Code section, and we want our DWARF debug info to
  5329. contain correct code offsets. }
  5330. GenerateCode_InvokeHelper;
  5331. if Assigned(exemap) then
  5332. WriteMap_IndirectFunctionTable;
  5333. end;
  5334. procedure TWasmExeOutput.MemPos_ExeSection(const aname: string);
  5335. const
  5336. DebugPrefix = '.debug_';
  5337. var
  5338. ExeSec: TExeSection;
  5339. i: Integer;
  5340. objsec: TObjSection;
  5341. firstdatasec: string;
  5342. begin
  5343. { WebAssembly is a Harvard architecture.
  5344. Data lives in a separate address space, so start addressing back from 0
  5345. (the LLVM leaves the first 1024 bytes in the data segment empty, so we
  5346. start at 1024). }
  5347. if ts_wasm_threads in current_settings.targetswitches then
  5348. firstdatasec:='.tbss'
  5349. else
  5350. firstdatasec:='.rodata';
  5351. if aname=firstdatasec then
  5352. begin
  5353. CurrMemPos:=1024;
  5354. inherited;
  5355. end
  5356. else if aname='.text' then
  5357. begin
  5358. CurrMemPos:=0;
  5359. ExeSec:=FindExeSection(aname);
  5360. if not assigned(ExeSec) then
  5361. exit;
  5362. exesec.MemPos:=CurrMemPos;
  5363. CurrMemPos:=CurrMemPos+UlebEncodingSize(exesec.ObjSectionList.Count);
  5364. { set position of object ObjSections }
  5365. for i:=0 to exesec.ObjSectionList.Count-1 do
  5366. begin
  5367. objsec:=TObjSection(exesec.ObjSectionList[i]);
  5368. CurrMemPos:=CurrMemPos+UlebEncodingSize(objsec.Size);
  5369. CurrMemPos:=objsec.setmempos(CurrMemPos);
  5370. end;
  5371. { calculate size of the section }
  5372. exesec.Size:=CurrMemPos-exesec.MemPos;
  5373. end
  5374. else if (aname='.wasm_globals') or (aname='.wasm_tags') or
  5375. (Copy(aname,1,Length(DebugPrefix))=DebugPrefix) then
  5376. begin
  5377. CurrMemPos:=0;
  5378. inherited;
  5379. end
  5380. else
  5381. inherited;
  5382. end;
  5383. procedure TWasmExeOutput.Load_Symbol(const aname: string);
  5384. begin
  5385. if aname=StackPointerSymStr then
  5386. begin
  5387. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5388. FStackPointerSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5389. FStackPointerSym.size:=1;
  5390. FStackPointerSym.ObjSection.WriteZeros(1);
  5391. TWasmObjSection(FStackPointerSym.ObjSection).MainFuncSymbol:=FStackPointerSym;
  5392. FStackPointerSym.LinkingData.GlobalType:=wbt_i32;
  5393. FStackPointerSym.LinkingData.GlobalIsMutable:=True;
  5394. FStackPointerSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5395. FStackPointerSym.LinkingData.GlobalInitializer.init_i32:=0;
  5396. end
  5397. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_base') then
  5398. begin
  5399. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5400. FTlsBaseSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5401. FTlsBaseSym.size:=1;
  5402. FTlsBaseSym.ObjSection.WriteZeros(1);
  5403. TWasmObjSection(FTlsBaseSym.ObjSection).MainFuncSymbol:=FTlsBaseSym;
  5404. FTlsBaseSym.LinkingData.GlobalType:=wbt_i32;
  5405. FTlsBaseSym.LinkingData.GlobalIsMutable:=True;
  5406. FTlsBaseSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5407. FTlsBaseSym.LinkingData.GlobalInitializer.init_i32:=0;
  5408. end
  5409. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_size') then
  5410. begin
  5411. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5412. FTlsSizeSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5413. FTlsSizeSym.size:=1;
  5414. FTlsSizeSym.ObjSection.WriteZeros(1);
  5415. TWasmObjSection(FTlsSizeSym.ObjSection).MainFuncSymbol:=FTlsSizeSym;
  5416. FTlsSizeSym.LinkingData.GlobalType:=wbt_i32;
  5417. FTlsSizeSym.LinkingData.GlobalIsMutable:=False;
  5418. FTlsSizeSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5419. FTlsSizeSym.LinkingData.GlobalInitializer.init_i32:=0;
  5420. end
  5421. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__tls_align') then
  5422. begin
  5423. internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
  5424. FTlsAlignSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
  5425. FTlsAlignSym.size:=1;
  5426. FTlsAlignSym.ObjSection.WriteZeros(1);
  5427. TWasmObjSection(FTlsAlignSym.ObjSection).MainFuncSymbol:=FTlsAlignSym;
  5428. FTlsAlignSym.LinkingData.GlobalType:=wbt_i32;
  5429. FTlsAlignSym.LinkingData.GlobalIsMutable:=False;
  5430. FTlsAlignSym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5431. FTlsAlignSym.LinkingData.GlobalInitializer.init_i32:=0;
  5432. end
  5433. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__wasm_init_tls') then
  5434. begin
  5435. internalObjData.createsection('*'+aname,0,[]);
  5436. FInitTlsFunctionSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION));
  5437. TWasmObjSection(FInitTlsFunctionSym.ObjSection).MainFuncSymbol:=FInitTlsFunctionSym;
  5438. FInitTlsFunctionSym.LinkingData.FuncType:=TWasmFuncType.Create([wbt_i32],[]);
  5439. end
  5440. else if (ts_wasm_threads in current_settings.targetswitches) and (aname='__fpc_wasm_init_shared_memory') then
  5441. begin
  5442. internalObjData.createsection('*'+aname,0,[]);
  5443. FInitSharedMemoryFunctionSym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION));
  5444. TWasmObjSection(FInitSharedMemoryFunctionSym.ObjSection).MainFuncSymbol:=FInitSharedMemoryFunctionSym;
  5445. FInitSharedMemoryFunctionSym.ObjSection.SecOptions:=FInitSharedMemoryFunctionSym.ObjSection.SecOptions+[oso_keep];
  5446. FInitSharedMemoryFunctionSym.LinkingData.FuncType:=TWasmFuncType.Create([],[]);
  5447. end
  5448. else
  5449. inherited;
  5450. end;
  5451. procedure TWasmExeOutput.PrepareImports;
  5452. function AddFunctionImport(const libname,symname:TCmdStr; functype: TWasmFuncType): Integer;
  5453. begin
  5454. SetLength(FFunctionImports,Length(FFunctionImports)+1);
  5455. Result:=High(FFunctionImports);
  5456. if assigned(exemap) then
  5457. exemap.Add(' Importing Function[' + tostr(Result) + '] ' + symname + functype.ToString);
  5458. with FFunctionImports[Result] do
  5459. begin
  5460. ModName:=libname;
  5461. Name:=symname;
  5462. TypeIdx:=FFuncTypes.AddOrGetFuncType(functype);
  5463. end;
  5464. end;
  5465. var
  5466. i, j: Integer;
  5467. ImportLibrary: TImportLibrary;
  5468. ImportSymbol: TImportSymbol;
  5469. exesym: TExeSymbol;
  5470. newdll: Boolean;
  5471. fsym: TWasmObjSymbol;
  5472. objdata: TObjData;
  5473. begin
  5474. for i:=0 to FImports.Count-1 do
  5475. begin
  5476. ImportLibrary:=TImportLibrary(FImports[i]);
  5477. newdll:=False;
  5478. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  5479. begin
  5480. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  5481. exesym:=ImportSymbol.CachedExeSymbol;
  5482. if assigned(exesym) and
  5483. exesym.Used then
  5484. begin
  5485. if (not newdll) and assigned(exemap) then
  5486. begin
  5487. exemap.Add('');
  5488. exemap.Add('Importing from module '+ImportLibrary.Name);
  5489. end;
  5490. newdll:=True;
  5491. TWasmObjSymbol(exesym.ObjSymbol).LinkingData.ExeFunctionIndex:=
  5492. AddFunctionImport(ImportLibrary.Name,ImportSymbol.Name,TWasmObjSymbol(exesym.ObjSymbol).LinkingData.FuncType);
  5493. AddToFunctionNameMap(TWasmObjSymbol(exesym.ObjSymbol).LinkingData.ExeFunctionIndex,ImportSymbol.MangledName);
  5494. end;
  5495. end;
  5496. end;
  5497. { set ExeFunctionIndex to the alias symbols as well }
  5498. for i:=0 to ObjDataList.Count-1 do
  5499. begin
  5500. objdata:=TObjData(ObjDataList[i]);
  5501. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5502. begin
  5503. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5504. if (fsym.LinkingData.ExeFunctionIndex=-1) and assigned(fsym.exesymbol) and (TWasmObjSymbol(fsym.exesymbol.ObjSymbol).LinkingData.ExeFunctionIndex<>-1) then
  5505. fsym.LinkingData.ExeFunctionIndex:=TWasmObjSymbol(fsym.exesymbol.ObjSymbol).LinkingData.ExeFunctionIndex;
  5506. end;
  5507. end;
  5508. end;
  5509. procedure TWasmExeOutput.PrepareFunctions;
  5510. var
  5511. i, j: Integer;
  5512. exesec: TExeSection;
  5513. objsec: TWasmObjSection;
  5514. fsym: TWasmObjSymbol;
  5515. objdata: TObjData;
  5516. begin
  5517. if assigned(exemap) then
  5518. begin
  5519. exemap.Add('');
  5520. exemap.Add('Functions, defined in this module:');
  5521. end;
  5522. exesec:=FindExeSection('.text');
  5523. if not assigned(exesec) then
  5524. internalerror(2023123106);
  5525. for i:=0 to exesec.ObjSectionList.Count-1 do
  5526. begin
  5527. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5528. fsym:=objsec.MainFuncSymbol;
  5529. if not assigned(fsym) then
  5530. internalerror(2023123107);
  5531. if not assigned(fsym.LinkingData.FuncType) then
  5532. internalerror(2023123108);
  5533. if fsym.LinkingData.ExeFunctionIndex<>-1 then
  5534. internalerror(2023123109);
  5535. if fsym.LinkingData.ExeTypeIndex<>-1 then
  5536. internalerror(2023123109);
  5537. fsym.LinkingData.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(fsym.LinkingData.FuncType);
  5538. fsym.LinkingData.ExeFunctionIndex:=i+Length(FFunctionImports);
  5539. if assigned(exemap) then
  5540. begin
  5541. exemap.Add(' Function[' + tostr(fsym.LinkingData.ExeFunctionIndex) + '] ' + fsym.Name + fsym.LinkingData.FuncType.ToString);
  5542. end;
  5543. AddToFunctionNameMap(fsym.LinkingData.ExeFunctionIndex,fsym.Name);
  5544. end;
  5545. { set ExeFunctionIndex to the alias symbols as well }
  5546. for i:=0 to ObjDataList.Count-1 do
  5547. begin
  5548. objdata:=TObjData(ObjDataList[i]);
  5549. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5550. begin
  5551. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5552. if assigned(fsym.objsection) and fsym.objsection.USed and (fsym.typ=AT_FUNCTION) and (fsym.LinkingData.ExeFunctionIndex=-1) then
  5553. begin
  5554. fsym.LinkingData.ExeFunctionIndex:=TWasmObjSection(fsym.objsection).MainFuncSymbol.LinkingData.ExeFunctionIndex;
  5555. if fsym.LinkingData.ExeFunctionIndex=-1 then
  5556. internalerror(2024010102);
  5557. end;
  5558. end;
  5559. end;
  5560. end;
  5561. procedure TWasmExeOutput.PrepareTags;
  5562. var
  5563. exesec: TExeSection;
  5564. i, j: Integer;
  5565. objsec: TWasmObjSection;
  5566. fsym: TWasmObjSymbol;
  5567. objdata: TObjData;
  5568. begin
  5569. exesec:=FindExeSection('.wasm_tags');
  5570. if not assigned(exesec) then
  5571. exit;
  5572. if assigned(exemap) then
  5573. begin
  5574. exemap.Add('');
  5575. exemap.Add('Tags, defined in this module:');
  5576. end;
  5577. for i:=0 to exesec.ObjSectionList.Count-1 do
  5578. begin
  5579. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5580. fsym:=objsec.MainFuncSymbol;
  5581. if not assigned(fsym) then
  5582. internalerror(2024010703);
  5583. if not assigned(fsym.LinkingData.FuncType) then
  5584. internalerror(2024010704);
  5585. if fsym.LinkingData.ExeTagIndex<>-1 then
  5586. internalerror(2024010705);
  5587. if fsym.LinkingData.ExeTypeIndex<>-1 then
  5588. internalerror(2024010706);
  5589. fsym.LinkingData.ExeTypeIndex:=FFuncTypes.AddOrGetFuncType(fsym.LinkingData.FuncType);
  5590. fsym.LinkingData.ExeTagIndex:=i+Length(FTagImports);
  5591. if assigned(exemap) then
  5592. begin
  5593. exemap.Add(' Tag[' + tostr(fsym.LinkingData.ExeTagIndex) + '] ' + fsym.Name + fsym.LinkingData.FuncType.ToString);
  5594. end;
  5595. end;
  5596. { set ExeTagIndex to the alias symbols as well }
  5597. for i:=0 to ObjDataList.Count-1 do
  5598. begin
  5599. objdata:=TObjData(ObjDataList[i]);
  5600. for j:=0 to objdata.ObjSymbolList.Count-1 do
  5601. begin
  5602. fsym:=TWasmObjSymbol(objdata.ObjSymbolList[j]);
  5603. if assigned(fsym.objsection) and fsym.objsection.USed and (fsym.typ=AT_WASM_EXCEPTION_TAG) and (fsym.LinkingData.ExeTagIndex=-1) then
  5604. begin
  5605. fsym.LinkingData.ExeTagIndex:=TWasmObjSection(fsym.objsection).MainFuncSymbol.LinkingData.ExeTagIndex;
  5606. if fsym.LinkingData.ExeTagIndex=-1 then
  5607. internalerror(2024010707);
  5608. end;
  5609. end;
  5610. end;
  5611. end;
  5612. function TWasmExeOutput.AddOrGetIndirectFunctionTableIndex(FuncIdx: Integer): integer;
  5613. var
  5614. i: Integer;
  5615. begin
  5616. for i:=1 to length(FIndirectFunctionTable)-1 do
  5617. if FIndirectFunctionTable[i].FuncIdx=FuncIdx then
  5618. begin
  5619. Result:=i;
  5620. exit;
  5621. end;
  5622. SetLength(FIndirectFunctionTable,Length(FIndirectFunctionTable)+1);
  5623. Result:=High(FIndirectFunctionTable);
  5624. FIndirectFunctionTable[Result].FuncIdx:=FuncIdx;
  5625. end;
  5626. procedure TWasmExeOutput.SetStackPointer;
  5627. var
  5628. BssSec: TExeSection;
  5629. StackStart, InitialStackPtrAddr: QWord;
  5630. begin
  5631. BssSec:=FindExeSection('.bss');
  5632. InitialStackPtrAddr := (BssSec.MemPos+BssSec.Size+stacksize+15) and (not 15);
  5633. FMinMemoryPages := Max(
  5634. QWord(Align(QWord(InitialStackPtrAddr),QWord(WasmPageSize)) div WasmPageSize),
  5635. QWord(Align(QWord(heapsize),QWord(WasmPageSize)) div WasmPageSize));
  5636. FStackPointerSym.LinkingData.GlobalInitializer.init_i32:=Int32(InitialStackPtrAddr);
  5637. end;
  5638. procedure TWasmExeOutput.SetTlsSizeAlignAndBase;
  5639. var
  5640. TBssSec: TExeSection;
  5641. begin
  5642. if not (ts_wasm_threads in current_settings.targetswitches) then
  5643. exit;
  5644. TBssSec:=FindExeSection('.tbss');
  5645. FTlsSizeSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.Size);
  5646. FTlsAlignSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.SecAlign);
  5647. FTlsBaseSym.LinkingData.GlobalInitializer.init_i32:=Int32(TBssSec.MemPos);
  5648. end;
  5649. procedure TWasmExeOutput.SetThreadVarGlobalsInitValues;
  5650. var
  5651. exesec: TExeSection;
  5652. i: Integer;
  5653. objsec: TWasmObjSection;
  5654. objsym: TWasmObjSymbol;
  5655. begin
  5656. if not (ts_wasm_threads in current_settings.targetswitches) then
  5657. exit;
  5658. exesec:=FindExeSection('.wasm_globals');
  5659. if not assigned(exesec) then
  5660. internalerror(2024010112);
  5661. for i:=0 to exesec.ObjSectionList.Count-1 do
  5662. begin
  5663. objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
  5664. objsym:=objsec.MainFuncSymbol;
  5665. if Assigned(objsym.TlsDataSym) then
  5666. begin
  5667. objsym.LinkingData.GlobalInitializer.typ:=wbt_i32;
  5668. objsym.LinkingData.GlobalInitializer.init_i32:=objsym.TlsDataSym.offset+objsym.TlsDataSym.objsection.MemPos;
  5669. end;
  5670. end;
  5671. end;
  5672. procedure TWasmExeOutput.GenerateCode_InitTls;
  5673. var
  5674. Sec: TObjSection;
  5675. globalexesec: TExeSection;
  5676. i: Integer;
  5677. globalobjsec: TWasmObjSection;
  5678. globalobjsym: TWasmObjSymbol;
  5679. OffsetInTls: QWord;
  5680. begin
  5681. if not (ts_wasm_threads in current_settings.targetswitches) then
  5682. exit;
  5683. globalexesec:=FindExeSection('.wasm_globals');
  5684. if not assigned(globalexesec) then
  5685. internalerror(2024010112);
  5686. Sec:=FInitTlsFunctionSym.objsection;
  5687. Sec.SecOptions:=Sec.SecOptions+[oso_Data];
  5688. { locals }
  5689. Sec.writeUInt8($00);
  5690. { local.get 0 }
  5691. Sec.writeUInt16BE($2000);
  5692. { global.set $__tls_base }
  5693. Sec.writeUInt8($24);
  5694. WriteUleb(sec,FTlsBaseSym.offset+FTlsBaseSym.objsection.MemPos);
  5695. for i:=0 to globalexesec.ObjSectionList.Count-1 do
  5696. begin
  5697. globalobjsec:=TWasmObjSection(globalexesec.ObjSectionList[i]);
  5698. globalobjsym:=globalobjsec.MainFuncSymbol;
  5699. if Assigned(globalobjsym.TlsDataSym) then
  5700. begin
  5701. OffsetInTls:=globalobjsym.TlsDataSym.offset+globalobjsym.TlsDataSym.objsection.MemPos-globalobjsym.TlsDataSym.objsection.ExeSection.MemPos;
  5702. { local.get 0 }
  5703. Sec.writeUInt16BE($2000);
  5704. if OffsetInTls<>0 then
  5705. begin
  5706. { i32.const $OffsetInTls }
  5707. Sec.writeUInt8($41);
  5708. WriteSleb(Sec,Int32(OffsetInTls));
  5709. { i32.add }
  5710. Sec.writeUInt8($6A);
  5711. end;
  5712. { global.set y }
  5713. Sec.writeUInt8($24);
  5714. WriteUleb(sec,globalobjsym.offset+globalobjsym.objsection.MemPos);
  5715. end;
  5716. end;
  5717. Sec.writeUInt8($0B); { end }
  5718. end;
  5719. procedure TWasmExeOutput.GenerateCode_InitSharedMemory;
  5720. const
  5721. InitFlagOfs=256;
  5722. var
  5723. Sec: TObjSection;
  5724. DataSecName: string;
  5725. DataSecIdx: Integer;
  5726. ExeSec: TExeSection;
  5727. begin
  5728. if not (ts_wasm_threads in current_settings.targetswitches) then
  5729. exit;
  5730. Sec:=FInitSharedMemoryFunctionSym.objsection;
  5731. Sec.SecOptions:=Sec.SecOptions+[oso_Data];
  5732. { locals }
  5733. Sec.writeUInt8($00);
  5734. { block }
  5735. Sec.writeUInt16BE($0240);
  5736. { block }
  5737. Sec.writeUInt16BE($0240);
  5738. { block }
  5739. Sec.writeUInt16BE($0240);
  5740. { i32.const $InitFlag }
  5741. Sec.writeUInt8($41);
  5742. WriteSleb(sec,InitFlagOfs);
  5743. { i32.const 0 }
  5744. Sec.writeUInt16BE($4100);
  5745. { i32.const 1 }
  5746. Sec.writeUInt16BE($4101);
  5747. { i32.atomic.rmw.cmpxchg 2 0 }
  5748. Sec.writeUInt32BE($fe480200);
  5749. { br_table 0 1 2 }
  5750. Sec.writebytes(#$0e#$02#$00#$01#$02);
  5751. { end }
  5752. Sec.writeUInt8($0B);
  5753. DataSecIdx:=-1;
  5754. for DataSecName in DataSections do
  5755. begin
  5756. ExeSec:=FindExeSection(DataSecName);
  5757. if Assigned(ExeSec) and (ExeSec.Size>0) then
  5758. begin
  5759. Inc(DataSecIdx);
  5760. { i32.const $memPos }
  5761. Sec.writeUInt8($41);
  5762. WriteSleb(sec,Int32(ExeSec.MemPos));
  5763. { i32.const 0 }
  5764. Sec.writeUInt16BE($4100);
  5765. { i32.const size }
  5766. Sec.writeUInt8($41);
  5767. WriteSleb(sec,Int32(ExeSec.Size));
  5768. { memory.init $DataSecIdx 0 }
  5769. Sec.writeUInt16BE($fc08);
  5770. WriteUleb(sec,DataSecIdx);
  5771. Sec.writeUInt8(0);
  5772. end;
  5773. end;
  5774. { i32.const $InitFlag }
  5775. Sec.writeUInt8($41);
  5776. WriteSleb(sec,InitFlagOfs);
  5777. { i32.const 2 }
  5778. Sec.writeUInt16BE($4102);
  5779. { i32.atomic.store 2 0 }
  5780. Sec.writeUInt32BE($fe170200);
  5781. { i32.const $InitFlag }
  5782. Sec.writeUInt8($41);
  5783. WriteSleb(sec,InitFlagOfs);
  5784. { i32.const 4294967295 }
  5785. Sec.writeUInt16BE($417f);
  5786. { memory.atomic.notify 2 0 }
  5787. Sec.writeUInt32BE($fe000200);
  5788. { drop }
  5789. Sec.writeUInt8($1A);
  5790. { br 1 }
  5791. Sec.writeUInt16BE($0C01);
  5792. { end }
  5793. Sec.writeUInt8($0B);
  5794. { i32.const $InitFlag }
  5795. Sec.writeUInt8($41);
  5796. WriteSleb(sec,InitFlagOfs);
  5797. { i32.const 1 }
  5798. Sec.writeUInt16BE($4101);
  5799. { i64.const -1 }
  5800. Sec.writeUInt16BE($427f);
  5801. { memory.atomic.wait32 2 0 }
  5802. Sec.writeUInt32BE($fe010200);
  5803. { drop }
  5804. Sec.writeUInt8($1A);
  5805. { end }
  5806. Sec.writeUInt8($0B);
  5807. DataSecIdx:=-1;
  5808. for DataSecName in DataSections do
  5809. begin
  5810. ExeSec:=FindExeSection(DataSecName);
  5811. if Assigned(ExeSec) and (ExeSec.Size>0) then
  5812. begin
  5813. Inc(DataSecIdx);
  5814. { data.drop $DataSecIdx }
  5815. Sec.writeUInt16BE($fc09);
  5816. WriteUleb(sec,DataSecIdx);
  5817. end;
  5818. end;
  5819. { end }
  5820. Sec.writeUInt8($0B);
  5821. end;
  5822. procedure TWasmExeOutput.GenerateCode_InvokeHelper;
  5823. var
  5824. Sec: TObjSection;
  5825. IndirectFunctionTableMap: array of Integer;
  5826. procedure InvokeFuncType(typidx: Integer; islast: Boolean);
  5827. var
  5828. ft: TWasmFuncType;
  5829. i, nextofs: Integer;
  5830. begin
  5831. ft:=FFuncTypes[typidx];
  5832. for i:=0 to Length(ft.results)-1 do
  5833. { local.get 2 }
  5834. Sec.writeUInt16BE($2002);
  5835. nextofs:=0;
  5836. for i:=0 to Length(ft.params)-1 do
  5837. begin
  5838. { local.get 1 }
  5839. Sec.writeUInt16BE($2001);
  5840. case ft.params[i] of
  5841. wbt_i32:
  5842. begin
  5843. { i32.load nextofs }
  5844. Sec.writeUInt16BE($2802);
  5845. WriteUleb(Sec, nextofs);
  5846. Inc(nextofs,4);
  5847. end;
  5848. wbt_i64:
  5849. begin
  5850. { i64.load nextofs }
  5851. Sec.writeUInt16BE($2902);
  5852. WriteUleb(Sec, nextofs);
  5853. Inc(nextofs,8);
  5854. end;
  5855. wbt_f32:
  5856. begin
  5857. { f32.load nextofs }
  5858. Sec.writeUInt16BE($2A02);
  5859. WriteUleb(Sec, nextofs);
  5860. Inc(nextofs,4);
  5861. end;
  5862. wbt_f64:
  5863. begin
  5864. { f64.load nextofs }
  5865. Sec.writeUInt16BE($2B02);
  5866. WriteUleb(Sec, nextofs);
  5867. Inc(nextofs,8);
  5868. end;
  5869. wbt_v128:
  5870. begin
  5871. { v128.load nextofs }
  5872. Sec.writeUInt16BE($FD00);
  5873. Sec.writeUInt8($02); { align: 4 bytes }
  5874. WriteUleb(Sec, nextofs);
  5875. Inc(nextofs,16);
  5876. end;
  5877. wbt_externref,
  5878. wbt_funcref:
  5879. begin
  5880. { unreachable }
  5881. Sec.writeUInt8($00);
  5882. end;
  5883. else
  5884. internalerror(2025012501);
  5885. end;
  5886. end;
  5887. { local.get 0 }
  5888. Sec.writeUInt16BE($2000);
  5889. { call_indirect }
  5890. Sec.writeUInt8($11);
  5891. WriteUleb(Sec,typidx);
  5892. Sec.writeUInt8($0); { table index 0 }
  5893. nextofs:=0;
  5894. for i:=0 to Length(ft.results)-1 do
  5895. begin
  5896. case ft.results[i] of
  5897. wbt_i32:
  5898. begin
  5899. { i32.store nextofs }
  5900. Sec.writeUInt16BE($3602);
  5901. WriteUleb(Sec, nextofs);
  5902. Inc(nextofs,4);
  5903. end;
  5904. wbt_i64:
  5905. begin
  5906. { i64.store nextofs }
  5907. Sec.writeUInt16BE($3702);
  5908. WriteUleb(Sec, nextofs);
  5909. Inc(nextofs,8);
  5910. end;
  5911. wbt_f32:
  5912. begin
  5913. { f32.store nextofs }
  5914. Sec.writeUInt16BE($3802);
  5915. WriteUleb(Sec, nextofs);
  5916. Inc(nextofs,4);
  5917. end;
  5918. wbt_f64:
  5919. begin
  5920. { f64.store nextofs }
  5921. Sec.writeUInt16BE($3902);
  5922. WriteUleb(Sec, nextofs);
  5923. Inc(nextofs,8);
  5924. end;
  5925. wbt_v128:
  5926. begin
  5927. { v128.store nextofs }
  5928. Sec.writeUInt16BE($FD0B);
  5929. Sec.writeUInt8($02); { align: 4 bytes }
  5930. WriteUleb(Sec, nextofs);
  5931. Inc(nextofs,16);
  5932. end;
  5933. wbt_externref,
  5934. wbt_funcref:
  5935. begin
  5936. { unreachable }
  5937. Sec.writeUInt8($00);
  5938. end;
  5939. else
  5940. internalerror(2025012501);
  5941. end;
  5942. end;
  5943. if not islast then
  5944. { return }
  5945. Sec.writeUInt8($0F);
  5946. end;
  5947. function FuncIdx2TypeIdx(fi: Integer): Integer;
  5948. var
  5949. exesec: TExeSection;
  5950. objsec: TWasmObjSection;
  5951. fsym: TWasmObjSymbol;
  5952. begin
  5953. if fi<Length(FFunctionImports) then
  5954. Result:=FFunctionImports[fi].TypeIdx
  5955. else
  5956. begin
  5957. exesec:=FindExeSection('.text');
  5958. if not assigned(exesec) then
  5959. internalerror(2023123106);
  5960. objsec:=TWasmObjSection(exesec.ObjSectionList[fi-Length(FFunctionImports)]);
  5961. fsym:=objsec.MainFuncSymbol;
  5962. Result:=fsym.LinkingData.ExeTypeIndex;
  5963. end;
  5964. end;
  5965. procedure WriteBrTable(l,h: Integer; addend: Integer=0);
  5966. const
  5967. { max len of br_table instruction }
  5968. MaxLen=1000;
  5969. var
  5970. i, len, m: Integer;
  5971. begin
  5972. { local.get 0 }
  5973. Sec.writeUInt16BE($2000);
  5974. len:=h-l+1;
  5975. if len<=MaxLen then
  5976. begin
  5977. if l>0 then
  5978. begin
  5979. { i32.const l }
  5980. Sec.writeUInt8($41);
  5981. WriteSleb(sec,l);
  5982. { i32.sub }
  5983. Sec.writeUInt8($6B);
  5984. end;
  5985. { br_table }
  5986. Sec.writeUInt8($0E);
  5987. if h=high(IndirectFunctionTableMap) then
  5988. begin
  5989. WriteUleb(Sec,len);
  5990. for i:=l to h do
  5991. WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
  5992. WriteUleb(Sec,addend);
  5993. end
  5994. else
  5995. begin
  5996. WriteUleb(Sec,len-1);
  5997. for i:=l to h do
  5998. WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
  5999. end;
  6000. end
  6001. else
  6002. begin
  6003. m:=(l+h) div 2;
  6004. { i32.const m }
  6005. Sec.writeUInt8($41);
  6006. WriteSleb(sec,m);
  6007. { i32.lt_u }
  6008. Sec.writeUInt8($49);
  6009. { if }
  6010. Sec.writeUInt16BE($0440);
  6011. WriteBrTable(l,m-1,addend+1);
  6012. { else }
  6013. Sec.writeUInt8($05);
  6014. WriteBrTable(m,h,addend+1);
  6015. { end }
  6016. Sec.writeUInt8($0B);
  6017. end;
  6018. end;
  6019. var
  6020. exesym: TExeSymbol;
  6021. objsym: TObjSymbol;
  6022. i, j, TypIdx: Integer;
  6023. InvokableTypeIndices: array of Integer;
  6024. begin
  6025. exesym:=TExeSymbol(ExeSymbolList.Find('fpc_wasm_invoke_helper'));
  6026. if not Assigned(exesym) then
  6027. exit;
  6028. SetLength(IndirectFunctionTableMap, Length(FIndirectFunctionTable));
  6029. SetLength(InvokableTypeIndices, 1);
  6030. InvokableTypeIndices[0] := -1;
  6031. for i:=1 to Length(FIndirectFunctionTable)-1 do
  6032. begin
  6033. IndirectFunctionTableMap[i]:=0;
  6034. TypIdx := FuncIdx2TypeIdx(FIndirectFunctionTable[i].FuncIdx);
  6035. for j := 1 to Length(InvokableTypeIndices)-1 do
  6036. if InvokableTypeIndices[j]=TypIdx then
  6037. begin
  6038. IndirectFunctionTableMap[i]:=j;
  6039. break;
  6040. end;
  6041. if IndirectFunctionTableMap[i]=0 then
  6042. begin
  6043. SetLength(InvokableTypeIndices,Length(InvokableTypeIndices)+1);
  6044. InvokableTypeIndices[High(InvokableTypeIndices)]:=TypIdx;
  6045. IndirectFunctionTableMap[i]:=High(InvokableTypeIndices);
  6046. end;
  6047. end;
  6048. objsym:=exesym.ObjSymbol;
  6049. Sec:=objsym.objsection;
  6050. Sec.Size:=0;
  6051. Sec.Data.reset;
  6052. { locals }
  6053. Sec.writeUInt8($00);
  6054. for i:=1 to Length(InvokableTypeIndices)-1 do
  6055. { block }
  6056. Sec.writeUInt16BE($0240);
  6057. { block }
  6058. Sec.writeUInt16BE($0240);
  6059. { local.get 0 + br_table }
  6060. WriteBrTable(low(IndirectFunctionTableMap),high(IndirectFunctionTableMap));
  6061. { end }
  6062. Sec.writeUInt8($0B);
  6063. { unreachable }
  6064. Sec.writeUInt8($00);
  6065. for i:=1 to Length(InvokableTypeIndices)-1 do
  6066. begin
  6067. { end }
  6068. Sec.writeUInt8($0B);
  6069. InvokeFuncType(InvokableTypeIndices[i],i=(Length(InvokableTypeIndices)-1));
  6070. end;
  6071. { end }
  6072. Sec.writeUInt8($0B);
  6073. end;
  6074. procedure TWasmExeOutput.WriteExeSectionToDynArray(exesec: TExeSection; dynarr: tdynamicarray);
  6075. var
  6076. exesecdatapos: LongWord;
  6077. i: Integer;
  6078. objsec: TObjSection;
  6079. dpos, pad: QWord;
  6080. begin
  6081. exesecdatapos:=dynarr.size;
  6082. for i:=0 to exesec.ObjSectionList.Count-1 do
  6083. begin
  6084. objsec:=TObjSection(exesec.ObjSectionList[i]);
  6085. if not (oso_data in objsec.secoptions) then
  6086. internalerror(2024010104);
  6087. if not assigned(objsec.data) then
  6088. internalerror(2024010105);
  6089. dpos:=objsec.MemPos-exesec.MemPos+exesecdatapos;
  6090. pad:=dpos-dynarr.size;
  6091. { objsection must be within SecAlign bytes from the previous one }
  6092. if (dpos<dynarr.Size) or
  6093. (pad>=max(objsec.SecAlign,1)) then
  6094. internalerror(2024010106);
  6095. writeZeros(dynarr,pad);
  6096. objsec.data.seek(0);
  6097. CopyDynamicArray(objsec.data,dynarr,objsec.data.size);
  6098. end;
  6099. if (dynarr.size-exesecdatapos)<>exesec.Size then
  6100. internalerror(2024010107);
  6101. end;
  6102. procedure TWasmExeOutput.WriteMemoryTo(dest: tdynamicarray; const MemType: TWasmMemoryType);
  6103. begin
  6104. WriteByte(dest,Byte(MemType.Flags));
  6105. WriteUleb(dest,MemType.MinPages);
  6106. if wmfHasMaximumBound in MemType.Flags then
  6107. WriteUleb(dest,MemType.MaxPages);
  6108. { todo: wmfCustomPageSize }
  6109. end;
  6110. function TWasmExeOutput.Memory2String(const MemType: TWasmMemoryType): string;
  6111. begin
  6112. Result:='index type: ';
  6113. if wmfMemory64 in MemType.Flags then
  6114. Result:=Result+'i64'
  6115. else
  6116. Result:=Result+'i32';
  6117. Result:=Result+', pages: initial='+tostr(MemType.MinPages);
  6118. if wmfHasMaximumBound in MemType.Flags then
  6119. Result:=Result+' max='+tostr(MemType.MaxPages);
  6120. if wmfShared in MemType.Flags then
  6121. Result:=Result+', shared'
  6122. else
  6123. Result:=Result+', unshared';
  6124. { todo: wmfCustomPageSize }
  6125. end;
  6126. procedure TWasmExeOutput.WriteMap_TypeSection;
  6127. var
  6128. i: Integer;
  6129. begin
  6130. exemap.AddHeader('Type section');
  6131. for i:=0 to FFuncTypes.Count-1 do
  6132. exemap.Add(' Type[' + tostr(i) + '] ' + FFuncTypes.Items[i].ToString);
  6133. end;
  6134. procedure TWasmExeOutput.WriteMap_IndirectFunctionTable;
  6135. var
  6136. i: Integer;
  6137. begin
  6138. exemap.AddHeader('Indirect function table');
  6139. for i:=1 to High(FIndirectFunctionTable) do
  6140. exemap.Add(' Elem[' + tostr(i) + '] = Function[' + tostr(FIndirectFunctionTable[i].FuncIdx) + ']');
  6141. end;
  6142. {****************************************************************************
  6143. TWasmAssembler
  6144. ****************************************************************************}
  6145. constructor TWasmAssembler.Create(info: pasminfo; smart:boolean);
  6146. begin
  6147. inherited;
  6148. CObjOutput:=TWasmObjOutput;
  6149. end;
  6150. {*****************************************************************************
  6151. Initialize
  6152. *****************************************************************************}
  6153. {$ifdef wasm32}
  6154. const
  6155. as_wasm32_wasm_info : tasminfo =
  6156. (
  6157. id : as_wasm32_wasm;
  6158. idtxt : 'WASM';
  6159. asmbin : '';
  6160. asmcmd : '';
  6161. supported_targets : [system_wasm32_embedded,system_wasm32_wasip1,system_wasm32_wasip1threads,
  6162. system_wasm32_wasip2];
  6163. flags : [af_outputbinary,af_smartlink_sections];
  6164. labelprefix : '..@';
  6165. labelmaxlen : -1;
  6166. comment : '; ';
  6167. dollarsign: '$';
  6168. );
  6169. {$endif wasm32}
  6170. initialization
  6171. {$ifdef wasm32}
  6172. RegisterAssembler(as_wasm32_wasm_info,TWasmAssembler);
  6173. {$endif wasm32}
  6174. finalization
  6175. end.