ogwasm.pas 254 KB

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