1 Star 0 Fork 6

xCodeRun/clang2mpl

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Clang2MapleVisitor.cpp 229.22 KB
一键复制 编辑 原始数据 按行查看 历史
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176
/*
* Copyright (c) 2021 Futurewei Technologies, Inc.
*
* clang2mpl is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
#include "Clang2MapleVisitor.h"
#include "Clang2MapleOptions.h"
#include "clang/AST/APValue.h"
#include "clang/AST/AST.h"
#include "clang/AST/Attr.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#pragma GCC diagnostic ignored "-Wreturn-type"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma GCC diagnostic ignored "-Wtype-limits"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#pragma GCC diagnostic ignored "-Wsuggest-override"
#include "bin_mplt.h"
#include "mir_symbol.h"
#include "mir_type.h"
#include "mpl_logging.h"
#include "opcode_info.h"
#pragma GCC diagnostic pop
#if defined __has_cpp_attribute
#if __has_cpp_attribute(clang::fallthrough)
#define FALLTHROUGH [[clang::fallthrough]]
#else
#define FALLTHROUGH
#endif
#else
#define FALLTHROUGH
#endif
using namespace maple;
#define BITS_PER_BYTE 8
#define MULTIDIM_ARRAYS 1
static MIRStorageClass StorageClass2Mpl(clang::StorageClass SC);
static Opcode BinOpcode2Mpl(clang::BinaryOperatorKind Op, bool isSigned);
static bool isAssign(Opcode Op);
static bool isPointerType(MIRType *Ty);
static size_t getPointedToSize(MIRType *Ty);
static bool isOneElementVector(clang::QualType QT);
static bool isOneElementVector(const clang::Type *Ty);
#ifdef DEBUG
namespace maple {
extern MIRModule *theMIRModule;
}
#endif // DEBUG
MIRSymbol *Clang2MapleVisitor::VisitTranslationUnitDecl(
const clang::TranslationUnitDecl *TU) {
Context = &TU->getASTContext();
setupBuiltinTypes();
// Initial setup for Maple
// Get source file
clang::FileID MainFileID = Context->getSourceManager().getMainFileID();
const clang::FileEntry *MainFile =
Context->getSourceManager().getFileEntryForID(MainFileID);
// Set source language
Module = new MIRModule(MainFile->getName().str().c_str());
Module->SetCurFunction(nullptr);
#ifdef DEBUG
theMIRModule = Module;
#endif // DEBUG
Module->SetSrcLang(Context->getLangOpts().CPlusPlus ? kSrcLangCPlusPlus
: kSrcLangC);
// TODO: Do we need to setup the source files here? see whirl2mpl.cxx:2879
Builder = new MIRBuilder(Module);
// Create the builtin va_list type
clang::TypedefDecl *VaListTypeDef = Context->getBuiltinVaListDecl();
if (VaListTypeDef->isReferenced()) {
Visit(VaListTypeDef->getUnderlyingType()->getAsRecordDecl());
}
// Visit all of the top-level children
for (auto child = TU->decls_begin(); child != TU->decls_end(); ++child) {
if (!child->isImplicit()) {
Visit(*child);
}
}
// Finalize the module
Module->SetFlavor(kFeProduced);
Module->SetNumFuncs(Module->GetFunctionList().size());
if (UseAscii) {
Module->OutputAsciiMpl("", ".mpl");
} else {
BinaryMplt BinMplt(*Module);
std::string ModuleName = Module->GetFileName();
std::string::size_type LastDot = ModuleName.find_last_of(".");
std::string BaseName = ModuleName.substr(0, LastDot);
BinMplt.GetBinExport().not2mplt = true;
BinMplt.Export(BaseName + ".bpl");
}
return nullptr;
}
//
// Visit Decls
//
// Visit TypeDecls
MIRSymbol *Clang2MapleVisitor::VisitTypeDecl(const clang::TypeDecl *Ty) {
LogInfo::MapleLogger() << "Error: Unhandled type decl\n";
#ifdef DEBUG
Ty->dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
return nullptr;
}
static bool TypeHasMayAlias(const clang::QualType srcType) {
// Tagged types have declarations, and therefore may have attributes.
auto *td = srcType->getAsTagDecl();
if (td != nullptr && td->hasAttr<clang::MayAliasAttr>()) {
return true;
}
clang::QualType qualType = srcType;
while (auto *tt = qualType->getAs<clang::TypedefType>()) {
if (tt->getDecl()->hasAttr<clang::MayAliasAttr>()) {
return true;
}
qualType = tt->desugar();
}
return false;
}
MIRSymbol *
Clang2MapleVisitor::VisitRecordDecl(const clang::RecordDecl *Record) {
// If there is not a complete definition, or this is not it, skip it.
if (!Record || !Record->isCompleteDefinition() ||
!Record->isThisDeclarationADefinition()) {
return nullptr;
}
// If this record has already been fully defined, skip it.
clang::QualType RecTy = Context->getRecordType(Record);
auto it = TypeMap.find(RecTy.getTypePtr());
if (it != TypeMap.end()) {
MIRStructType *STy = static_cast<MIRStructType *>(
GlobalTables::GetTypeTable().GetTypeFromTyIdx(it->second));
if (!STy->IsIncomplete()) {
return nullptr;
}
}
// Process any decls inside of this record (inner struct)
clang::DeclContext *DC = clang::TagDecl::castToDeclContext(Record);
for (const auto *D : DC->decls()) {
if (auto Inner = llvm::dyn_cast<clang::RecordDecl>(D)) {
Visit(Inner);
}
}
std::string TypeName = Record->getName().str();
if (TypeName.empty()) { // Anonymous struct
TypeName = "_anon" + std::to_string(++UnnamedCount);
} else if (TypeName[0] == '.') {
TypeName[0] = '_';
}
const clang::Type *StructTy = Record->getTypeForDecl();
MIRStructType Struct(StructTy->isUnionType() ? kTypeUnion : kTypeStruct);
FieldVector Fields;
for (const auto *I : Record->fields()) {
clang::QualType FieldQT = I->getType();
TyIdx FieldTyIdx = type2MplIdx(FieldQT);
FieldAttrs Attrs;
TyIdxFieldAttrPair TyAttrPair;
clang::CharUnits Alignment = Context->getDeclAlign(I);
if (Alignment > Context->toCharUnitsFromBits(
Context->getTypeUnadjustedAlign(FieldQT))) {
Attrs.SetAlign(Alignment.getQuantity());
}
if (FieldQT.isVolatileQualified()) {
Attrs.SetAttr(FLDATTR_volatile);
}
if (FieldQT.isRestrictQualified()) {
Attrs.SetAttr(FLDATTR_restrict);
}
if (FieldQT.isConstQualified()) {
Attrs.SetAttr(FLDATTR_const);
}
if (isOneElementVector(FieldQT)) {
Attrs.SetAttr(FLDATTR_oneelem_simd);
}
if (I->isBitField()) {
MIRType *FieldTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(FieldTyIdx);
unsigned BitWidth = I->getBitWidthValue(*Context);
MIRBitFieldType BitFieldTy(BitWidth, FieldTy->GetPrimType());
FieldTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&BitFieldTy);
}
TyAttrPair = std::make_pair(FieldTyIdx, Attrs);
std::string FieldName(I->getName().str());
if (FieldName.empty()) {
FieldName = "_no.name" + std::to_string(++UnnamedCount);
} else if (FieldName[0] == '.') {
FieldName[0] = '_';
}
GStrIdx FieldStrIdx =
GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(FieldName);
Fields.push_back(std::make_pair(FieldStrIdx, TyAttrPair));
}
Struct.SetFields(Fields);
recordFieldIDs(Record, Record, 0);
MIRType *MTy = GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(Struct);
GStrIdx StrIdx =
GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(TypeName);
MTy->SetNameStrIdx(StrIdx);
Module->GetTypeNameTab()->SetGStrIdxToTyIdx(StrIdx, MTy->GetTypeIndex());
Module->PushbackTypeDefOrder(StrIdx);
TypeMap[StructTy] = MTy->GetTypeIndex();
// If this record was referenced while it was incomplete, update the pointer
// type.
auto UT = UnresolvedTypes.find(Record);
if (UT != UnresolvedTypes.end()) {
UT->second->SetPointedTyIdx(MTy->GetTypeIndex());
}
return nullptr;
}
MIRSymbol *
Clang2MapleVisitor::VisitTypedefDecl(const clang::TypedefDecl *Typedef) {
return nullptr;
}
// Visit VarDecls
MIRSymbol *Clang2MapleVisitor::VisitVarDecl(const clang::VarDecl *Var) {
std::string Name = Var->getName().str();
if (Name[0] == '.') {
Name[0] = '_';
}
MIRType *Ty = type2Mpl(Var->getType());
MIRSymbol *Symbol;
if (Var->isLocalVarDecl()) {
if (Var->hasExternalStorage()) {
// If it is referring to an existing global, use it, else create it.
Symbol = Builder->GetGlobalDecl(Name);
if (!Symbol) {
Symbol = Builder->CreateGlobalDecl(Name, *Ty);
}
Symbol->SetAttr(ATTR_extern);
} else {
// If a local with this name already exists (from a different scope),
// append a number so that they are unique.
if (Builder->GetLocalDecl(Name)) {
Name = Name + "." + std::to_string(++UnnamedCount);
}
Symbol = Builder->CreateLocalDecl(Name, *Ty);
if (Var->isStaticLocal()) {
Symbol->SetStorageClass(kScPstatic);
if (Var->hasInit()) {
Initializer = true;
if (MIRConst *Init = getInitializer(Ty, Var->getInit())) {
Init = expandConstants(Ty, Init);
Symbol->SetKonst(Init);
}
Initializer = false;
}
}
}
if (Var->isUsed()) { // locals
Symbol->SetAttr(ATTR_used);
}
if (Var->isImplicit()) {
Symbol->SetAttr(ATTR_implicit);
}
} else { // Global
Symbol = Builder->GetOrCreateGlobalDecl(Name, *Ty);
if (Var->isThisDeclarationADefinition() || !Var->isKnownToBeDefined()) {
// Set the type here in case a previous declaration had an incomplete
// array type and the definition has the complete type.
Symbol->SetTyIdx(Ty->GetTypeIndex());
Symbol->SetStorageClass(StorageClass2Mpl(Var->getStorageClass()));
if (Var->hasInit()) {
Initializer = true;
if (MIRConst *Init = getInitializer(Ty, Var->getInit())) {
Init = expandConstants(Ty, Init);
Symbol->SetKonst(Init);
}
Initializer = false;
}
}
if (Var->isWeak()) {
Symbol->SetAttr(ATTR_weak);
}
if (Var->isUsed()) { // locals
Symbol->SetAttr(ATTR_used);
}
if (Var->isImplicit()) {
Symbol->SetAttr(ATTR_implicit);
}
}
if (Var->getType().isConstQualified()) {
Symbol->SetAttr(ATTR_const);
}
if (Var->getType().isRestrictQualified()) {
Symbol->SetAttr(ATTR_restrict);
}
if (Var->getType().isVolatileQualified()) {
Symbol->SetAttr(ATTR_volatile);
}
if (!Var->getType()->isIncompleteType()) {
int64_t NaturalAlignment =
Context
->toCharUnitsFromBits(
Context->getTypeUnadjustedAlign(Var->getType()))
.getQuantity();
// Get alignment from the decl
TypeAttrs Attrs = Symbol->GetAttrs();
if (unsigned int AlignmentBits = Var->getMaxAlignment()) {
unsigned int Alignment = AlignmentBits / BITS_PER_BYTE;
if (Alignment > NaturalAlignment) {
Attrs.SetAlign(Alignment);
}
}
// Get alignment from the type
if (unsigned int AlignmentBits =
Context->getTypeAlignIfKnown(Var->getType())) {
unsigned int Alignment = AlignmentBits / BITS_PER_BYTE;
if (Alignment > Attrs.GetAlign() && Alignment > NaturalAlignment) {
Attrs.SetAlign(Alignment);
}
}
Symbol->SetAttrs(Attrs);
}
if (isOneElementVector(Var->getType())) {
Symbol->SetAttr(ATTR_oneelem_simd);
}
if (const auto *PT = Var->getType()
.getDesugaredType(*Context)
->getAs<clang::PointerType>()) {
if (const auto FT = PT->getPointeeType()
.getDesugaredType(*Context)
->getAs<clang::FunctionType>()) {
if (isOneElementVector(FT->getReturnType())) {
Symbol->SetAttr(ATTR_oneelem_simd);
}
}
}
if (const auto *SA = Var->getAttr<clang::SectionAttr>()) {
UStrIdx StrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(
SA->getName().str());
Symbol->sectionAttr = StrIdx;
}
Symbol->SetSKind(kStVar);
SrcPosition Pos = sourceLocation2Mpl(Var->getLocation());
Symbol->SetSrcPosition(Pos);
DeclMap.insert({Var, Symbol});
return Symbol;
}
MIRSymbol *Clang2MapleVisitor::VisitParmVarDecl(const clang::ParmVarDecl *Var) {
MIRType *Ty = type2Mpl(Var->getType());
std::string Name = Var->getName().str();
if (Name.empty()) {
Name = "arg|" + std::to_string(Var->getFunctionScopeIndex());
}
if (Var->isKNRPromoted()) {
Name = Name + ".kr";
}
MIRSymbol *Symbol = Builder->GetOrCreateLocalDecl(Name, *Ty);
Symbol->SetStorageClass(kScFormal);
SrcPosition Pos = sourceLocation2Mpl(Var->getLocation());
Symbol->SetSrcPosition(Pos);
if (Var->isUsed()) {
Symbol->SetAttr(ATTR_used);
}
if (isOneElementVector(Var->getType())) {
Symbol->SetAttr(ATTR_oneelem_simd);
}
if (Var->getType().isConstQualified()) {
Symbol->SetAttr(ATTR_const);
}
if (Var->getType().isRestrictQualified()) {
Symbol->SetAttr(ATTR_restrict);
}
if (Var->getType().isVolatileQualified()) {
Symbol->SetAttr(ATTR_volatile);
}
DeclMap.insert({Var, Symbol});
return Symbol;
}
void
Clang2MapleVisitor::SetFunctionAttrs(MIRFunction *Func, const clang::FunctionDecl *Decl) {
if (Decl->isUsed()) {
Func->SetAttr(FUNCATTR_used);
}
if (Decl->isImplicit()) {
Func->SetAttr(FUNCATTR_implicit);
}
if (Decl->isInlineSpecified()) {
Func->SetAttr(FUNCATTR_inline);
} else if (Decl->hasAttr<clang::NoInlineAttr>()) {
Func->SetAttr(FUNCATTR_noinline);
}
if (Decl->isVariadic()) {
Func->SetAttr(FUNCATTR_varargs);
}
if (Decl->isNoReturn()) {
Func->SetAttr(FUNCATTR_noreturn);
}
if (Decl->isWeak()) {
Func->SetAttr(FUNCATTR_weak);
}
if (Decl->isStatic()) {
Func->SetAttr(FUNCATTR_static);
}
if (Decl->getStorageClass() == clang::SC_Extern) {
Func->SetAttr(FUNCATTR_extern);
}
if (isOneElementVector(Decl->getReturnType())) {
Func->SetAttr(FUNCATTR_oneelem_simd);
}
// C++ attributes
if (Decl->isVirtualAsWritten()) {
Func->SetAttr(FUNCATTR_virtual);
}
if (Decl->isDeletedAsWritten()) {
Func->SetAttr(FUNCATTR_delete);
}
if (Decl->isPure()) {
Func->SetAttr(FUNCATTR_pure);
}
if (Decl->isDefaulted()) {
Func->SetAttr(FUNCATTR_default);
}
if (Decl->getKind() == clang::Decl::CXXConstructor) {
Func->SetAttr(FUNCATTR_constructor);
}
if (Decl->getKind() == clang::Decl::CXXDestructor) {
Func->SetAttr(FUNCATTR_destructor);
}
}
MIRSymbol *
Clang2MapleVisitor::VisitFunctionDecl(const clang::FunctionDecl *Func) {
// Ignore Maple builtins' prototypes
if (Func->getName().startswith("__builtin")) {
return nullptr;
}
std::string Name = Func->getName().str();
if (Name[0] == '.') {
Name[0] = '_';
}
TyIdx FuncTyIdx = type2MplIdx(Func->getType());
MIRFuncType *FuncType = static_cast<MIRFuncType *>(
GlobalTables::GetTypeTable().GetTypeFromTyIdx(FuncTyIdx));
MIRSymbol *FuncSym = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
GStrIdx StrIdx = Builder->GetOrCreateStringIndex(Name);
FuncSym->SetNameStrIdx(StrIdx);
GlobalTables::GetGsymTable().AddToStringSymbolMap(*FuncSym);
FuncSym->SetStorageClass(kScText);
FuncSym->SetSKind(kStFunc);
SrcPosition Pos = sourceLocation2Mpl(Func->getLocation());
FuncSym->SetSrcPosition(Pos);
FuncSym->SetAppearsInCode(true);
MIRFunction *MFunc = Builder->GetCurrentFuncCodeMp()->New<MIRFunction>(
Module, FuncSym->GetStIdx());
MFunc->SetMIRFuncType(FuncType);
MIRType *RetTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(FuncType->GetRetTyIdx());
MIRType *OrigRetTy = type2Mpl(Func->getReturnType());
MFunc->SetReturnStruct(*RetTy);
MFunc->SetPuidx(GlobalTables::GetFunctionTable().GetFuncTable().size());
MFunc->SetPuidxOrigin(MFunc->GetPuidx());
SetFunctionAttrs(MFunc, Func);
if (Func->isVariadic()) {
MFunc->SetVarArgs();
}
GlobalTables::GetFunctionTable().GetFuncTable().push_back(MFunc);
FuncSym->SetTyIdx(FuncTyIdx);
FuncSym->SetFunction(MFunc);
if (Func->isWeak()) {
FuncSym->SetAttr(ATTR_weak);
}
MIRFunction *LastFunc = Module->CurFunction();
Module->SetCurFunction(MFunc);
Builder->SetCurrentFunction(*MFunc);
MFunc->AllocSymTab();
MFunc->AllocPregTab();
MFunc->AllocTypeNameTab();
MFunc->AllocLabelTab();
DeclMap.insert({Func, FuncSym});
unsigned int firstParam = 0;
if (OrigRetTy->GetSize() > 16) {
MFunc->SetFirstArgReturn();
firstParam = 1;
MIRType *RetAddrTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(
FuncType->GetNthParamType(0));
MIRSymbol *Symbol = Builder->GetOrCreateLocalDecl("retval.0", *RetAddrTy);
Symbol->SetStorageClass(kScFormal);
SrcPosition Pos = sourceLocation2Mpl(Func->getLocation());
Symbol->SetSrcPosition(Pos);
FormalDef RetVal(Symbol->GetNameStrIdx(), Symbol, RetAddrTy->GetTypeIndex(),
TypeAttrs());
MFunc->AddFormalDef(RetVal);
}
size_t NumParams = FuncType->GetParamTypeList().size();
for (uint32 i = firstParam; i < NumParams; i++) {
MIRSymbol *Param = Visit(Func->getParamDecl(i - firstParam));
Param->SetTyIdx(FuncType->GetNthParamType(i));
FormalDef FormalDef(Param->GetNameStrIdx(), Param,
FuncType->GetNthParamType(i),
FuncType->GetNthParamAttrs(i));
MFunc->AddFormalDef(FormalDef);
}
if (Func->isThisDeclarationADefinition() && Func->hasBody()) {
BlockNode *FuncBody = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
// Insert conversions for K&R style parameters
for (uint32 i = firstParam; i < NumParams; i++) {
const clang::ParmVarDecl *Parm = Func->getParamDecl(i - firstParam);
if (Parm->isKNRPromoted()) {
MIRType *ParmTy = type2Mpl(Parm->getType());
MIRType *KRTy = MFunc->GetNthParamType(i);
// Create a new local with the correct type.
MIRSymbol *ParmSym =
Builder->GetOrCreateLocalDecl(Parm->getNameAsString(), *ParmTy);
// Convert from the K&R type to the parameter's type.
StmtNode *ParmInit = Builder->CreateStmtDassign(
*ParmSym, 0,
createNumericCast(
ParmTy, Builder->CreateExprDread(
*KRTy, 0, *MFunc->GetFormalDefAt(i).formalSym)));
FuncBody->AddStatement(ParmInit);
// Update the map so that uses of the parameter use this new symbol.
DeclMap[Parm] = ParmSym;
}
}
// Insert function body
Result BodyRes = Visit(Func->getBody());
FuncBody->SetSrcPos(sourceLocation2Mpl(BodyRes.getLoc()));
BlockNode *Body = static_cast<BlockNode *>(BodyRes.getNode());
FuncBody->AppendStatementsFromBlock(*Body);
MFunc->SetBody(FuncBody);
if (VerifyMaple) {
ASSERT(FuncBody->Verify(), "Verify failed");
}
// If the last instruction of the body is not a return, add a return, with a
// zero value if there is a non-void return type.
if (!FuncBody->GetLast() || FuncBody->GetLast()->GetOpCode() != OP_return) {
BaseNode *RetVal = nullptr;
if (RetTy->GetPrimType() != PTY_void) {
if (PrimitiveType(RetTy->GetPrimType()).IsVector()) {
RetVal = createVectorZero(RetTy);
} else {
if (!RetTy->IsScalarType()) {
RetTy = GlobalTables::GetTypeTable().GetUInt32();
}
MIRConst *Zero = createZero(RetTy);
RetVal = Builder->CreateConstval(Zero);
}
}
NaryStmtNode *Return = Builder->CreateStmtReturn(RetVal);
Return->SetSrcPos(sourceLocation2Mpl(Func->getEndLoc()));
FuncBody->AddStatement(Return);
}
}
Module->AddFunction(MFunc);
Module->SetCurFunction(LastFunc);
return FuncSym;
}
MIRSymbol *Clang2MapleVisitor::VisitEnumDecl(const clang::EnumDecl *Enum) {
// Enums are just converted to constants when used, so do nothing here
return nullptr;
}
MIRSymbol *Clang2MapleVisitor::VisitEnumConstantDecl(
const clang::EnumConstantDecl *EnumConst) {
// Enums are just converted to constants when used, so do nothing here
return nullptr;
}
MIRSymbol *Clang2MapleVisitor::VisitFileScopeAsmDecl(
const clang::FileScopeAsmDecl *AsmDecl) {
MapleString AsmString(AsmDecl->getAsmString()->getString().str(),
Module->GetMemPool());
Module->GetAsmDecls().push_back(AsmString);
return nullptr;
}
//
// Visit Statements
//
Result Clang2MapleVisitor::VisitStmt(const clang::Stmt *S) {
LogInfo::MapleLogger() << "Error: Unhandled statement\n";
#ifdef DEBUG
S->dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
return Result(S->getBeginLoc());
}
Result Clang2MapleVisitor::VisitGCCAsmStmt(const clang::GCCAsmStmt *GAS) {
AsmNode *Asm = Builder->GetCurrentFuncCodeMp()->New<AsmNode>(
Builder->GetCurrentFuncCodeMpAllocator());
Result Res(Asm, GAS->getID(*Context), GAS->getBeginLoc());
Asm->asmString = MapleString(GAS->generateAsmString(*Context),
Builder->GetCurrentFuncCodeMp());
// Inputs
for (unsigned int InNum = 0; InNum < GAS->getNumInputs(); InNum++) {
Result InRes = Visit(GAS->getInputExpr(InNum));
BaseNode *InNode = nullptr;
if (GAS->getInputConstraint(InNum).contains('m')) {
InNode = getNodeAsAddrOf(InRes);
} else {
InNode = getNodeAsRVal(InRes);
}
Asm->PushOpnd(InNode);
Res.appendStmts(InRes);
UStrIdx StrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(
GAS->getInputConstraint(InNum).str());
Asm->inputConstraints.push_back(StrIdx);
}
// Outputs
for (unsigned int OutNum = 0; OutNum < GAS->getNumOutputs(); OutNum++) {
Result OutRes = Visit(GAS->getOutputExpr(OutNum));
MIRSymbol *Sym = nullptr;
if (OutRes.isSym()) {
Sym = OutRes.getSym();
}
if (!Sym || !Sym->IsLocal()) {
// Generate a temporary for the output, then assign that to the original
// expression after the asm node.
Sym = Builder->GetOrCreateLocalDecl(
"_asmout_" + std::to_string(GAS->getID(*Context)) + "_" +
std::to_string(OutNum),
*OutRes.getValueTy());
Sym->SetAttrs(OutRes.getValueTyAttrs());
StmtNode *Assign = nullptr;
// If this is a read/write, copy the initial value into the temp before
// the asm node.
if (GAS->isOutputPlusConstraint(OutNum)) {
Assign = Builder->CreateStmtDassign(*Sym, 0, getNodeAsRVal(OutRes));
Assign->SetSrcPos(sourceLocation2Mpl(GAS->getBeginLoc()));
Res.appendStmtBefore(Assign);
}
BaseNode *ReadTmp = Builder->CreateExprDread(*OutRes.getValueTy(), *Sym);
if (OutRes.isSym()) {
Assign = Builder->CreateStmtDassign(*OutRes.getSym(), OutRes.getField(),
ReadTmp);
} else if (OutRes.isDeref()) {
Assign = Builder->CreateStmtIassign(
*OutRes.getAddrTy(), OutRes.getField(), OutRes.getAddr(), ReadTmp);
} else {
getNodeAsRVal(OutRes)->Dump();
ASSERT(OutRes.isDeref() || OutRes.isSym(),
"Error: output of asm is neither deref or symbol");
}
Assign->SetSrcPos(sourceLocation2Mpl(GAS->getBeginLoc()));
Res.appendStmtAfter(Assign);
}
CallReturnPair OutPair(Sym->GetStIdx(), RegFieldPair(OutRes.getField(), 0));
Asm->asmOutputs.push_back(OutPair);
UStrIdx StrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(
GAS->getOutputConstraint(OutNum).str());
Asm->outputConstraints.push_back(StrIdx);
// Outputs with '+' are also added to the input list
if (GAS->isOutputPlusConstraint(OutNum)) {
BaseNode *InNode = Builder->CreateExprDread(*OutRes.getValueTy(), *Sym);
Asm->PushOpnd(InNode);
Asm->inputConstraints.push_back(StrIdx);
}
}
// Clobbers
for (unsigned int C = 0; C < GAS->getNumClobbers(); C++) {
UStrIdx StrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(
GAS->getClobber(C).str());
Asm->clobberList.push_back(StrIdx);
}
// Labels
for (unsigned int L = 0; L < GAS->getNumLabels(); L++) {
LabelIdx Label = Builder->GetOrCreateMIRLabel(GAS->getLabelName(L).str());
Asm->gotoLabels.push_back(Label);
}
if (GAS->isVolatile())
Asm->SetQualifier(kASMvolatile);
if (GAS->isAsmGoto())
Asm->SetQualifier(kASMgoto);
return Res;
}
Result Clang2MapleVisitor::VisitCompoundStmt(const clang::CompoundStmt *CS) {
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
for (clang::Stmt *S : CS->body()) {
Result Res = Visit(S);
addToBlock(Block, Res);
}
return Result(Block, CS->getID(*Context), CS->getBeginLoc());
}
Result Clang2MapleVisitor::VisitDeclStmt(const clang::DeclStmt *DS) {
Result Res(DS->getBeginLoc());
for (const auto *D : DS->decls()) {
MIRSymbol *Sym = Visit(D);
if (const clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(D)) {
if (VD->isLocalVarDecl() && !VD->isStaticLocal()) {
// Handle allocating stack space for a variable-length array
if (const clang::VariableArrayType *VarArrTy =
llvm::dyn_cast<clang::VariableArrayType>(VD->getType())) {
Result VLASizeRes = Visit(VarArrTy->getSizeExpr());
BaseNode *AllocaSize = getNodeAsRVal(VLASizeRes);
if (GetPrimTypeSize(AllocaSize->GetPrimType()) != GetPrimTypeSize(IntPointerTy->GetPrimType())) {
AllocaSize = Builder->CreateExprTypeCvt(OP_cvt, IntPointerTy->GetPrimType(), AllocaSize->GetPrimType(), *AllocaSize);
}
Res.appendStmts(VLASizeRes);
MIRType *Ty = type2Mpl(VD->getType());
size_t Scale =
static_cast<MIRPtrType *>(Ty)->GetPointedType()->GetSize();
if (Scale > 1) { // Skip multiplication for 1 (char) and 0 (void)
ConstvalNode *Const = Builder->CreateIntConst(Scale, PointerPrimTy);
AllocaSize = Builder->CreateExprBinary(OP_mul, *IntPointerTy,
AllocaSize, Const);
}
BaseNode *Alloca =
Builder->CreateExprUnary(OP_alloca, *Ty, AllocaSize);
Alloca->SetPrimType(PointerPrimTy);
StmtNode *Assign = Builder->CreateStmtDassign(*Sym, 0, Alloca);
Res.appendStmtAfter(Assign);
}
// Handle initialization
if (VD->hasInit()) {
const clang::Expr *InitExpr = VD->getInit();
Result InitRes = Visit(InitExpr);
BaseNode *Init = getNodeAsRVal(InitRes);
Res.appendStmts(InitRes);
if (!Init) {
continue;
}
if (Sym->GetType()->GetKind() == kTypeStruct ||
Sym->GetType()->GetKind() == kTypeUnion) {
MIRStructType *StructTy =
static_cast<MIRStructType *>(Sym->GetType());
assignStruct(Res, Sym, nullptr, StructTy, Init);
} else if (Sym->GetType()->GetKind() == kTypeArray) {
MIRArrayType *ArrayTy = static_cast<MIRArrayType *>(Sym->GetType());
AddrofNode *BaseAddr = Builder->CreateExprAddrof(0, *Sym);
BaseAddr->SetPrimType(PointerPrimTy);
assignArray(Res, BaseAddr, ArrayTy, Init);
} else if (PrimitiveType(Sym->GetType()->GetPrimType()).IsVector()) {
assignVector(Res, Sym, Sym->GetType(), Init);
} else {
DassignNode *Assign =
Builder->CreateStmtDassign(Sym->GetStIdx(), 0, Init);
Assign->SetSrcPos(sourceLocation2Mpl(DS->getBeginLoc()));
Res.appendStmtBefore(Assign);
}
}
}
} else if (llvm::isa<clang::TypedefDecl>(D)) {
// Safely ignore typedefs
return Res;
} else {
LogInfo::MapleLogger() << "Warning: Non-VarDecl in DeclStmt\n";
D->dump();
}
}
return Res;
}
Result Clang2MapleVisitor::VisitDoStmt(const clang::DoStmt *Do) {
WhileStmtNode *WhileNode =
Builder->GetCurrentFuncCodeMp()->New<WhileStmtNode>(OP_dowhile);
Result Res(WhileNode, Do->getID(*Context), Do->getDoLoc());
Result Cond = Visit(Do->getCond());
WhileNode->SetRHS(exprToCond(getNodeAsRVal(Cond)));
LabelIdx EndLabel =
Builder->GetOrCreateMIRLabel("L_END" + std::to_string(++UnnamedCount));
LabelIdx ExitLabel =
Builder->GetOrCreateMIRLabel("L_EXIT" + std::to_string(++UnnamedCount));
EndLabels.push(LabelInfo(EndLabel));
ExitLabels.push(LabelInfo(ExitLabel));
const clang::Stmt *BodyStmt = Do->getBody();
Result BodyRes = Visit(BodyStmt);
if (llvm::isa<clang::CompoundStmt>(BodyStmt)) {
WhileNode->SetBody(static_cast<BlockNode *>(BodyRes.getNode()));
} else {
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
addToBlock(Block, BodyRes);
WhileNode->SetBody(Block);
}
// Add an end label, if needed, to the end of the body
LabelInfo End = EndLabels.top();
if (End.Used) {
StmtNode *EndLabelStmt = Builder->CreateStmtLabel(End.Label);
EndLabelStmt->SetSrcPos(sourceLocation2Mpl(Do->getEndLoc()));
WhileNode->GetBody()->AddStatement(EndLabelStmt);
}
EndLabels.pop();
// The condition is called on every iteration of the loop, so if there are any
// statements that must run before the condition expression, insert them at
// the end of the loop.
Cond = Visit(Do->getCond());
getNodeAsRVal(Cond);
for (Result::iterator It = Cond.beginStmtsBefore();
It != Cond.endStmtsBefore(); ++It) {
WhileNode->GetBody()->AddStatement(*It);
}
// Add an exit label, if needed, after this loop
LabelInfo Exit = ExitLabels.top();
if (Exit.Used) {
StmtNode *ExitLabelStmt = Builder->CreateStmtLabel(Exit.Label);
ExitLabelStmt->SetSrcPos(sourceLocation2Mpl(Do->getEndLoc()));
Res.appendStmtAfter(ExitLabelStmt);
}
ExitLabels.pop();
return Res;
}
Result Clang2MapleVisitor::VisitForStmt(const clang::ForStmt *For) {
WhileStmtNode *WhileNode =
Builder->GetCurrentFuncCodeMp()->New<WhileStmtNode>(OP_while);
Result Res(WhileNode, For->getID(*Context), For->getForLoc());
const clang::Stmt *InitStmt = For->getInit();
const clang::Expr *CondExpr = For->getCond();
const clang::Expr *IncExpr = For->getInc();
if (InitStmt) {
Result Init = Visit(InitStmt);
Res.appendStmts(Init);
if (!Init.mayDrop()) {
StmtNode *SNode = getNodeAsStmt(Init);
Res.appendStmtBefore(SNode);
}
}
Result Cond(CondExpr ? CondExpr->getBeginLoc() : For->getForLoc());
if (CondExpr) {
Cond = Visit(CondExpr);
WhileNode->SetRHS(exprToCond(getNodeAsRVal(Cond)));
Res.appendStmts(Cond);
} else {
// If condition is null, create a constant 1 for the condition.
WhileNode->SetRHS(Builder->CreateIntConst(1, PTY_i32));
}
LabelIdx EndLabel =
Builder->GetOrCreateMIRLabel("L_END" + std::to_string(++UnnamedCount));
LabelIdx ExitLabel =
Builder->GetOrCreateMIRLabel("L_EXIT" + std::to_string(++UnnamedCount));
EndLabels.push(LabelInfo(EndLabel));
ExitLabels.push(LabelInfo(ExitLabel));
const clang::Stmt *BodyStmt = For->getBody();
Result BodyRes = Visit(BodyStmt);
if (llvm::isa<clang::CompoundStmt>(BodyStmt)) {
WhileNode->SetBody(static_cast<BlockNode *>(BodyRes.getNode()));
} else {
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
addToBlock(Block, BodyRes);
WhileNode->SetBody(Block);
}
// Add an end label, if needed, to the end of the body
LabelInfo End = EndLabels.top();
if (End.Used) {
StmtNode *EndLabelStmt = Builder->CreateStmtLabel(End.Label);
EndLabelStmt->SetSrcPos(sourceLocation2Mpl(For->getEndLoc()));
WhileNode->GetBody()->AddStatement(EndLabelStmt);
}
EndLabels.pop();
if (IncExpr) {
Result Inc = Visit(IncExpr);
addToBlock(WhileNode->GetBody(), Inc);
}
// The condition is called on every iteration of the loop, so if there are any
// statements that must run before the condition expression, insert them at
// the end of the loop.
if (CondExpr) {
Cond = Visit(CondExpr);
getNodeAsRVal(Cond);
for (Result::iterator It = Cond.beginStmtsBefore();
It != Cond.endStmtsBefore(); ++It) {
WhileNode->GetBody()->AddStatement(*It);
}
}
// Add an exit label, if needed, after this loop
LabelInfo Exit = ExitLabels.top();
if (Exit.Used) {
StmtNode *ExitLabelStmt = Builder->CreateStmtLabel(Exit.Label);
ExitLabelStmt->SetSrcPos(sourceLocation2Mpl(For->getEndLoc()));
Res.appendStmtAfter(ExitLabelStmt);
}
ExitLabels.pop();
return Res;
}
Result Clang2MapleVisitor::VisitIfStmt(const clang::IfStmt *If) {
Result Cond = Visit(If->getCond());
IfStmtNode *IfNode = Builder->CreateStmtIf(exprToCond(getNodeAsRVal(Cond)));
Result Res(IfNode, If->getID(*Context), If->getBeginLoc());
Res.appendStmts(Cond);
const clang::Stmt *ThenStmt = If->getThen();
Result Then = Visit(ThenStmt);
if (llvm::isa<clang::CompoundStmt>(ThenStmt)) {
IfNode->SetThenPart(static_cast<BlockNode *>(Then.getNode()));
} else {
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
addToBlock(Block, Then);
IfNode->SetThenPart(Block);
}
const clang::Stmt *ElseStmt = If->getElse();
if (ElseStmt) {
Result Else = Visit(ElseStmt);
if (llvm::isa<clang::CompoundStmt>(ElseStmt)) {
IfNode->SetElsePart(static_cast<BlockNode *>(Else.getNode()));
} else {
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
addToBlock(Block, Else);
IfNode->SetElsePart(Block);
}
}
return Res;
}
Result Clang2MapleVisitor::VisitNullStmt(const clang::NullStmt *N) {
return Result(N->getBeginLoc());
}
Result Clang2MapleVisitor::VisitReturnStmt(const clang::ReturnStmt *Return) {
Result RetValRes(Return->getReturnLoc());
Result Res(Return->getReturnLoc());
BaseNode *RetVal = nullptr;
if (const clang::Expr *E = Return->getRetValue()) {
RetValRes = Visit(E);
Res.appendStmts(RetValRes);
if (E->getType()->isVoidType()) {
Res.appendStmtBefore(getNodeAsStmt(RetValRes));
} else {
RetVal = getNodeAsRVal(RetValRes);
Res.appendStmts(RetValRes);
}
} else if (Builder->GetCurrentFunction()->GetReturnType()->GetPrimType() !=
PTY_void) {
// Handle a return statement with no expression in a function that has a
// non-void return type.
RetVal = Builder->CreateConstval(
createZero(Builder->GetCurrentFunction()->GetReturnType()));
}
StmtNode *Ret = nullptr;
// If the address of a return structure has been passed as an implicit
// parameter, write the return value to it, otherwise, generate a return
// statement.
if (Builder->GetCurrentFunction()->IsFirstArgReturn()) {
FormalDef RetAddr = Builder->GetCurrentFunction()->GetFormalDefAt(0);
MIRType *RetTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(RetAddr.formalTyIdx);
StmtNode *Assign = Builder->CreateStmtIassign(
*RetTy, 0, Builder->CreateExprDread(*RetTy, *RetAddr.formalSym),
RetVal);
Assign->SetSrcPos(sourceLocation2Mpl(Return->getReturnLoc()));
Res.appendStmtBefore(Assign);
Ret = Builder->CreateStmtReturn(nullptr);
} else {
Ret = Builder->CreateStmtReturn(RetVal);
}
Res.setNode(Ret, Return->getID(*Context));
return Res;
}
Result Clang2MapleVisitor::VisitWhileStmt(const clang::WhileStmt *While) {
WhileStmtNode *WhileNode =
Builder->GetCurrentFuncCodeMp()->New<WhileStmtNode>(OP_while);
Result Res(WhileNode, While->getID(*Context), While->getWhileLoc());
Result Cond = Visit(While->getCond());
WhileNode->SetRHS(exprToCond(getNodeAsRVal(Cond)));
Res.appendStmts(Cond);
LabelIdx EndLabel =
Builder->GetOrCreateMIRLabel("L_END" + std::to_string(++UnnamedCount));
LabelIdx ExitLabel =
Builder->GetOrCreateMIRLabel("L_EXIT" + std::to_string(++UnnamedCount));
EndLabels.push(LabelInfo(EndLabel));
ExitLabels.push(LabelInfo(ExitLabel));
const clang::Stmt *BodyStmt = While->getBody();
Result BodyRes = Visit(BodyStmt);
if (llvm::isa<clang::CompoundStmt>(BodyStmt)) {
WhileNode->SetBody(static_cast<BlockNode *>(BodyRes.getNode()));
} else {
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
addToBlock(Block, BodyRes);
WhileNode->SetBody(Block);
}
// Add an end label, if needed, to the end of the body
LabelInfo End = EndLabels.top();
if (End.Used) {
StmtNode *EndLabelStmt = Builder->CreateStmtLabel(End.Label);
EndLabelStmt->SetSrcPos(sourceLocation2Mpl(While->getEndLoc()));
WhileNode->GetBody()->AddStatement(EndLabelStmt);
}
EndLabels.pop();
// The condition is called on every iteration of the loop, so if there are any
// statements that must run before the condition expression, insert them at
// the end of the loop.
Cond = Visit(While->getCond());
getNodeAsRVal(Cond);
for (Result::iterator It = Cond.beginStmtsBefore();
It != Cond.endStmtsBefore(); ++It) {
WhileNode->GetBody()->AddStatement(*It);
}
// Add an exit label, if needed, after this loop
LabelInfo Exit = ExitLabels.top();
if (Exit.Used) {
StmtNode *ExitLabelStmt = Builder->CreateStmtLabel(Exit.Label);
ExitLabelStmt->SetSrcPos(sourceLocation2Mpl(While->getEndLoc()));
Res.appendStmtAfter(ExitLabelStmt);
}
ExitLabels.pop();
return Res;
}
Result Clang2MapleVisitor::VisitBreakStmt(const clang::BreakStmt *BS) {
ASSERT(ExitLabels.size() > 0, "'break' outside of known loop or switch");
LabelInfo &LI = ExitLabels.top();
LI.Used = true;
GotoNode *GoTo = Builder->CreateStmtGoto(OP_goto, LI.Label);
return Result(GoTo, BS->getID(*Context), BS->getBreakLoc());
}
Result Clang2MapleVisitor::VisitContinueStmt(const clang::ContinueStmt *CS) {
ASSERT(EndLabels.size() > 0, "'continue' outside of known loop");
LabelInfo &LI = EndLabels.top();
LI.Used = true;
GotoNode *GoTo = Builder->CreateStmtGoto(OP_goto, LI.Label);
return Result(GoTo, CS->getID(*Context), CS->getContinueLoc());
}
Result Clang2MapleVisitor::VisitLabelStmt(const clang::LabelStmt *LS) {
LabelIdx Label = Builder->GetOrCreateMIRLabel(LS->getName());
StmtNode *LabelStmt = Builder->CreateStmtLabel(Label);
LabelStmt->SetSrcPos(sourceLocation2Mpl(LS->getIdentLoc()));
Result SubExprRes = Visit(LS->getSubStmt());
SubExprRes.prependStmtBefore(LabelStmt);
return SubExprRes;
}
Result Clang2MapleVisitor::VisitGotoStmt(const clang::GotoStmt *Goto) {
LabelIdx Label =
Builder->GetOrCreateMIRLabel(Goto->getLabel()->getName().str());
StmtNode *GotoStmt = Builder->CreateStmtGoto(OP_goto, Label);
return Result(GotoStmt, Goto->getID(*Context), Goto->getGotoLoc());
}
Result
Clang2MapleVisitor::VisitIndirectGotoStmt(const clang::IndirectGotoStmt *Goto) {
Result TargetRes = Visit(Goto->getTarget());
BaseNode *Target = getNodeAsRVal(TargetRes);
StmtNode *GotoStmt = Builder->GetCurrentFuncCodeMp()->New<UnaryStmtNode>(
OP_igoto, PointerPrimTy, Target);
Result Res(GotoStmt, Goto->getID(*Context), Goto->getGotoLoc());
Res.appendStmts(TargetRes);
return Res;
}
Result Clang2MapleVisitor::VisitSwitchStmt(const clang::SwitchStmt *Switch) {
Result CondRes = Visit(Switch->getCond());
CaseVector *Cases = Builder->GetCurrentFuncCodeMp()->New<CaseVector>(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
SwitchCases.push(Cases);
LabelIdx DefaultLabel = Builder->GetOrCreateMIRLabel(
"L_DEFAULT" + std::to_string(++UnnamedCount));
LabelIdx BreakLabel =
Builder->GetOrCreateMIRLabel("L_BREAK" + std::to_string(++UnnamedCount));
DefaultLabels.push(LabelInfo(DefaultLabel));
ExitLabels.push(LabelInfo(BreakLabel));
const clang::Stmt *BodyStmt = Switch->getBody();
Result BodyRes = Visit(BodyStmt);
// Generate a temporary for the switch condition
MIRSymbol *Temp = Builder->GetOrCreateLocalDecl(
"_switch." + std::to_string(Switch->getID(*Context)),
*CondRes.getValueTy());
StmtNode *TempAssign =
Builder->CreateStmtDassign(*Temp, 0, getNodeAsRVal(CondRes));
TempAssign->SetSrcPos(sourceLocation2Mpl(CondRes.getLoc()));
BaseNode *ReadCond = Builder->CreateExprDread(*CondRes.getValueTy(), *Temp);
SwitchNode *SwitchStmt =
Builder->CreateStmtSwitch(ReadCond, DefaultLabel, *Cases);
Result Res(SwitchStmt, Switch->getID(*Context), Switch->getSwitchLoc());
// Add statements that need to run before the switch, from the condition.
for (Result::iterator It = CondRes.beginStmtsBefore();
It != CondRes.endStmtsBefore(); ++It) {
Res.appendStmtBefore(*It);
}
Res.appendStmtBefore(TempAssign);
// Add the body after the switch.
if (llvm::isa<clang::CompoundStmt>(BodyStmt)) {
BlockNode *BodyBlock = static_cast<BlockNode *>(BodyRes.getNode());
for (auto &Stmt : BodyBlock->GetStmtNodes()) {
Res.appendStmtAfter(&Stmt);
}
} else {
StmtNode *SNode = getNodeAsStmt(BodyRes);
Res.appendStmtAfter(SNode);
}
Res.appendStmts(BodyRes);
// If there was no default case, add the label.
LabelInfo &DefaultLI = DefaultLabels.top();
if (!DefaultLI.Used) {
StmtNode *DefaultStmt = Builder->CreateStmtLabel(DefaultLI.Label);
DefaultStmt->SetSrcPos(sourceLocation2Mpl(Switch->getSwitchLoc()));
Res.appendStmtAfter(DefaultStmt);
}
// If there were any breaks in the body, add the label for the exit.
LabelInfo &ExitLI = ExitLabels.top();
if (ExitLI.Used) {
StmtNode *ExitLabelStmt = Builder->CreateStmtLabel(ExitLI.Label);
ExitLabelStmt->SetSrcPos(sourceLocation2Mpl(Switch->getEndLoc()));
Res.appendStmtAfter(ExitLabelStmt);
}
SwitchCases.pop();
DefaultLabels.pop();
ExitLabels.pop();
return Res;
}
Result Clang2MapleVisitor::VisitCaseStmt(const clang::CaseStmt *CS) {
LabelIdx Label =
Builder->GetOrCreateMIRLabel("L_CASE" + std::to_string(++UnnamedCount));
StmtNode *LabelStmt = Builder->CreateStmtLabel(Label);
LabelStmt->SetSrcPos(sourceLocation2Mpl(CS->getCaseLoc()));
clang::Expr::EvalResult Constant;
bool IsConstant = CS->getLHS()->EvaluateAsConstantExpr(Constant, *Context);
ASSERT(IsConstant, "case statement expression is not constant");
if (!Constant.Val.isInt()) {
LogInfo::MapleLogger() << "Error: Constant.Val in case statement is "
<< Constant.Val.getKind() << "\n";
Constant.Val.dump();
}
llvm::APSInt Value = Constant.Val.getInt();
ASSERT(SwitchCases.size() > 0, "'case' outside of known switch");
CaseVector *Cases = SwitchCases.top();
Cases->push_back(CasePair(Value.getExtValue(), Label));
Result Body = Visit(CS->getSubStmt());
Body.prependStmtBefore(LabelStmt);
return Body;
}
Result Clang2MapleVisitor::VisitDefaultStmt(const clang::DefaultStmt *DS) {
ASSERT(DefaultLabels.size() > 0, "'default' outside of known switch");
LabelInfo &LI = DefaultLabels.top();
StmtNode *DefaultStmt = Builder->CreateStmtLabel(LI.Label);
DefaultStmt->SetSrcPos(sourceLocation2Mpl(DS->getDefaultLoc()));
LI.Used = true;
Result Body = Visit(DS->getSubStmt());
Body.prependStmtBefore(DefaultStmt);
return Body;
}
//
// Visit Expressions
//
Result Clang2MapleVisitor::Visit(const clang::Stmt *S) {
if (const clang::Expr *E = clang::dyn_cast<clang::Expr>(S)) {
MIRType *ResTy = type2Mpl(E->getType());
if (MIRConst *Const = evaluateExprAsConst(E, ResTy)) {
// If this is not in an initializer, set the type to a register-sized
// type.
if (!Initializer && Const->GetKind() == kConstInt) {
MIRIntConst *IConst = static_cast<MIRIntConst *>(Const);
PrimType PTy = Const->GetType().GetPrimType();
PrimType RegPTy = GetRegPrimType(PTy);
if (RegPTy != PTy) {
Const = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
IsSignedInteger(PTy) ? IConst->GetValue().GetSXTValue() : IConst->GetValue().GetZXTValue(),
*GlobalTables::GetTypeTable().GetPrimType(RegPTy));
}
}
BaseNode *N = Builder->CreateConstval(Const);
Result Res(N, E->getID(*Context), E->getBeginLoc(), ResTy);
return Res;
}
}
return clang::ConstStmtVisitor<Clang2MapleVisitor, Result>::Visit(S);
}
Result Clang2MapleVisitor::VisitAddrLabelExpr(const clang::AddrLabelExpr *ALE) {
LabelIdx Label =
Builder->GetOrCreateMIRLabel(ALE->getLabel()->getName().str());
AddroflabelNode *AOL =
Builder->GetCurrentFuncCodeMp()->New<AddroflabelNode>(Label);
AOL->SetPrimType(PointerPrimTy);
return Result(AOL, ALE->getID(*Context), ALE->getAmpAmpLoc(),
type2Mpl(ALE->getType()));
}
Result Clang2MapleVisitor::VisitArraySubscriptExpr(
const clang::ArraySubscriptExpr *ASE) {
MIRType *Ty = type2Mpl(ASE->getType());
Result BaseRes = Visit(ASE->getBase());
Result IdxRes = Visit(ASE->getIdx());
BaseNode *Idx = getNodeAsRVal(IdxRes);
MIRType *IdxTy = GlobalTables::GetTypeTable().GetPrimType(
GetRegPrimType(Idx->GetPrimType()));
Idx = createNumericCast(IdxTy, Idx);
ArrayNode *Array;
#ifdef MULTIDIM_ARRAYS
// If this is a multi-dimensional array subscript (ex. x[3][4]), append to the
// existing array node. Do not use multi-dimensional array subscripting when
// accessing through a pointer, or when accessing a field of the array
// element.
BaseNode *ArrBase = BaseRes.getNode();
if (ArrBase && ArrBase->GetOpCode() == OP_array &&
BaseRes.getValueTy()->GetKind() == kTypeArray &&
BaseRes.getField() == 0) {
Array = static_cast<ArrayNode *>(ArrBase);
MapleVector<BaseNode *> &Opnds = Array->GetNopnd();
Opnds.push_back(Idx);
Array->SetNumOpnds(Opnds.size());
} else {
#endif // MULTIDIM_ARRAYS
// Get the base array type from the base expression, ignoring the implicit
// array-to-pointer decay cast
MIRType *ArrayTy = type2Mpl(ASE->getBase()->IgnoreImpCasts()->getType());
if (ArrayTy->GetKind() == kTypePointer) {
MIRPtrType *PointerTy = static_cast<MIRPtrType *>(ArrayTy);
MIRType *PointeeTy = PointerTy->GetPointedType();
#ifdef MULTIDIM_ARRAYS
if (PointeeTy->GetKind() == kTypeArray) {
MIRArrayType *PointeeArrTy = static_cast<MIRArrayType *>(PointeeTy);
std::vector<maple::uint32> SizeArray{1};
for (size_t d = 0; d < PointeeArrTy->GetDim(); d++) {
SizeArray.push_back(PointeeArrTy->GetSizeArrayItem(d));
}
MIRArrayType NewArrTy(PointeeArrTy->GetElemTyIdx(), SizeArray);
ArrayTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(NewArrTy));
} else {
#endif // MULTIDIM_ARRAYS
ArrayTy =
GlobalTables::GetTypeTable().GetOrCreateArrayType(*PointeeTy, 1);
#ifdef MULTIDIM_ARRAYS
}
#endif // MULTIDIM_ARRAYS
}
// If this is an access of a 0-size array, change the type to be a 1-size
// array.
if (ArrayTy->GetKind() == kTypeArray) {
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(ArrayTy);
if (ArrTy->GetSizeArrayItem(0) == 0) {
std::vector<maple::uint32> SizeArray{1};
for (size_t d = 1; d < ArrTy->GetDim(); d++) {
SizeArray.push_back(ArrTy->GetSizeArrayItem(d));
}
MIRArrayType NewArrTy(ArrTy->GetElemTyIdx(), SizeArray);
ArrayTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(NewArrTy));
}
}
Array = Builder->CreateExprArray(*ArrayTy, getNodeAsRVal(BaseRes), Idx);
Array->SetBoundsCheck(false);
Array->SetPrimType(PointerPrimTy);
#ifdef MULTIDIM_ARRAYS
}
#endif // MULTIDIM_ARRAYS
Result Res(Array, ASE->getID(*Context), type2Mpl(ASE->getBase()->getType()),
Ty, ASE->getBeginLoc());
Res.appendStmts(BaseRes);
Res.appendStmts(IdxRes);
return Res;
}
int Clang2MapleVisitor::typeRank(PrimType PTy) {
switch (PTy) {
case PTY_i8:
case PTY_i16:
case PTY_i32:
return 0;
case PTY_u1:
case PTY_u8:
case PTY_u16:
case PTY_u32:
return 1;
case PTY_a32:
return 2;
case PTY_i64:
return 3;
case PTY_u64:
return 4;
case PTY_a64:
return 5;
case PTY_ptr:
case PTY_ref:
return PointerPrimTy == PTY_a32 ? 2 : 4;
case PTY_f32:
return 6;
case PTY_f64:
return 7;
case PTY_f128:
return 8;
default:
return -1;
}
}
PrimType Clang2MapleVisitor::typeOfOperation(PrimType PTy1, PrimType PTy2) {
static PrimType RankPrimTy[] = {PTY_i32, PTY_u32, PTY_a32, PTY_i64, PTY_u64,
PTY_a64, PTY_f32, PTY_f64, PTY_f128};
int R1, R2, Rank;
R1 = typeRank(PTy1);
R2 = typeRank(PTy2);
Rank = std::max(R1, R2);
if (Rank < 0)
return PTy1;
return RankPrimTy[Rank];
}
Result
Clang2MapleVisitor::VisitBinaryOperator(const clang::BinaryOperator *BO) {
Result Lhs = Visit(BO->getLHS());
Result Rhs = Visit(BO->getRHS());
MIRType *Ty = type2Mpl(BO->getType());
StmtNode *Assign = nullptr;
// Assignments need to be handled differently from the other operators
if (BO->isAssignmentOp()) {
Result Res(BO->getExprLoc());
BaseNode *RhsNode = getNodeAsRVal(Rhs);
bool CompoundAssign = false;
// For compound assignments, convert the RHS to LHS op RHS
if (auto CAO = llvm::dyn_cast<clang::CompoundAssignOperator>(BO)) {
CompoundAssign = true;
bool isSigned = BO->getType()->isSignedIntegerType();
Opcode Op = BinOpcode2Mpl(BO->getOpcode(), isSigned);
if (Op == OP_undef) {
LogInfo::MapleLogger()
<< "Error: Unhandled opcode in binary operator: " << BO->getOpcode()
<< "\n";
CHECK_FATAL(false, "Failing due to unsupported feature");
}
MIRType *ResultTy = type2Mpl(CAO->getComputationResultType());
MIRType *LhsTy = type2Mpl(CAO->getComputationLHSType());
BaseNode *LhsOp = getNodeAsRVal(Lhs);
if (Lhs.getValueTy() != LhsTy) {
LhsOp = createNumericCast(LhsTy, LhsOp);
}
// If this is addition or subtraction of a pointer and an integer, the
// integer must be scaled to the size of the pointed-to type.
if (Op == OP_add || Op == OP_sub) {
if (isPointerType(LhsTy) && !isPointerType(Rhs.getValueTy())) {
size_t Scale = getPointedToSize(LhsTy);
if (Scale > 1) { // Skip multiplication for 1 (char) and 0 (void)
if (RhsNode->GetOpCode() == OP_constval) {
ConstvalNode *RhsConst = static_cast<ConstvalNode *>(RhsNode);
ASSERT(RhsConst->GetConstVal()->GetKind() == kConstInt,
"expected int const");
MIRIntConst *IntConst =
static_cast<MIRIntConst *>(RhsConst->GetConstVal());
int64_t Val = IntConst->GetValue().GetSXTValue();
RhsNode = Builder->CreateIntConst(Val * Scale, PointerPrimTy);
} else {
ConstvalNode *Const =
Builder->CreateIntConst(Scale, PointerPrimTy);
RhsNode = Builder->CreateExprBinary(
OP_mul, *IntPointerTy,
createNumericCast(IntPointerTy, RhsNode), Const);
}
}
}
}
RhsNode = Builder->CreateExprBinary(Op, *ResultTy, LhsOp,
createNumericCast(ResultTy, RhsNode));
if (ResultTy != Ty) {
RhsNode = createNumericCast(Ty, RhsNode);
}
}
BaseNode *N;
if (Lhs.isDeref()) {
Assign = Builder->CreateStmtIassign(*Lhs.getAddrTy(), Lhs.getField(),
Lhs.getAddr(), RhsNode);
if (CompoundAssign) {
N = Builder->CreateExprIread(*Lhs.getValueTy(), *Lhs.getAddrTy(),
Lhs.getField(), Lhs.getAddr());
}
} else if (Lhs.isSym()) {
Assign =
Builder->CreateStmtDassign(*Lhs.getSym(), Lhs.getField(), RhsNode);
if (CompoundAssign) {
N = Builder->CreateExprDread(*Lhs.getValueTy(), Lhs.getField(),
*Lhs.getSym());
}
} else {
BO->getLHS()->dump();
ASSERT(false, "Error: LHS of assign is neither deref or symbol");
}
Res.appendStmts(Rhs);
Res.appendStmts(Lhs);
if (CompoundAssign) {
Assign->SetSrcPos(sourceLocation2Mpl(BO->getExprLoc()));
Res.appendStmtBefore(Assign);
Res.setNode(N, BO->getID(*Context), Lhs.getValueTy(), TypeAttrs(), true);
} else {
Res.setNode(Assign, BO->getID(*Context), Ty);
}
return Res;
}
// Comma operator is also unique
if (BO->getOpcode() == clang::BO_Comma) {
Result Res(BO->getRHS()->getBeginLoc());
appendResultBefore(Res, Lhs);
Res.appendStmts(Rhs);
Res.setResult(Rhs);
return Res;
}
BaseNode *RhsNode = getNodeAsRVal(Rhs);
BaseNode *LhsNode = getNodeAsRVal(Lhs);
// For logical and/or, turn both left and right hand sides into conditional
// statements if needed.
if (BO->getOpcode() == clang::BO_LAnd || BO->getOpcode() == clang::BO_LOr) {
LhsNode = exprToCond(LhsNode);
RhsNode = exprToCond(RhsNode);
}
// For many binary operations, the types of the two operands must match. Cast
// the operands, if needed, to the appropriate type for the operation.
else if ((BO->getOpcode() >= clang::BO_Mul &&
BO->getOpcode() <= clang::BO_Sub) ||
(BO->getOpcode() >= clang::BO_LT &&
BO->getOpcode() <= clang::BO_LOr)) {
MIRType *OpTy = GlobalTables::GetTypeTable().GetPrimType(
typeOfOperation(LhsNode->GetPrimType(), RhsNode->GetPrimType()));
RhsNode = createNumericCast(OpTy, RhsNode);
LhsNode = createNumericCast(OpTy, LhsNode);
}
BaseNode *BinNode;
bool isSigned = BO->getType()->isSignedIntegerType();
Opcode Op = BinOpcode2Mpl(BO->getOpcode(), isSigned);
if (Op == OP_undef) {
LogInfo::MapleLogger() << "Error: Unhandled opcode in binary operator: "
<< BO->getOpcode() << "\n";
CHECK_FATAL(false, "Failing due to unsupported feature");
}
if ((Op == OP_cior || Op == OP_cand) &&
!(Rhs.isSimple() && useSimpleShortCircuit())) {
// Handle C's short-circuiting rules:
// x || y;
// becomes:
// _shortcircuit.0 = x;
// if (_shortcircuit.0) goto L0;
// _shortcircuit.0 = y;
// L0: _shortcircuit.0
Result Res(BO->getExprLoc());
MIRType *IntTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_i32));
// The label should be recreated if this node is visited multiple times, so
// use an iterative name.
LabelIdx LabelID = Builder->GetOrCreateMIRLabel(
"Lshortcircuit." + std::to_string(++UnnamedCount));
// The temporary variable should be reused if this node is visited multiple
// times, so use a stable name.
MIRSymbol *Temp = Builder->GetOrCreateLocalDecl(
"_shortcircuit." + std::to_string(BO->getID(*Context)), *IntTy);
Res.appendStmts(Lhs);
StmtNode *TempAssign =
Builder->CreateStmtDassign(*Temp, 0, exprToCond(LhsNode));
TempAssign->SetSrcPos(sourceLocation2Mpl(Lhs.getLoc()));
Res.appendStmtBefore(TempAssign);
CondGotoNode *Branch = Builder->CreateStmtCondGoto(
Builder->CreateExprDread(*IntTy, *Temp),
Op == OP_cior ? OP_brtrue : OP_brfalse, LabelID);
Branch->SetSrcPos(sourceLocation2Mpl(BO->getOperatorLoc()));
Res.appendStmtBefore(Branch);
Res.appendStmts(Rhs);
TempAssign = Builder->CreateStmtDassign(*Temp, 0, exprToCond(RhsNode));
TempAssign->SetSrcPos(sourceLocation2Mpl(Rhs.getLoc()));
Res.appendStmtBefore(TempAssign);
StmtNode *LabelStmt = Builder->CreateStmtLabel(LabelID);
LabelStmt->SetSrcPos(sourceLocation2Mpl(BO->getOperatorLoc()));
Res.appendStmtBefore(LabelStmt);
Res.setSym(Temp, IntTy, true);
return Res;
} else if (kOpcodeInfo.IsCompare(Op)) {
// Compare operators need two types
MIRType *OpndTy = type2Mpl(BO->getLHS()->getType());
BinNode = Builder->CreateExprCompare(Op, *Ty, *OpndTy, LhsNode, RhsNode);
} else {
MIRType *LhsTy = Lhs.getValueTy();
MIRType *RhsTy = Rhs.getValueTy();
// If this is addition or subtraction of a pointer and an integer, the
// integer must be scaled to the size of the pointed-to type.
if (Op == OP_add || Op == OP_sub) {
if (!isPointerType(LhsTy) && isPointerType(RhsTy)) {
size_t Scale = getPointedToSize(RhsTy);
if (Scale > 1) { // Skip multiplication for 1 (char) and 0 (void)
if (LhsNode->GetOpCode() == OP_constval) {
ConstvalNode *LhsConst = static_cast<ConstvalNode *>(LhsNode);
ASSERT(LhsConst->GetConstVal()->GetKind() == kConstInt,
"expected int const");
MIRIntConst *IntConst =
static_cast<MIRIntConst *>(LhsConst->GetConstVal());
int64_t Val = IntConst->GetValue().GetSXTValue();
LhsNode = Builder->CreateIntConst(Val * Scale, PointerPrimTy);
} else {
ConstvalNode *Const = Builder->CreateIntConst(Scale, PointerPrimTy);
LhsNode = Builder->CreateExprBinary(OP_mul, *IntPointerTy, LhsNode,
Const);
}
}
} else if (isPointerType(LhsTy) && !isPointerType(RhsTy)) {
size_t Scale = getPointedToSize(LhsTy);
if (Scale > 1) { // Skip multiplication for 1 (char) and 0 (void)
if (RhsNode->GetOpCode() == OP_constval) {
ConstvalNode *RhsConst = static_cast<ConstvalNode *>(RhsNode);
ASSERT(RhsConst->GetConstVal()->GetKind() == kConstInt,
"expected int const");
MIRIntConst *IntConst =
static_cast<MIRIntConst *>(RhsConst->GetConstVal());
int64_t Val = IntConst->GetValue().GetSXTValue();
RhsNode = Builder->CreateIntConst(Val * Scale, PointerPrimTy);
} else {
ConstvalNode *Const = Builder->CreateIntConst(Scale, PointerPrimTy);
RhsNode = Builder->CreateExprBinary(OP_mul, *IntPointerTy, RhsNode,
Const);
}
}
}
}
BinNode = Builder->CreateExprBinary(Op, *Ty, LhsNode, RhsNode);
// For the difference of two pointers, the result needs to be scaled by the
// size of the pointed-to object.
if (Op == OP_sub && isPointerType(LhsTy) && isPointerType(RhsTy)) {
size_t Scale = getPointedToSize(LhsTy);
if (Scale > 1) { // Skip multiplication for 1 (char) and 0 (void)
ConstvalNode *Const = Builder->CreateIntConst(Scale, Ty->GetPrimType());
BinNode = Builder->CreateExprBinary(OP_div, *Ty, BinNode, Const);
}
}
}
Result BinRes(BinNode, BO->getID(*Context), BO->getExprLoc(), Ty);
BinRes.appendStmts(Rhs);
BinRes.appendStmts(Lhs);
return BinRes;
}
Result Clang2MapleVisitor::VisitBinaryConditionalOperator(
const clang::BinaryConditionalOperator *BCO) {
// First, check if the condition is a compile-time constant
clang::Expr::EvalResult R;
bool Success = BCO->getCond()->EvaluateAsInt(R, *Context);
if (Success) {
llvm::APSInt Val = R.Val.getInt();
if (Val.isNullValue()) {
return Visit(BCO->getFalseExpr());
} else {
return Visit(BCO->getCond());
}
}
Result CondRes = Visit(BCO->getCond());
Result FalseRes = Visit(BCO->getFalseExpr());
MIRType *Ty = type2Mpl(BCO->getType());
// In the simple case, both true and false are just one expression
if (Ty->GetPrimType() != PTY_void && FalseRes.isSimple() &&
FalseRes.canSpeculate()) {
Result Res(Builder->CreateExprTernary(
OP_select, *Ty, exprToCond(getNodeAsRVal(CondRes)),
getNodeAsRVal(CondRes), getNodeAsRVal(FalseRes)),
BCO->getID(*Context), BCO->getBeginLoc(), Ty);
Res.appendStmts(CondRes);
return Res;
}
// If not, then expand to an if-then-else
MIRSymbol *Temp = nullptr;
if (Ty->GetPrimType() != PTY_void) {
Temp = Builder->GetOrCreateLocalDecl(
"cond." + std::to_string(BCO->getID(*Context)), *Ty);
}
Result Res(Temp, Ty, BCO->getBeginLoc());
IfStmtNode *IfNode =
Builder->CreateStmtIf(exprToNotCond(getNodeAsRVal(CondRes)));
Res.appendStmts(CondRes);
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
StmtNode *FalsePart;
if (Temp) {
FalsePart = Builder->CreateStmtDassign(*Temp, 0, getNodeAsRVal(FalseRes));
} else {
FalsePart = getNodeAsStmt(FalseRes);
}
for (Result::iterator It = FalseRes.beginStmtsBefore();
It != FalseRes.endStmtsBefore(); ++It) {
Block->AddStatement(*It);
}
addStmtToBlock(Block, FalsePart);
for (Result::iterator It = FalseRes.beginStmtsAfter();
It != FalseRes.endStmtsAfter(); ++It) {
Block->AddStatement(*It);
}
IfNode->SetThenPart(Block);
IfNode->SetSrcPos(sourceLocation2Mpl(BCO->getBeginLoc()));
Res.appendStmtBefore(IfNode);
return Res;
}
Result Clang2MapleVisitor::VisitCallExpr(const clang::CallExpr *CE) {
MapleVector<BaseNode *> Args(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
Result Res(CE->getBeginLoc());
const clang::FunctionDecl *CalleeDecl = CE->getDirectCallee();
MIRType *Ty = type2Mpl(CE->getType());
TypeAttrs Attrs;
if (isOneElementVector(CE->getType())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
unsigned NumArgs = CE->getNumArgs();
if (shouldEvaluateArgs(CalleeDecl)) {
for (unsigned i = 0; i < NumArgs; ++i) {
Result ArgRes = Visit(CE->getArg(i));
Args.push_back(getNodeAsRVal(ArgRes));
Res.appendStmts(ArgRes);
}
}
// Indirect call
if (!CalleeDecl) {
Result CalleeRes = Visit(CE->getCallee());
Args.insert(Args.begin(), getNodeAsRVal(CalleeRes));
IcallNode *ICall = Builder->CreateStmtIcall(Args);
Res.appendStmts(CalleeRes);
Res.setNode(ICall, CE->getID(*Context), Ty, Attrs);
return Res;
} else {
BaseNode *Call;
// Special cases for some builtins
unsigned int BuiltinID = CalleeDecl->getBuiltinID();
// Note: The cases are kept in alphabetical order, ignoring an optional
// `__builtin_` prefix, and similar builtins are grouped together, even if
// that puts them out of order.
switch (CalleeDecl->getBuiltinID()) {
case clang::Builtin::BI__builtin_abs:
case clang::Builtin::BI__builtin_fabs:
case clang::Builtin::BI__builtin_fabsf:
case clang::Builtin::BI__builtin_fabsl:
case clang::Builtin::BI__builtin_fabsf16:
case clang::Builtin::BI__builtin_fabsf128:
case clang::Builtin::BI__builtin_labs:
case clang::Builtin::BI__builtin_llabs:
case clang::Builtin::BIabs:
case clang::Builtin::BIlabs:
case clang::Builtin::BIllabs:
case clang::Builtin::BIfabs:
case clang::Builtin::BIfabsf:
case clang::Builtin::BIfabsl:
Call = Builder->CreateExprUnary(OP_abs, *Ty, Args[0]);
break;
case clang::Builtin::BI__builtin_acos:
case clang::Builtin::BIacos:
Call = Builder->CreateExprIntrinsicop(INTRN_C_acos, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_acosf:
case clang::Builtin::BIacosf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_acosf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_alloca:
case clang::Builtin::BI_alloca:
case clang::Builtin::BIalloca:
Call = Builder->CreateExprUnary(OP_alloca, *Ty, Args[0]);
Call->SetPrimType(PointerPrimTy);
break;
case clang::Builtin::BI__builtin_asin:
case clang::Builtin::BIasin:
Call = Builder->CreateExprIntrinsicop(INTRN_C_asin, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_asinf:
case clang::Builtin::BIasinf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_asinf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_atan:
case clang::Builtin::BIatan:
Call = Builder->CreateExprIntrinsicop(INTRN_C_atan, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_atanf:
case clang::Builtin::BIatanf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_atanf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_classify_type: {
// Let Clang figure out the type classification
clang::Expr::EvalResult R;
bool Success = CE->EvaluateAsInt(R, *Context);
ASSERT(Success, "Failed to evaluate __builtin_classify_type");
llvm::APSInt Val = R.Val.getInt();
Call = Builder->CreateIntConst(Val.getExtValue(), Ty->GetPrimType());
} break;
case clang::Builtin::BI__builtin_clz:
Call = Builder->CreateExprIntrinsicop(INTRN_C_clz32, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_clzl:
case clang::Builtin::BI__builtin_clzll:
Call = Builder->CreateExprIntrinsicop(INTRN_C_clz64, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_constant_p: {
int Val = CE->getArg(0)->isConstantInitializer(*Context, false) ? 1 : 0;
// Pointers are not considered constant
if (CE->getArg(0)->getType()->isPointerType() &&
!llvm::isa<clang::StringLiteral>(CE->getArg(0)->IgnoreParenCasts())) {
Val = 0;
}
Call = Builder->CreateIntConst(Val, Ty->GetPrimType());
} break;
case clang::Builtin::BI__builtin_cos:
case clang::Builtin::BIcos:
Call = Builder->CreateExprIntrinsicop(INTRN_C_cos, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_cosf:
case clang::Builtin::BIcosf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_cosf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_cosh:
case clang::Builtin::BIcosh:
Call = Builder->CreateExprIntrinsicop(INTRN_C_cosh, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_coshf:
case clang::Builtin::BIcoshf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_coshf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_ctz:
Call = Builder->CreateExprIntrinsicop(INTRN_C_ctz32, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_ctzl:
case clang::Builtin::BI__builtin_ctzll:
Call = Builder->CreateExprIntrinsicop(INTRN_C_ctz64, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_exp:
case clang::Builtin::BIexp:
Call = Builder->CreateExprIntrinsicop(INTRN_C_exp, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_expf:
case clang::Builtin::BIexpf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_expf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_expect: {
ASSERT(Args.size() == 2, "__builtin_expect requires two arguments");
// Arg 0 is the expression and arg 1 is the expected value.
Call = Args[0];
// TODO: Currently the expected value is just executed, but we should do
// something with it to improve performance.
StmtNode *SNode;
if (kOpcodeInfo.IsStmt(Args[1]->op)) {
SNode = static_cast<StmtNode *>(Args[1]);
} else {
// If the node is an expression, not a statement, wrap it in an eval
SNode = Builder->CreateStmtUnary(OP_eval, Args[1]);
}
Res.appendStmtBefore(SNode);
} break;
case clang::Builtin::BI__builtin_ffs:
Call = Builder->CreateExprIntrinsicop(INTRN_C_ffs, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_fmax:
case clang::Builtin::BI__builtin_fmaxf:
case clang::Builtin::BI__builtin_fmaxf16:
case clang::Builtin::BI__builtin_fmaxl:
case clang::Builtin::BIfmax:
case clang::Builtin::BIfmaxf:
case clang::Builtin::BIfmaxl:
Call = Builder->CreateExprBinary(OP_max, *Ty, Args[0], Args[1]);
break;
case clang::Builtin::BI__builtin_fmin:
case clang::Builtin::BI__builtin_fminf:
case clang::Builtin::BI__builtin_fminf16:
case clang::Builtin::BI__builtin_fminl:
case clang::Builtin::BIfmin:
case clang::Builtin::BIfminf:
case clang::Builtin::BIfminl:
Call = Builder->CreateExprBinary(OP_min, *Ty, Args[0], Args[1]);
break;
case clang::Builtin::BI__builtin_isinf_sign:
ASSERT(Args.size() == 1, "Incorrect arguments to isinf");
if (Args[0]->GetPrimType() == PTY_f64) {
Call = Builder->CreateStmtCall("__isinf", Args);
} else if (Args[0]->GetPrimType() == PTY_f32) {
Call = Builder->CreateStmtCall("__isinff", Args);
} else {
ASSERT(false, "Unsupported type passed to isinf");
}
break;
case clang::Builtin::BI__builtin_huge_val:
case clang::Builtin::BI__builtin_inf:
Call =
Builder->CreateDoubleConst(std::numeric_limits<double>::infinity());
break;
case clang::Builtin::BI__builtin_huge_valf:
case clang::Builtin::BI__builtin_inff:
Call = Builder->CreateFloatConst(std::numeric_limits<float>::infinity());
break;
case clang::Builtin::BI__builtin_log:
case clang::Builtin::BIlog:
Call = Builder->CreateExprIntrinsicop(INTRN_C_log, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_logf:
case clang::Builtin::BIlogf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_logf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_log10:
case clang::Builtin::BIlog10:
Call = Builder->CreateExprIntrinsicop(INTRN_C_log10, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_log10f:
case clang::Builtin::BIlog10f:
Call = Builder->CreateExprIntrinsicop(INTRN_C_log10f, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_memcmp:
case clang::Builtin::BImemcmp:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_memcmp, Args);
break;
case clang::Builtin::BI__builtin_memcpy:
case clang::Builtin::BImemcpy:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_memcpy, Args);
break;
case clang::Builtin::BI__builtin_memmove:
case clang::Builtin::BImemmove:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_memmove, Args);
break;
case clang::Builtin::BI__builtin_memset:
case clang::Builtin::BImemset:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_memset, Args);
break;
case clang::Builtin::BI__builtin_prefetch:
// TODO: Do something useful here.
return Res;
case clang::Builtin::BI__builtin_signbit: {
MIRFunction *Callee =
Builder->GetOrCreateFunction("__signbit", Ty->GetTypeIndex());
Call = Builder->CreateStmtCall(Callee->GetPuidx(), Args);
Callee->GetFuncSymbol()->SetAppearsInCode(true);
} break;
case clang::Builtin::BI__builtin_sin:
case clang::Builtin::BIsin:
Call = Builder->CreateExprIntrinsicop(INTRN_C_sin, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_sinf:
case clang::Builtin::BIsinf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_sinf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_sinh:
case clang::Builtin::BIsinh:
Call = Builder->CreateExprIntrinsicop(INTRN_C_sinh, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_sinhf:
case clang::Builtin::BIsinhf:
Call = Builder->CreateExprIntrinsicop(INTRN_C_sinhf, OP_intrinsicop, *Ty,
Args);
break;
case clang::Builtin::BI__builtin_strcmp:
case clang::Builtin::BIstrcmp:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_strcmp, Args);
break;
case clang::Builtin::BI__builtin_strncmp:
case clang::Builtin::BIstrncmp:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_strncmp, Args);
break;
case clang::Builtin::BI__builtin_strcpy:
case clang::Builtin::BIstrcpy:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_strcpy, Args);
break;
case clang::Builtin::BI__builtin_strncpy:
case clang::Builtin::BIstrncpy:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_strncpy, Args);
break;
case clang::Builtin::BI__builtin_strlen:
case clang::Builtin::BIstrlen:
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_strlen, Args);
break;
case clang::Builtin::BI__builtin_va_copy: {
ASSERT(Args.size() == 2, "ap_copy expects 2 arguments");
// The address of the ap_list parameters needs to be passed
Args[0] = getAddrOfNode(Args[0]);
Args[1] = getAddrOfNode(Args[1]);
// Add the size of the ap_list structure as the size to memcpy.
clang::TypedefDecl *VaListTypeDef = Context->getBuiltinVaListDecl();
MIRType *APListTy = type2Mpl(VaListTypeDef->getUnderlyingType());
Args.push_back(Builder->GetConstInt(APListTy->GetSize()));
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_memcpy, Args);
} break;
case clang::Builtin::BI__builtin_va_end:
// Nothing needs to be done for this function
return Res;
case clang::Builtin::BI__builtin_va_start:
// The address of the ap_list parameter needs to be passed
Args[0] = getAddrOfNode(Args[0]);
Call = Builder->CreateStmtIntrinsicCall(INTRN_C_va_start, Args);
break;
default: {
#if DEBUG
if (BuiltinID != 0) {
LogInfo::MapleLogger()
<< "Unhandled builtin: " << Context->BuiltinInfo.getName(BuiltinID)
<< "\n";
}
#endif
llvm::StringRef CalleeName = CalleeDecl->getName();
if (CalleeName.startswith("__builtin_mpl_vector_")) {
StringRef VectorOpName =
CalleeName.substr(strlen("__builtin_mpl_vector_"));
// clang-format off
#define VECTOR_INTRINSIC_TYPE(OP_NAME, VECTY) \
if (VectorOpName.endswith(#VECTY)) { \
Call = Builder->CreateExprIntrinsicop(INTRN_vector_##OP_NAME##_##VECTY, \
OP_intrinsicop, *Ty, Args); \
}
#define VECTOR_INTRINSICCALL_TYPE(OP_NAME, VECTY) \
if (VectorOpName.endswith(#VECTY)) { \
Call = Builder->CreateStmtIntrinsicCall(INTRN_vector_##OP_NAME##_##VECTY, \
Args); \
}
#define VECTOR_INTRINSIC(OP_NAME) \
if (VectorOpName.startswith(#OP_NAME)) { \
VECTOR_INTRINSIC_TYPE(OP_NAME, v2i64) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v4i32) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v8i16) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v16i8) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v2u64) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v4u32) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v8u16) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v16u8) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v2f64) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v4f32) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v1i64) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v2i32) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v4i16) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v8i8) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v1u64) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v2u32) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v4u16) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v8u8) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v1f64) \
else VECTOR_INTRINSIC_TYPE(OP_NAME, v2f32) \
}
VECTOR_INTRINSIC(from_scalar)
else VECTOR_INTRINSIC(merge)
else VECTOR_INTRINSIC(reverse)
else VECTOR_INTRINSIC(set_element)
else VECTOR_INTRINSIC(sum)
else VECTOR_INTRINSIC(table_lookup)
else if (VectorOpName.startswith("get_lane")) {
VECTOR_INTRINSIC_TYPE(get_lane, v1i64)
else VECTOR_INTRINSIC_TYPE(get_lane, v2i32)
else VECTOR_INTRINSIC_TYPE(get_lane, v4i16)
else VECTOR_INTRINSIC_TYPE(get_lane, v8i8)
else VECTOR_INTRINSIC_TYPE(get_lane, v1u64)
else VECTOR_INTRINSIC_TYPE(get_lane, v2u32)
else VECTOR_INTRINSIC_TYPE(get_lane, v4u16)
else VECTOR_INTRINSIC_TYPE(get_lane, v8u8)
} else if (VectorOpName.startswith("getq_lane")) {
VECTOR_INTRINSIC_TYPE(getq_lane, v2i64)
else VECTOR_INTRINSIC_TYPE(getq_lane, v4i32)
else VECTOR_INTRINSIC_TYPE(getq_lane, v8i16)
else VECTOR_INTRINSIC_TYPE(getq_lane, v16i8)
else VECTOR_INTRINSIC_TYPE(getq_lane, v2u64)
else VECTOR_INTRINSIC_TYPE(getq_lane, v4u32)
else VECTOR_INTRINSIC_TYPE(getq_lane, v8u16)
else VECTOR_INTRINSIC_TYPE(getq_lane, v16u8)
} else if (VectorOpName.startswith("abs")) {
VECTOR_INTRINSIC_TYPE(abs, v8i8)
else VECTOR_INTRINSIC_TYPE(abs, v4i16)
else VECTOR_INTRINSIC_TYPE(abs, v2i32)
else VECTOR_INTRINSIC_TYPE(abs, v1i64)
else VECTOR_INTRINSIC_TYPE(abs, v2f32)
else VECTOR_INTRINSIC_TYPE(abs, v1f64)
else VECTOR_INTRINSIC_TYPE(abs, v16i8)
else VECTOR_INTRINSIC_TYPE(abs, v8i16)
else VECTOR_INTRINSIC_TYPE(abs, v4i32)
else VECTOR_INTRINSIC_TYPE(abs, v2i64)
else VECTOR_INTRINSIC_TYPE(abs, v4f32)
else VECTOR_INTRINSIC_TYPE(abs, v2f64)
} else if (VectorOpName.startswith("addl_low")) {
VECTOR_INTRINSIC_TYPE(addl_low, v8i8)
else VECTOR_INTRINSIC_TYPE(addl_low, v4i16)
else VECTOR_INTRINSIC_TYPE(addl_low, v2i32)
else VECTOR_INTRINSIC_TYPE(addl_low, v8u8)
else VECTOR_INTRINSIC_TYPE(addl_low, v4u16)
else VECTOR_INTRINSIC_TYPE(addl_low, v2u32)
} else if (VectorOpName.startswith("addl_high")) {
VECTOR_INTRINSIC_TYPE(addl_high, v8i8)
else VECTOR_INTRINSIC_TYPE(addl_high, v4i16)
else VECTOR_INTRINSIC_TYPE(addl_high, v2i32)
else VECTOR_INTRINSIC_TYPE(addl_high, v8u8)
else VECTOR_INTRINSIC_TYPE(addl_high, v4u16)
else VECTOR_INTRINSIC_TYPE(addl_high, v2u32)
} else if (VectorOpName.startswith("addw_low")) {
VECTOR_INTRINSIC_TYPE(addw_low, v8i8)
else VECTOR_INTRINSIC_TYPE(addw_low, v4i16)
else VECTOR_INTRINSIC_TYPE(addw_low, v2i32)
else VECTOR_INTRINSIC_TYPE(addw_low, v8u8)
else VECTOR_INTRINSIC_TYPE(addw_low, v4u16)
else VECTOR_INTRINSIC_TYPE(addw_low, v2u32)
} else if (VectorOpName.startswith("addw_high")) {
VECTOR_INTRINSIC_TYPE(addw_high, v8i8)
else VECTOR_INTRINSIC_TYPE(addw_high, v4i16)
else VECTOR_INTRINSIC_TYPE(addw_high, v2i32)
else VECTOR_INTRINSIC_TYPE(addw_high, v8u8)
else VECTOR_INTRINSIC_TYPE(addw_high, v4u16)
else VECTOR_INTRINSIC_TYPE(addw_high, v2u32)
} else if (VectorOpName.startswith("get_low")) {
VECTOR_INTRINSIC_TYPE(get_low, v2i64)
else VECTOR_INTRINSIC_TYPE(get_low, v4i32)
else VECTOR_INTRINSIC_TYPE(get_low, v8i16)
else VECTOR_INTRINSIC_TYPE(get_low, v16i8)
else VECTOR_INTRINSIC_TYPE(get_low, v2u64)
else VECTOR_INTRINSIC_TYPE(get_low, v4u32)
else VECTOR_INTRINSIC_TYPE(get_low, v8u16)
else VECTOR_INTRINSIC_TYPE(get_low, v16u8)
else VECTOR_INTRINSIC_TYPE(get_low, v2f64)
else VECTOR_INTRINSIC_TYPE(get_low, v4f32)
} else if (VectorOpName.startswith("get_high")) {
VECTOR_INTRINSIC_TYPE(get_high, v2i64)
else VECTOR_INTRINSIC_TYPE(get_high, v4i32)
else VECTOR_INTRINSIC_TYPE(get_high, v8i16)
else VECTOR_INTRINSIC_TYPE(get_high, v16i8)
else VECTOR_INTRINSIC_TYPE(get_high, v2u64)
else VECTOR_INTRINSIC_TYPE(get_high, v4u32)
else VECTOR_INTRINSIC_TYPE(get_high, v8u16)
else VECTOR_INTRINSIC_TYPE(get_high, v16u8)
else VECTOR_INTRINSIC_TYPE(get_high, v2f64)
else VECTOR_INTRINSIC_TYPE(get_high, v4f32)
} else if (VectorOpName.startswith("narrow_low")) {
VECTOR_INTRINSIC_TYPE(narrow_low, v2i64)
else VECTOR_INTRINSIC_TYPE(narrow_low, v4i32)
else VECTOR_INTRINSIC_TYPE(narrow_low, v8i16)
else VECTOR_INTRINSIC_TYPE(narrow_low, v2u64)
else VECTOR_INTRINSIC_TYPE(narrow_low, v4u32)
else VECTOR_INTRINSIC_TYPE(narrow_low, v8u16)
} else if (VectorOpName.startswith("narrow_high")) {
VECTOR_INTRINSIC_TYPE(narrow_high, v2i64)
else VECTOR_INTRINSIC_TYPE(narrow_high, v4i32)
else VECTOR_INTRINSIC_TYPE(narrow_high, v8i16)
else VECTOR_INTRINSIC_TYPE(narrow_high, v2u64)
else VECTOR_INTRINSIC_TYPE(narrow_high, v4u32)
else VECTOR_INTRINSIC_TYPE(narrow_high, v8u16)
} else if (VectorOpName.startswith("shli")) {
Call = Builder->CreateExprBinary(OP_shl, *Ty, Args[0], Args[1]);
} else if (VectorOpName.startswith("shri")) {
Call = Builder->CreateExprBinary(OP_lshr, *Ty, Args[0], Args[1]);
} else if (VectorOpName.startswith("labssub_low")) {
VECTOR_INTRINSIC_TYPE(labssub_low, v8i8)
else VECTOR_INTRINSIC_TYPE(labssub_low, v4i16)
else VECTOR_INTRINSIC_TYPE(labssub_low, v2i32)
else VECTOR_INTRINSIC_TYPE(labssub_low, v8u8)
else VECTOR_INTRINSIC_TYPE(labssub_low, v4u16)
else VECTOR_INTRINSIC_TYPE(labssub_low, v2u32)
} else if (VectorOpName.startswith("labssub_high")) {
VECTOR_INTRINSIC_TYPE(labssub_high, v8i8)
else VECTOR_INTRINSIC_TYPE(labssub_high, v4i16)
else VECTOR_INTRINSIC_TYPE(labssub_high, v2i32)
else VECTOR_INTRINSIC_TYPE(labssub_high, v8u8)
else VECTOR_INTRINSIC_TYPE(labssub_high, v4u16)
else VECTOR_INTRINSIC_TYPE(labssub_high, v2u32)
} else if (VectorOpName.startswith("shr_narrow_low")) {
VECTOR_INTRINSIC_TYPE(shr_narrow_low, v2i64)
else VECTOR_INTRINSIC_TYPE(shr_narrow_low, v4i32)
else VECTOR_INTRINSIC_TYPE(shr_narrow_low, v8i16)
else VECTOR_INTRINSIC_TYPE(shr_narrow_low, v2u64)
else VECTOR_INTRINSIC_TYPE(shr_narrow_low, v4u32)
else VECTOR_INTRINSIC_TYPE(shr_narrow_low, v8u16)
} else if (VectorOpName.startswith("pairwise_adalp")) {
VECTOR_INTRINSIC_TYPE(pairwise_adalp, v8i8)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v4i16)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v2i32)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v8u8)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v4u16)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v2u32)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v16i8)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v8i16)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v4i32)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v16u8)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v8u16)
else VECTOR_INTRINSIC_TYPE(pairwise_adalp, v4u32)
} else if (VectorOpName.startswith("pairwise_add")) {
VECTOR_INTRINSIC_TYPE(pairwise_add, v4i32)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v8i16)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v16i8)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v4u32)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v8u16)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v16u8)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v2i32)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v4i16)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v8i8)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v2u32)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v4u16)
else VECTOR_INTRINSIC_TYPE(pairwise_add, v8u8)
} else if (VectorOpName.startswith("madd")) {
VECTOR_INTRINSIC_TYPE(madd, v2i32)
else VECTOR_INTRINSIC_TYPE(madd, v4i16)
else VECTOR_INTRINSIC_TYPE(madd, v8i8)
else VECTOR_INTRINSIC_TYPE(madd, v2u32)
else VECTOR_INTRINSIC_TYPE(madd, v4u16)
else VECTOR_INTRINSIC_TYPE(madd, v8u8)
} else if (VectorOpName.startswith("mull_low")) {
VECTOR_INTRINSIC_TYPE(mull_low, v2i32)
else VECTOR_INTRINSIC_TYPE(mull_low, v4i16)
else VECTOR_INTRINSIC_TYPE(mull_low, v8i8)
else VECTOR_INTRINSIC_TYPE(mull_low, v2u32)
else VECTOR_INTRINSIC_TYPE(mull_low, v4u16)
else VECTOR_INTRINSIC_TYPE(mull_low, v8u8)
} else if (VectorOpName.startswith("mull_high")) {
VECTOR_INTRINSIC_TYPE(mull_high, v2i32)
else VECTOR_INTRINSIC_TYPE(mull_high, v4i16)
else VECTOR_INTRINSIC_TYPE(mull_high, v8i8)
else VECTOR_INTRINSIC_TYPE(mull_high, v2u32)
else VECTOR_INTRINSIC_TYPE(mull_high, v4u16)
else VECTOR_INTRINSIC_TYPE(mull_high, v8u8)
} else if (VectorOpName.startswith("subl_low")) {
VECTOR_INTRINSIC_TYPE(subl_low, v8i8)
else VECTOR_INTRINSIC_TYPE(subl_low, v4i16)
else VECTOR_INTRINSIC_TYPE(subl_low, v2i32)
else VECTOR_INTRINSIC_TYPE(subl_low, v8u8)
else VECTOR_INTRINSIC_TYPE(subl_low, v4u16)
else VECTOR_INTRINSIC_TYPE(subl_low, v2u32)
} else if (VectorOpName.startswith("subl_high")) {
VECTOR_INTRINSIC_TYPE(subl_high, v8i8)
else VECTOR_INTRINSIC_TYPE(subl_high, v4i16)
else VECTOR_INTRINSIC_TYPE(subl_high, v2i32)
else VECTOR_INTRINSIC_TYPE(subl_high, v8u8)
else VECTOR_INTRINSIC_TYPE(subl_high, v4u16)
else VECTOR_INTRINSIC_TYPE(subl_high, v2u32)
} else if (VectorOpName.startswith("subw_low")) {
VECTOR_INTRINSIC_TYPE(subw_low, v8i8)
else VECTOR_INTRINSIC_TYPE(subw_low, v4i16)
else VECTOR_INTRINSIC_TYPE(subw_low, v2i32)
else VECTOR_INTRINSIC_TYPE(subw_low, v8u8)
else VECTOR_INTRINSIC_TYPE(subw_low, v4u16)
else VECTOR_INTRINSIC_TYPE(subw_low, v2u32)
} else if (VectorOpName.startswith("subw_high")) {
VECTOR_INTRINSIC_TYPE(subw_high, v8i8)
else VECTOR_INTRINSIC_TYPE(subw_high, v4i16)
else VECTOR_INTRINSIC_TYPE(subw_high, v2i32)
else VECTOR_INTRINSIC_TYPE(subw_high, v8u8)
else VECTOR_INTRINSIC_TYPE(subw_high, v4u16)
else VECTOR_INTRINSIC_TYPE(subw_high, v2u32)
} else if (VectorOpName.startswith("widen_low")) {
VECTOR_INTRINSIC_TYPE(widen_low, v2i32)
else VECTOR_INTRINSIC_TYPE(widen_low, v4i16)
else VECTOR_INTRINSIC_TYPE(widen_low, v8i8)
else VECTOR_INTRINSIC_TYPE(widen_low, v2u32)
else VECTOR_INTRINSIC_TYPE(widen_low, v4u16)
else VECTOR_INTRINSIC_TYPE(widen_low, v8u8)
} else if (VectorOpName.startswith("widen_high")) {
VECTOR_INTRINSIC_TYPE(widen_high, v2i32)
else VECTOR_INTRINSIC_TYPE(widen_high, v4i16)
else VECTOR_INTRINSIC_TYPE(widen_high, v8i8)
else VECTOR_INTRINSIC_TYPE(widen_high, v2u32)
else VECTOR_INTRINSIC_TYPE(widen_high, v4u16)
else VECTOR_INTRINSIC_TYPE(widen_high, v8u8)
} else if (VectorOpName.startswith("zip1q")) {
VECTOR_INTRINSIC_TYPE(zip1q, v16i8)
else VECTOR_INTRINSIC_TYPE(zip1q, v8i16)
else VECTOR_INTRINSIC_TYPE(zip1q, v4i32)
else VECTOR_INTRINSIC_TYPE(zip1q, v2i64)
else VECTOR_INTRINSIC_TYPE(zip1q, v16u8)
else VECTOR_INTRINSIC_TYPE(zip1q, v8u16)
else VECTOR_INTRINSIC_TYPE(zip1q, v4u32)
else VECTOR_INTRINSIC_TYPE(zip1q, v2u64)
} else if (VectorOpName.startswith("zip2q")) {
VECTOR_INTRINSIC_TYPE(zip2q, v16i8)
else VECTOR_INTRINSIC_TYPE(zip2q, v8i16)
else VECTOR_INTRINSIC_TYPE(zip2q, v4i32)
else VECTOR_INTRINSIC_TYPE(zip2q, v2i64)
else VECTOR_INTRINSIC_TYPE(zip2q, v16u8)
else VECTOR_INTRINSIC_TYPE(zip2q, v8u16)
else VECTOR_INTRINSIC_TYPE(zip2q, v4u32)
else VECTOR_INTRINSIC_TYPE(zip2q, v2u64)
} else if (VectorOpName.startswith("zip1")) {
VECTOR_INTRINSIC_TYPE(zip1, v8i8)
else VECTOR_INTRINSIC_TYPE(zip1, v4i16)
else VECTOR_INTRINSIC_TYPE(zip1, v2i32)
else VECTOR_INTRINSIC_TYPE(zip1, v8u8)
else VECTOR_INTRINSIC_TYPE(zip1, v4u16)
else VECTOR_INTRINSIC_TYPE(zip1, v2u32)
else VECTOR_INTRINSIC_TYPE(zip1q, v8u16)
} else if (VectorOpName.startswith("zip2")) {
VECTOR_INTRINSIC_TYPE(zip2, v8i8)
else VECTOR_INTRINSIC_TYPE(zip2, v4i16)
else VECTOR_INTRINSIC_TYPE(zip2, v2i32)
else VECTOR_INTRINSIC_TYPE(zip2, v8u8)
else VECTOR_INTRINSIC_TYPE(zip2, v4u16)
else VECTOR_INTRINSIC_TYPE(zip2, v2u32)
}
// clang-format on
else if (VectorOpName.startswith("load")) {
Call = Builder->CreateExprIread(
*Ty,
*GlobalTables::GetTypeTable().GetOrCreatePointerType(
*Ty, PointerPrimTy),
0, Args[0]);
}
else if (VectorOpName.startswith("store")) {
Call = Builder->CreateStmtIassign(
*GlobalTables::GetTypeTable().GetOrCreatePointerType(
type2MplIdx(CE->getArg(1)->getType()), PointerPrimTy),
0, Args[0], Args[1]);
}
} else if (CalleeDecl->getName().startswith("__builtin_")) {
MIRFunction *Callee = Builder->GetOrCreateFunction(
CalleeDecl->getName().substr(10).str(), Ty->GetTypeIndex());
Call = Builder->CreateStmtCall(Callee->GetPuidx(), Args);
Callee->GetFuncSymbol()->SetAppearsInCode(true);
} else if (CalleeDecl->getName() == "alloca") {
Call = Builder->CreateExprUnary(OP_alloca, *Ty, Args[0]);
Call->SetPrimType(PointerPrimTy);
} else {
MIRSymbol *CalleeSym = decl2Mpl(CalleeDecl);
MIRFunction *Callee = CalleeSym->GetFunction();
Call = Builder->CreateStmtCall(Callee->GetPuidx(), Args);
Callee->GetFuncSymbol()->SetAppearsInCode(true);
}
}
}
Res.setNode(Call, CE->getID(*Context), Ty, Attrs);
return Res;
}
}
Result Clang2MapleVisitor::VisitCastExpr(const clang::CastExpr *CE) {
Result SubExprRes = Visit(CE->getSubExpr());
MIRType *FromTy = type2Mpl(CE->getSubExpr()->getType());
MIRType *ToTy = type2Mpl(CE->getType());
Result Res(CE->getExprLoc());
switch (CE->getCastKind()) {
case clang::CK_BitCast: {
if (FromTy->GetPrimType() == ToTy->GetPrimType() &&
FromTy->IsScalarType()) {
// This case may show up when casting from a 1-element vector to its
// scalar type.
return SubExprRes;
}
BaseNode *SubExpr = getNodeAsRVal(SubExprRes);
if (ToTy->GetKind() == kTypePointer) {
Res.setNode(SubExpr, CE->getID(*Context), ToTy);
} else {
BaseNode *SubExpr = getNodeAsRVal(SubExprRes);
Res.setNode(Builder->CreateExprRetype(*ToTy, *FromTy, SubExpr),
CE->getID(*Context), ToTy);
}
} break;
// This must be handled by the parent node
case clang::CK_LValueToRValue:
// Nothing needs to be passed down into the IR for these
case clang::CK_NoOp:
case clang::CK_ToVoid:
case clang::CK_ToUnion:
return SubExprRes;
case clang::CK_ArrayToPointerDecay: {
// A variable array type has been converted to a pointer, so do not take its
// address here.
if (CE->getSubExpr()->getType()->isVariableArrayType()) {
return SubExprRes;
}
if (SubExprRes.isSym()) {
BaseNode *AddrOf = Builder->CreateExprAddrof(SubExprRes.getField(),
*SubExprRes.getSym());
AddrOf->SetPrimType(PointerPrimTy);
Result NodeRes(AddrOf, CE->getID(*Context), ToTy, FromTy,
CE->getExprLoc());
NodeRes.appendStmts(SubExprRes);
return NodeRes;
}
if (SubExprRes.getField()) {
Result FieldRes(Builder->CreateExprIaddrof(*ToTy, *SubExprRes.getAddrTy(),
SubExprRes.getField(),
SubExprRes.getNode()),
CE->getID(*Context), ToTy, FromTy, CE->getExprLoc());
FieldRes.appendStmts(SubExprRes);
return FieldRes;
}
Result Res(getNodeAsRVal(SubExprRes), CE->getID(*Context), ToTy, FromTy,
CE->getExprLoc());
Res.appendStmts(SubExprRes);
return Res;
}
case clang::CK_NullToPointer:
case clang::CK_IntegralToPointer: {
// Change the type of the const
if (BaseNode *N = SubExprRes.getNode()) {
if (N->GetOpCode() == OP_constval) {
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(N);
MIRConst *Const = ConstNode->GetConstVal();
ASSERT(Const->GetKind() == kConstInt, "Expected constant int in cast");
MIRIntConst *IntConst = static_cast<MIRIntConst *>(Const);
ConstNode->SetConstVal(
GlobalTables::GetIntConstTable().GetOrCreateIntConst(
IsSignedInteger(N->GetPrimType()) ? IntConst->GetValue().GetSXTValue() : IntConst->GetValue().GetZXTValue(), *IntPointerTy));
}
N->SetPrimType(PointerPrimTy);
}
SubExprRes.setValueTy(ToTy, TypeAttrs(), true);
return SubExprRes;
}
case clang::CK_FunctionToPointerDecay:
// This is just a type change
SubExprRes.setValueTy(ToTy);
return SubExprRes;
case clang::CK_IntegralCast: {
clang::Expr::EvalResult Constant;
if (CE->EvaluateAsConstantExpr(Constant, *Context)) {
// Don't generate casts for constants, just emit the constant
if (!Constant.Val.isInt()) {
LogInfo::MapleLogger()
<< "Error: expected integer constant in integral cast\n";
Constant.Val.dump();
}
llvm::APSInt Value = Constant.Val.getInt();
PrimType PTy = ToTy->GetPrimType();
if (!Initializer) {
PTy = GetRegPrimType(PTy);
}
BaseNode *ConstNode = Builder->CreateIntConst(Value.getExtValue(), PTy);
Res.setNode(ConstNode, CE->getID(*Context), ToTy);
} else {
Res.setNode(createNumericCast(ToTy, getNodeAsRVal(SubExprRes)),
CE->getID(*Context), ToTy);
}
} break;
case clang::CK_IntegralToBoolean:
case clang::CK_PointerToBoolean:
case clang::CK_FloatingToBoolean:
Res.setNode(exprToCond(getNodeAsRVal(SubExprRes)), CE->getID(*Context),
ToTy);
break;
case clang::CK_PointerToIntegral:
Res.setNode(createNumericCast(ToTy, getNodeAsRVal(SubExprRes)),
CE->getID(*Context), ToTy);
break;
case clang::CK_IntegralToFloating:
case clang::CK_FloatingCast:
// Because we treat `long double` as `double`, this may be a cast to/from
// the same type. If so, do not generate a convert node.
if (ToTy == FromTy) {
return SubExprRes;
}
Res.setNode(Builder->CreateExprTypeCvt(OP_cvt, *ToTy, *FromTy,
getNodeAsRVal(SubExprRes)),
CE->getID(*Context), ToTy);
break;
case clang::CK_FloatingToIntegral: {
BaseNode *SubExpr = getNodeAsRVal(SubExprRes);
if (ToTy->GetSize() < 4) {
bool IsUnsigned = PrimitiveType(ToTy->GetPrimType()).IsUnsigned();
TypeCvtNode *Cvt =
Builder->CreateExprTypeCvt(OP_cvt, IsUnsigned ? PTY_u32 : PTY_i32,
FromTy->GetPrimType(), *SubExpr);
Res.setNode(Builder->CreateExprExtractbits(
IsUnsigned ? OP_zext : OP_sext,
IsUnsigned ? *GlobalTables::GetTypeTable().GetUInt32()
: *GlobalTables::GetTypeTable().GetInt32(),
0, ToTy->GetSize() * 8, Cvt),
CE->getID(*Context), ToTy);
} else {
Res.setNode(Builder->CreateExprTypeCvt(OP_cvt, *ToTy, *FromTy, SubExpr),
CE->getID(*Context), ToTy);
}
} break;
case clang::CK_VectorSplat: {
BaseNode *SubExpr = getNodeAsRVal(SubExprRes);
PrimType PTy = ToTy->GetPrimType();
MapleVector<BaseNode *> Args(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
Args.push_back(createNumericCast(
GlobalTables::GetTypeTable().GetPrimType(getVectorElementPrimType(PTy)),
SubExpr));
#define CASE_VECTOR_FROM_SCALAR(VECTY) \
case PTY_##VECTY: \
Res.setNode( \
Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_##VECTY, \
OP_intrinsicop, *ToTy, Args), \
CE->getID(*Context), ToTy); \
break;
switch (PTy) {
CASE_VECTOR_FROM_SCALAR(v2i64)
CASE_VECTOR_FROM_SCALAR(v4i32)
CASE_VECTOR_FROM_SCALAR(v8i16)
CASE_VECTOR_FROM_SCALAR(v16i8)
CASE_VECTOR_FROM_SCALAR(v2u64)
CASE_VECTOR_FROM_SCALAR(v4u32)
CASE_VECTOR_FROM_SCALAR(v8u16)
CASE_VECTOR_FROM_SCALAR(v16u8)
CASE_VECTOR_FROM_SCALAR(v2f64)
CASE_VECTOR_FROM_SCALAR(v4f32)
CASE_VECTOR_FROM_SCALAR(v2i32)
CASE_VECTOR_FROM_SCALAR(v4i16)
CASE_VECTOR_FROM_SCALAR(v8i8)
CASE_VECTOR_FROM_SCALAR(v2u32)
CASE_VECTOR_FROM_SCALAR(v4u16)
CASE_VECTOR_FROM_SCALAR(v8u8)
CASE_VECTOR_FROM_SCALAR(v2f32)
case PTY_i64: {
ASSERT(isOneElementVector(CE->getType()),
"unexpected scalar type in VectorSplat cast");
TypeAttrs Attrs;
Attrs.SetAttr(ATTR_oneelem_simd);
Res.setNode(Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v1i64,
OP_intrinsicop, *ToTy, Args),
CE->getID(*Context), ToTy, Attrs);
} break;
case PTY_u64: {
ASSERT(isOneElementVector(CE->getType()),
"unexpected scalar type in VectorSplat cast");
TypeAttrs Attrs;
Attrs.SetAttr(ATTR_oneelem_simd);
Res.setNode(Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v1u64,
OP_intrinsicop, *ToTy, Args),
CE->getID(*Context), ToTy, Attrs);
} break;
case PTY_f64: {
ASSERT(isOneElementVector(CE->getType()),
"unexpected scalar type in VectorSplat cast");
TypeAttrs Attrs;
Attrs.SetAttr(ATTR_oneelem_simd);
Res.setNode(Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v1f64,
OP_intrinsicop, *ToTy, Args),
CE->getID(*Context), ToTy, Attrs);
} break;
default:
LogInfo::MapleLogger()
<< "Error: Unhandled vector type in VisitCastExpr\n";
#ifdef DEBUG
ToTy->Dump(0);
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
} break;
default:
LogInfo::MapleLogger() << "Error: Unhandled cast kind: "
<< CE->getCastKindName() << "\n";
CHECK_FATAL(false, "Failing due to unsupported feature");
}
Res.appendStmts(SubExprRes);
return Res;
}
Result
Clang2MapleVisitor::VisitCharacterLiteral(const clang::CharacterLiteral *CL) {
MIRType *Ty = type2Mpl(CL->getType());
ConstvalNode *Const =
Builder->CreateIntConst(CL->getValue(), Ty->GetPrimType());
return Result(Const, CL->getID(*Context), CL->getLocation(), Ty);
}
Result Clang2MapleVisitor::VisitChooseExpr(const clang::ChooseExpr *CE) {
return Visit(CE->getChosenSubExpr());
}
Result Clang2MapleVisitor::VisitCompoundLiteralExpr(
const clang::CompoundLiteralExpr *CLE) {
MIRType *Ty = type2Mpl(CLE->getType());
ASSERT(Ty->IsStructType() || Ty->GetKind() == kTypeArray ||
PrimitiveType(Ty->GetPrimType()).IsVector(),
"Unexpected type of CompoundLiteralExpr (not struct or array)");
// Create a temporary value for this structure and initialize it using this
// literal expression
if (Builder->GetCurrentFunction()) {
Result InitRes = Visit(CLE->getInitializer());
MIRSymbol *Temp = Builder->GetOrCreateLocalDecl(
"cle." + std::to_string(++UnnamedCount), *Ty);
Result Res(Temp, Ty, CLE->getBeginLoc());
Res.appendStmts(InitRes);
BaseNode *InitNode = InitRes.getNode();
if (InitNode) {
if (Ty->IsStructType()) {
MIRStructType *StructTy = static_cast<MIRStructType *>(Ty);
assignStruct(Res, Temp, nullptr, StructTy, InitNode);
} else if (PrimitiveType(Ty->GetPrimType()).IsVector()) {
assignVector(Res, Temp, Ty, InitNode);
} else { // array
MIRArrayType *ArrayTy = static_cast<MIRArrayType *>(Ty);
BaseNode *Base = Builder->CreateExprAddrof(0, *Temp);
Base->SetPrimType(PointerPrimTy);
assignArray(Res, Base, ArrayTy, InitNode);
}
}
return Res;
} else {
Initializer = true;
MIRConst *Init = getInitializer(Ty, CLE->getInitializer());
Initializer = false;
MIRSymbol *Temp =
Builder->CreateGlobalDecl("cle." + std::to_string(++UnnamedCount), *Ty);
Temp->SetKonst(Init);
return Result(Temp, Ty, CLE->getBeginLoc());
}
}
Result Clang2MapleVisitor::VisitConditionalOperator(
const clang::ConditionalOperator *CO) {
// First, check if the condition is a compile-time constant
clang::Expr::EvalResult R;
bool Success = CO->getCond()->EvaluateAsInt(R, *Context);
if (Success) {
llvm::APSInt Val = R.Val.getInt();
if (Val.isNullValue()) {
return Visit(CO->getFalseExpr());
} else {
return Visit(CO->getTrueExpr());
}
}
Result CondRes = Visit(CO->getCond());
Result TrueRes = Visit(CO->getTrueExpr());
Result FalseRes = Visit(CO->getFalseExpr());
MIRType *Ty = type2Mpl(CO->getType());
// In the simple case, both true and false are just one expression
if (Ty->GetPrimType() != PTY_void && TrueRes.isSimple() &&
TrueRes.canSpeculate() && FalseRes.isSimple() &&
FalseRes.canSpeculate()) {
Result Res(Builder->CreateExprTernary(
OP_select, *Ty, exprToCond(getNodeAsRVal(CondRes)),
getNodeAsRVal(TrueRes), getNodeAsRVal(FalseRes)),
CO->getID(*Context), CO->getBeginLoc(), Ty);
Res.appendStmts(CondRes);
return Res;
}
// If not, then expand to an if-then-else
MIRSymbol *Temp = nullptr;
if (Ty->GetPrimType() != PTY_void) {
Temp = Builder->GetOrCreateLocalDecl(
"cond." + std::to_string(CO->getID(*Context)), *Ty);
}
Result Res(Temp, Ty, CO->getBeginLoc());
IfStmtNode *IfNode =
Builder->CreateStmtIf(exprToCond(getNodeAsRVal(CondRes)));
Res.appendStmts(CondRes);
BlockNode *Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
StmtNode *TruePart;
if (Temp) {
TruePart = Builder->CreateStmtDassign(*Temp, 0, getNodeAsRVal(TrueRes));
} else {
TruePart = getNodeAsStmt(TrueRes);
}
for (Result::iterator It = TrueRes.beginStmtsBefore();
It != TrueRes.endStmtsBefore(); ++It) {
Block->AddStatement(*It);
}
addStmtToBlock(Block, TruePart);
for (Result::iterator It = TrueRes.beginStmtsAfter();
It != TrueRes.endStmtsAfter(); ++It) {
Block->AddStatement(*It);
}
IfNode->SetThenPart(Block);
Block = Builder->GetCurrentFuncCodeMp()->New<BlockNode>();
StmtNode *FalsePart;
if (Temp) {
FalsePart = Builder->CreateStmtDassign(*Temp, 0, getNodeAsRVal(FalseRes));
} else {
FalsePart = getNodeAsStmt(FalseRes);
}
for (Result::iterator It = FalseRes.beginStmtsBefore();
It != FalseRes.endStmtsBefore(); ++It) {
Block->AddStatement(*It);
}
addStmtToBlock(Block, FalsePart);
for (Result::iterator It = FalseRes.beginStmtsAfter();
It != FalseRes.endStmtsAfter(); ++It) {
Block->AddStatement(*It);
}
IfNode->SetElsePart(Block);
IfNode->SetSrcPos(sourceLocation2Mpl(CO->getBeginLoc()));
Res.appendStmtBefore(IfNode);
return Res;
}
Result Clang2MapleVisitor::VisitConstantExpr(const clang::ConstantExpr *CE) {
// This is just a wrapper expression
return Visit(CE->getSubExpr());
}
Result Clang2MapleVisitor::VisitDeclRefExpr(const clang::DeclRefExpr *DRE) {
MIRType *Ty = type2Mpl(DRE->getType());
const clang::ValueDecl *D = DRE->getDecl();
// We do not actually create symbols for enums, just extract the constant
if (auto EnumConst = llvm::dyn_cast<clang::EnumConstantDecl>(D)) {
const llvm::APSInt Value = EnumConst->getInitVal();
ConstvalNode *ConstNode =
Builder->CreateIntConst(Value.getExtValue(), Ty->GetPrimType());
return Result(ConstNode, DRE->getID(*Context), DRE->getLocation(), Ty);
}
MIRSymbol *Sym = decl2Mpl(D);
return Result(Sym, Ty, DRE->getLocation());
}
Result
Clang2MapleVisitor::VisitFloatingLiteral(const clang::FloatingLiteral *Lit) {
MIRType *Ty = type2Mpl(Lit->getType());
llvm::APFloat Value = Lit->getValue();
ConstvalNode *Const = nullptr;
if (&Value.getSemantics() == &llvm::APFloat::IEEEsingle()) {
Const = Builder->CreateFloatConst(Value.convertToFloat());
} else if (&Value.getSemantics() == &llvm::APFloat::IEEEdouble()) {
Const = Builder->CreateDoubleConst(Value.convertToDouble());
} else if (&Value.getSemantics() == &llvm::APFloat::IEEEquad()) {
bool LosesInfo;
Value.convert(llvm::APFloat::IEEEdouble(),
llvm::APFloatBase::roundingMode::NearestTiesToAway,
&LosesInfo);
Const = Builder->CreateDoubleConst(Value.convertToDouble());
} else {
LogInfo::MapleLogger() << "Unexpected type of floating literal: "
<< Ty->GetPrimType() << "\n";
}
return Result(Const, Lit->getID(*Context), Lit->getLocation(), Ty);
}
Result Clang2MapleVisitor::VisitImplicitValueInitExpr(
const clang::ImplicitValueInitExpr *IV) {
MIRType *Ty = type2Mpl(IV->getType());
MIRConst *Zero = createZero(Ty);
ConstvalNode *ZeroNode = Builder->CreateConstval(Zero);
return Result(ZeroNode, IV->getID(*Context), IV->getBeginLoc(), Ty);
}
Result Clang2MapleVisitor::VisitInitListExpr(const clang::InitListExpr *ILE) {
bool isStruct = ILE->getType()->isStructureType();
bool isUnion = ILE->getType()->isUnionType();
clang::RecordDecl *Record = ILE->getType()->getAsRecordDecl();
MIRType *Ty = type2Mpl(ILE->getType());
if (ILE->getNumInits() == 0) {
// Avoid generating an empty aggregate
if (Ty->GetSize() == 0) {
return Result(ILE->getBeginLoc());
}
MIRConst *Zero = createZero(Ty);
return Result(Builder->CreateConstval(Zero), ILE->getID(*Context),
ILE->getBeginLoc(), Ty);
}
// Ignore an init list expression for a scalar. For example:
// int x[3] = {{3}};
if (Ty->IsScalarType() && !PrimitiveType(Ty->GetPrimType()).IsVector()) {
return Visit(ILE->getInit(0));
}
if (ILE->isConstantInitializer(*Context, false)) {
// Constant initializers return an agg const and may be used to initialize a
// global.
MIRAggConst *Agg;
if (ILE->isStringLiteralInit()) {
// String literals are a special case. getInitializer will return the
// complete agg, rather than processing it as an array.
MIRConst *Const = getInitializer(Ty, ILE->getInit(0));
ASSERT(Const->GetKind() == kConstAggConst,
"Expected agg const for string literal");
Agg = static_cast<MIRAggConst *>(Const);
} else {
Agg = Builder->GetCurrentFuncCodeMp()->New<MIRAggConst>(*Module, *Ty);
if (isStruct) {
unsigned InitIndex = 0;
for (const auto *FD : Record->fields()) {
if (FD->isUnnamedBitfield()) {
continue;
}
MIRType *InitTy = type2Mpl(ILE->getInit(InitIndex)->getType());
// Skip zero-sized structs
if (InitTy->GetSize() == 0) {
InitIndex++;
continue;
}
MIRConst *Const =
evaluateExprAsConst(ILE->getInit(InitIndex), InitTy);
if (!Const) {
Const = getInitializer(InitTy, ILE->getInit(InitIndex));
}
ASSERT(Const, "Failed to get constant initializer for field");
if (FD->isBitField()) {
ASSERT(Const->GetKind() == kConstInt,
"Expected int for bitfield initialization");
MIRIntConst *IntConst = static_cast<MIRIntConst *>(Const);
unsigned long Mask = (1L << FD->getBitWidthValue(*Context)) - 1;
Const = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
IntConst->GetValue().GetZXTValue() & Mask, *InitTy);
}
// If this agg const will be used as a global initializer, use the
// field index, but if it will be expanded in a function body, use
// the field ID.
FieldID Field;
if (Builder->GetCurrentFunction()) {
Field = FieldMap[Record][0][FD];
} else {
Field = FD->getFieldIndex() + 1;
}
Agg->AddItem(Const, Field);
InitIndex++;
}
} else if (isUnion) {
MIRType *InitTy = type2Mpl(ILE->getInit(0)->getType());
MIRConst *Const = getInitializer(InitTy, ILE->getInit(0));
const clang::FieldDecl *FD = ILE->getInitializedFieldInUnion();
Agg->AddItem(Const, FieldMap[Record][0][FD]);
} else {
for (unsigned i = 0; i < ILE->getNumInits(); ++i) {
MIRType *InitTy = type2Mpl(ILE->getInit(i)->getType());
MIRConst *Const = getInitializer(InitTy, ILE->getInit(i));
Agg->PushBack(Const);
}
}
}
ConstvalNode *ConstNode =
Builder->GetCurrentFuncCodeMp()->New<ConstvalNode>(PTY_agg, Agg);
return Result(ConstNode, ILE->getID(*Context), ILE->getBeginLoc(), Ty);
} else {
Result Res(ILE->getBeginLoc());
// This will get translated into a series of assign nodes. For now, just
// return an intrinsic op node with all of the expressions. For structs and
// unions, the expressions are wrapped in an iread node to store the field
// ID.
MapleVector<BaseNode *> Ops(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
if (isStruct) {
unsigned InitIndex = 0;
for (const auto *FD : Record->fields()) {
// Skip unnamed bitfields
if (FD->isUnnamedBitfield()) {
continue;
}
Result InitRes = Visit(ILE->getInit(InitIndex));
BaseNode *InitNode = getNodeAsRVal(InitRes);
Res.appendStmts(InitRes);
Ops.push_back(Builder->CreateExprIread(
*InitRes.getValueTy(), *Ty, FieldMap[Record][0][FD], InitNode));
InitIndex++;
}
} else if (isUnion) {
Result InitRes = Visit(ILE->getInit(0));
BaseNode *InitNode = getNodeAsRVal(InitRes);
Res.appendStmts(InitRes);
const clang::FieldDecl *FD = ILE->getInitializedFieldInUnion();
Ops.push_back(Builder->CreateExprIread(
*InitRes.getValueTy(), *Ty, FieldMap[Record][0][FD], InitNode));
} else {
for (unsigned i = 0; i < ILE->getNumInits(); ++i) {
Result InitRes = Visit(ILE->getInit(i));
BaseNode *InitNode = getNodeAsRVal(InitRes);
Res.appendStmts(InitRes);
Ops.push_back(InitNode);
}
}
IntrinsicopNode *N = Builder->CreateExprIntrinsicop(
INTRN_UNDEFINED, OP_intrinsicopwithtype, *Ty, Ops);
Res.setNode(N, ILE->getID(*Context), Ty);
return Res;
}
}
Result
Clang2MapleVisitor::VisitIntegerLiteral(const clang::IntegerLiteral *Lit) {
MIRType *Ty = type2Mpl(Lit->getType());
ConstvalNode *Const = Builder->CreateIntConst(Lit->getValue().getSExtValue(),
Ty->GetPrimType());
return Result(Const, Lit->getID(*Context), Lit->getLocation(), Ty);
}
Result Clang2MapleVisitor::VisitMemberExpr(const clang::MemberExpr *ME) {
clang::Expr *BaseExpr = ME->getBase();
clang::QualType QT = BaseExpr->getType();
if (ME->isArrow()) {
QT = QT->getPointeeType();
}
clang::RecordDecl *Record = QT->getAsRecordDecl();
Result BaseRes = Visit(BaseExpr);
const clang::FieldDecl *FD =
llvm::dyn_cast<clang::FieldDecl>(ME->getMemberDecl());
ASSERT(FD, "member is not a FieldDecl");
// Handle member access through a pointer
if (ME->isArrow()) {
BaseNode *Base = getNodeAsRVal(BaseRes);
Result Res(Base, ME->getID(*Context), type2Mpl(BaseExpr->getType()),
type2Mpl(ME->getType()), ME->getExprLoc());
Res.appendStmts(BaseRes);
Res.setBaseRecordDecl(Record);
ASSERT(FieldMap.find(Record) != FieldMap.end() &&
FieldMap[Record].find(0) != FieldMap[Record].end() &&
FieldMap[Record][0].find(FD) != FieldMap[Record][0].end(),
"Structure or field not in map");
Res.setField(FieldMap[Record][0][FD]);
return Res;
} else {
Record = BaseRes.setBaseRecordDecl(Record);
ASSERT(FieldMap.find(Record) != FieldMap.end() &&
FieldMap[Record].find(BaseRes.getField()) !=
FieldMap[Record].end() &&
FieldMap[Record][BaseRes.getField()].find(FD) !=
FieldMap[Record][BaseRes.getField()].end(),
"Structure or field not in map");
BaseRes.setField(FieldMap[Record][BaseRes.getField()][FD]);
BaseRes.setValueTy(type2Mpl(ME->getType()), TypeAttrs(), true);
return BaseRes;
}
}
Result Clang2MapleVisitor::VisitOffsetOfExpr(const clang::OffsetOfExpr *OOE) {
size_t Offset = 0;
clang::QualType QT;
for (unsigned int i = 0; i < OOE->getNumComponents(); i++) {
const clang::OffsetOfNode &OON = OOE->getComponent(i);
switch (OON.getKind()) {
case clang::OffsetOfNode::Field: {
clang::FieldDecl *Field = OON.getField();
QT = Field->getType();
uint64_t FieldOffset = Context->getFieldOffset(Field) / BITS_PER_BYTE;
Offset += FieldOffset;
} break;
case clang::OffsetOfNode::Array: {
const clang::Expr *E = OOE->getIndexExpr(OON.getArrayExprIndex());
clang::Expr::EvalResult IndexVal;
if (E->EvaluateAsInt(IndexVal, *Context)) {
llvm::APSInt Index = IndexVal.Val.getInt();
const clang::Type *ElementType = QT->getPointeeOrArrayElementType();
clang::CharUnits ElementSize = Context->getTypeSizeInChars(ElementType);
Offset += (Index.getExtValue() * ElementSize.getQuantity());
} else {
ASSERT(false, "Non-constant array index in offsetof expressions");
}
} break;
default:
OOE->dump();
ASSERT(false, "Unsupported offsetof");
}
}
return Result(Builder->CreateIntConst(Offset, PTY_u64), OOE->getID(*Context),
OOE->getOperatorLoc(), type2Mpl(OOE->getType()));
}
Result
Clang2MapleVisitor::VisitOpaqueValueExpr(const clang::OpaqueValueExpr *OVE) {
MIRType *Ty = type2Mpl(OVE->getType());
Result SourceRes = Visit(OVE->getSourceExpr());
std::string Name = "_opaque." + std::to_string(OVE->getID(*Context));
MIRSymbol *Temp = Builder->GetLocalDecl(Name);
if (!Temp) {
Temp = Builder->GetOrCreateLocalDecl(Name, *Ty);
StmtNode *TempAssign =
Builder->CreateStmtDassign(*Temp, 0, getNodeAsRVal(SourceRes));
TempAssign->SetSrcPos(sourceLocation2Mpl(OVE->getBeginLoc()));
Result Res(Temp, Ty, OVE->getBeginLoc());
Res.appendStmts(SourceRes);
Res.appendStmtBefore(TempAssign);
return Res;
}
Result Res(Temp, Ty, OVE->getBeginLoc());
Res.appendStmts(SourceRes);
return Res;
}
Result Clang2MapleVisitor::VisitParenExpr(const clang::ParenExpr *PE) {
return Visit(PE->getSubExpr());
}
Result
Clang2MapleVisitor::VisitPredefinedExpr(const clang::PredefinedExpr *PE) {
return Visit(PE->getFunctionName());
}
// FIXME: This needs to be properly implemented
Result Clang2MapleVisitor::VisitShuffleVectorExpr(
const clang::ShuffleVectorExpr *SVE) {
return Visit(SVE->getExpr(0));
}
Result Clang2MapleVisitor::VisitStmtExpr(const clang::StmtExpr *SE) {
Result Res(SE->getBeginLoc());
const clang::CompoundStmt *CS = SE->getSubStmt();
// All of the statements from the compound statement should run before the
// last expression, which should be returned from this visitor.
for (clang::Stmt *S : CS->body()) {
// Do not include the last statement.
if (S == CS->body_back())
break;
Result SRes = Visit(S);
appendResultBefore(Res, SRes);
}
// Now add the last expression as the node returned for this expression.
Result LastRes = Visit(CS->body_back());
Res.appendStmts(LastRes);
Res.setResult(LastRes);
return Res;
}
Result Clang2MapleVisitor::VisitStringLiteral(const clang::StringLiteral *Lit) {
MIRType *Ty = type2Mpl(Lit->getType());
ConstvalNode *ConstVal = nullptr;
if (Lit->isAscii()) {
UStrIdx StrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(
Lit->getString().str());
ConststrNode *Const =
Module->GetMemPool()->New<ConststrNode>(PointerPrimTy, StrIdx);
return Result(Const, Lit->getID(*Context), Lit->getBeginLoc(), Ty);
} else if (Lit->isWide()) {
ConstVal = Module->CurFuncCodeMemPool()->New<ConstvalNode>();
MIRAggConst *Const =
Module->CurFuncCodeMemPool()->New<MIRAggConst>(*Module, *Ty);
for (unsigned int i = 0; i < Lit->getLength(); i++) {
Const->PushBack(GlobalTables::GetIntConstTable().GetOrCreateIntConst(
Lit->getCodeUnit(i),
*GlobalTables::GetTypeTable().GetPrimType(PTY_i32)));
}
ConstVal->SetPrimType(PTY_agg);
ConstVal->SetConstVal(Const);
} else {
Lit->dump();
ASSERT(false, "Unsupported string type");
}
return Result(ConstVal, Lit->getID(*Context), Lit->getBeginLoc(), Ty);
}
Result Clang2MapleVisitor::VisitTypeTraitExpr(const clang::TypeTraitExpr *TTE) {
MIRType *Ty = type2Mpl(TTE->getType());
return Result(Builder->CreateIntConst(TTE->getValue() ? 1 : 0, PTY_i32),
TTE->getID(*Context), TTE->getBeginLoc(), Ty);
}
Result Clang2MapleVisitor::VisitUnaryExprOrTypeTraitExpr(
const clang::UnaryExprOrTypeTraitExpr *UETT) {
MIRType *Ty = type2Mpl(UETT->getType());
clang::QualType QT;
if (UETT->isArgumentType()) {
QT = UETT->getArgumentType();
} else {
QT = UETT->getArgumentExpr()->getType();
}
switch (UETT->getKind()) {
case clang::UETT_SizeOf: {
// C11 specification: ISO/IEC 9899:201x
// $ 6.5.3.4
// "If the type of the operand is a variable length array type,
// the operand is evaluated; otherwise, the operand is not evaluated
// and the result is an integer constant."
if (QT->isVariableArrayType()) {
return buildExprToComputeSizeFromVLA(UETT, QT);
}
clang::CharUnits Size = Context->getTypeSizeInChars(QT);
return Result(
Builder->CreateIntConst(Size.getQuantity(), Ty->GetPrimType()),
UETT->getID(*Context), UETT->getBeginLoc(), Ty);
} break;
case clang::UETT_AlignOf:
case clang::UETT_PreferredAlignOf: {
clang::CharUnits Align = Context->getTypeAlignInChars(QT);
return Result(
Builder->CreateIntConst(Align.getQuantity(), Ty->GetPrimType()),
UETT->getID(*Context), UETT->getRParenLoc(), Ty);
} break;
default:
LogInfo::MapleLogger()
<< "Error: Unhandled kind of UnaryExprOrTypeTraitExpr: "
<< UETT->getKind() << "\n";
CHECK_FATAL(false, "Failing due to unsupported feature");
return Result(UETT->getBeginLoc());
}
}
Result Clang2MapleVisitor::VisitUnaryOperator(const clang::UnaryOperator *UO) {
Result SubExpr = Visit(UO->getSubExpr());
MIRType *ResTy = type2Mpl(UO->getType());
BaseNode *UONode = nullptr;
switch (UO->getOpcode()) {
case clang::UO_Deref: {
// Deref has to be handled by the parent. If it is on the left-hand side of
// an assignment, then the assignment becomes an iassign, but if it is on
// the right, then it needs an iread.
MIRType *SubTy = type2Mpl(UO->getSubExpr()->getType());
Result Res(getNodeAsRVal(SubExpr), UO->getID(*Context), SubTy, ResTy,
UO->getExprLoc());
Res.appendStmts(SubExpr);
return Res;
}
case clang::UO_AddrOf:
UONode = getNodeAsAddrOf(SubExpr);
break;
case clang::UO_Extension:
// This is just a wrapper to indicate a GNU extension.
return SubExpr;
case clang::UO_Plus:
return SubExpr;
case clang::UO_Minus:
UONode = Builder->CreateExprUnary(OP_neg, *ResTy, getNodeAsRVal(SubExpr));
break;
case clang::UO_Not:
UONode = Builder->CreateExprUnary(OP_bnot, *ResTy, getNodeAsRVal(SubExpr));
break;
case clang::UO_LNot:
UONode = exprToNotCond(getNodeAsRVal(SubExpr));
break;
case clang::UO_PostInc:
case clang::UO_PostDec:
case clang::UO_PreInc:
case clang::UO_PreDec: {
size_t IncAmount = 1;
if (ResTy->GetKind() == kTypePointer) {
IncAmount = static_cast<MIRPtrType *>(ResTy)->GetPointedType()->GetSize();
}
PrimitiveType ResPrimTy(ResTy->GetPrimType());
if (ResPrimTy.IsInteger() && !ResPrimTy.IsAddress()) {
ResTy = GlobalTables::GetTypeTable().GetPrimType(
GetRegPrimType(ResTy->GetPrimType()));
}
BaseNode *IncAmountNode;
if (PrimitiveType(ResTy->GetPrimType()).IsInteger()) {
IncAmountNode =
Builder->CreateIntConst(IncAmount, (ResTy->GetKind() == kTypePointer)
? IntPointerTy->GetPrimType()
: ResTy->GetPrimType());
} else if (ResTy->GetPrimType() == PTY_f32) {
IncAmountNode = Builder->CreateFloatConst(1.0f);
} else if (ResTy->GetPrimType() == PTY_f64) {
IncAmountNode = Builder->CreateDoubleConst(1.0);
} else {
ResTy->Dump(0);
ASSERT(false, "Unexpected type of pre/post inc/dec");
}
BaseNode *BinNode =
Builder->CreateExprBinary(UO->isDecrementOp() ? OP_sub : OP_add, *ResTy,
getNodeAsRVal(SubExpr), IncAmountNode);
if (UO->isPrefix()) {
Result Res(getNodeAsRVal(SubExpr), UO->getID(*Context), UO->getExprLoc(),
ResTy, TypeAttrs(), true);
Res.appendStmts(SubExpr);
StmtNode *Assign = nullptr;
if (SubExpr.isSym()) {
Assign = Builder->CreateStmtDassign(*SubExpr.getSym(),
SubExpr.getField(), BinNode);
} else if (SubExpr.isDeref()) {
Assign =
Builder->CreateStmtIassign(*SubExpr.getAddrTy(), SubExpr.getField(),
SubExpr.getAddr(), BinNode);
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled expression in prefix operation\n";
#ifdef DEBUG
getNodeAsRVal(SubExpr)->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
return Result(UO->getExprLoc());
}
Assign->SetSrcPos(sourceLocation2Mpl(UO->getExprLoc()));
Res.appendStmtBefore(Assign);
return Res;
} else {
MIRSymbol *Temp = Builder->GetOrCreateLocalDecl(
"post." + std::to_string(UO->getID(*Context)), *ResTy);
Result Res(Temp, ResTy, UO->getExprLoc(), TypeAttrs(), true);
Res.appendStmts(SubExpr);
StmtNode *TempAssign =
Builder->CreateStmtDassign(*Temp, 0, getNodeAsRVal(SubExpr));
TempAssign->SetSrcPos(sourceLocation2Mpl(UO->getExprLoc()));
Res.appendStmtBefore(TempAssign);
StmtNode *Assign = nullptr;
if (SubExpr.isSym()) {
Assign = Builder->CreateStmtDassign(*SubExpr.getSym(),
SubExpr.getField(), BinNode);
} else if (SubExpr.isDeref()) {
Assign =
Builder->CreateStmtIassign(*SubExpr.getAddrTy(), SubExpr.getField(),
SubExpr.getAddr(), BinNode);
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled expression in postfix operation\n";
#ifdef DEBUG
getNodeAsRVal(SubExpr)->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
Assign->SetSrcPos(sourceLocation2Mpl(UO->getExprLoc()));
Res.appendStmtBefore(Assign);
return Res;
}
}
default:
LogInfo::MapleLogger() << "Error: Unhandled unary opcode\n";
#ifdef DEBUG
UO->dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
Result Res(UONode, UO->getID(*Context), UO->getExprLoc(), ResTy);
Res.appendStmts(SubExpr);
return Res;
}
BaseNode *Clang2MapleVisitor::readField(Result BaseRes, FieldID Field,
MIRType *Ty) {
if (BaseRes.isSym()) {
return Builder->CreateExprDread(*Ty, BaseRes.getField() + Field,
*BaseRes.getSym());
} else {
return Builder->CreateExprIread(*Ty, *BaseRes.getAddrTy(),
BaseRes.getField() + Field,
BaseRes.getNode());
}
}
StmtNode *Clang2MapleVisitor::writeField(Result BaseRes, FieldID Field,
BaseNode *Src) {
if (BaseRes.isSym()) {
return Builder->CreateStmtDassign(*BaseRes.getSym(),
BaseRes.getField() + Field, Src);
} else {
return Builder->CreateStmtIassign(*BaseRes.getAddrTy(),
BaseRes.getField() + Field,
BaseRes.getNode(), Src);
}
}
Result Clang2MapleVisitor::VisitVAArgExpr(const clang::VAArgExpr *VAArg) {
ASSERT(Context->getTargetInfo().getBuiltinVaListKind() ==
clang::TargetInfo::AArch64ABIBuiltinVaList,
"Architecture not yet supported for varargs");
// This sequence of instructions implements the pseducode from
// https://developer.arm.com/documentation/ihi0055/d/?lang=en#the-va-arg-macro
MIRType *ArgTy = type2Mpl(VAArg->getType());
MIRPtrType *PointerToArgTy = static_cast<MIRPtrType *>(
GlobalTables::GetTypeTable().GetOrCreatePointerType(*ArgTy,
PointerPrimTy));
SrcPosition SrcPos = sourceLocation2Mpl(VAArg->getBeginLoc());
MIRType *IntTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_i32));
MIRSymbol *Offs = Builder->GetOrCreateLocalDecl(
"va_offs." + std::to_string(++UnnamedCount), *IntTy);
MIRSymbol *ArgPtr = Builder->GetOrCreateLocalDecl(
"va_arg_ptr." + std::to_string(++UnnamedCount), *PointerToArgTy);
Result Res(VAArg->getBeginLoc());
Result ApRes = Visit(VAArg->getSubExpr());
Res.appendStmts(ApRes);
MIRStructType *ApListTy =
static_cast<MIRStructType *>(type2Mpl(VAArg->getSubExpr()->getType()));
LabelIdx OnStackLabel = Builder->GetOrCreateMIRLabel(
"_vaarg_on_stack." + std::to_string(++UnnamedCount));
LabelIdx EndLabel = Builder->GetOrCreateMIRLabel(
"_vaarg_end." + std::to_string(++UnnamedCount));
// If the argument type is a Composite Type that is larger than 16 bytes,
// then the argument is copied to memory allocated by the caller and the
// argument is replaced by a pointer to the copy.
bool CopyToStack = false;
if (ArgTy->IsStructType() && ArgTy->GetSize() > 16) {
CopyToStack = true;
ArgTy = PointerToArgTy;
PointerToArgTy = static_cast<MIRPtrType *>(
GlobalTables::GetTypeTable().GetOrCreatePointerType(*ArgTy));
}
// if (type passed in general registers)
if (passInGeneralRegisters(ArgTy)) {
// offs = ap.__gr_offs
StmtNode *S =
Builder->CreateStmtDassign(*Offs, 0, readField(ApRes, 4, IntTy));
S->SetSrcPos(SrcPos);
Res.appendStmtBefore(S);
// if (offs >= 0), goto on_stack
ConstvalNode *ZeroNode = Builder->GetConstInt(0);
BaseNode *ReadOffs = Builder->CreateExprDread(*IntTy, 0, *Offs);
BaseNode *Cond =
Builder->CreateExprCompare(OP_ge, *IntTy, *IntTy, ReadOffs, ZeroNode);
StmtNode *CondBranch =
Builder->CreateStmtCondGoto(Cond, OP_brtrue, OnStackLabel);
CondBranch->SetSrcPos(SrcPos);
Res.appendStmtBefore(CondBranch);
// if (alignof(type) > 8) offs = (offs + 15) & -16;
if (ArgTy->GetAlign() > 8) {
BaseNode *SumNode = Builder->CreateExprBinary(
OP_add, *IntTy, Builder->CreateExprDread(*IntTy, 0, *Offs),
Builder->GetConstInt(15));
BaseNode *AndNode = Builder->CreateExprBinary(OP_band, *IntTy, SumNode,
Builder->GetConstInt(-16));
StmtNode *Assign = Builder->CreateStmtDassign(*Offs, 0, AndNode);
Assign->SetSrcPos(SrcPos);
Res.appendStmtBefore(Assign);
}
// nreg = (sizeof(type) + 7) / 8;
int Nreg = (ArgTy->GetSize() + 7) / 8;
// ap.__gr_offs = offs + (nreg * 8);
BaseNode *OffsSum = Builder->CreateExprBinary(
OP_add, *IntTy, Builder->CreateExprDread(*IntTy, 0, *Offs),
Builder->GetConstInt(Nreg * 8));
StmtNode *UpdateOffs = writeField(ApRes, 4, OffsSum);
UpdateOffs->SetSrcPos(SrcPos);
Res.appendStmtBefore(UpdateOffs);
// if (ap.__gr_offs > 0) goto on_stack;
ZeroNode = Builder->GetConstInt(0);
ReadOffs = readField(ApRes, 4, IntTy);
Cond =
Builder->CreateExprCompare(OP_gt, *IntTy, *IntTy, ReadOffs, ZeroNode);
CondBranch = Builder->CreateStmtCondGoto(Cond, OP_brtrue, OnStackLabel);
CondBranch->SetSrcPos(SrcPos);
Res.appendStmtBefore(CondBranch);
// return *(type *)(ap.__gr_top + offs);
BaseNode *ArgAddr = Builder->CreateExprBinary(
OP_add, *ApListTy->GetFieldType(2),
readField(ApRes, 2, ApListTy->GetFieldType(2)),
Builder->CreateExprTypeCvt(OP_cvt, *ApListTy->GetFieldType(2), *IntTy,
Builder->CreateExprDread(*IntTy, 0, *Offs)));
StmtNode *AssignPtr = Builder->CreateStmtDassign(*ArgPtr, 0, ArgAddr);
AssignPtr->SetSrcPos(SrcPos);
Res.appendStmtBefore(AssignPtr);
GotoNode *GoToEnd = Builder->CreateStmtGoto(OP_goto, EndLabel);
GoToEnd->SetSrcPos(SrcPos);
Res.appendStmtBefore(GoToEnd);
}
// else if (type is an HFA or an HVA)
// TODO: Handle HVA
else if (MIRType *ElemTy = isHomogenousAggregate(ArgTy)) {
// offs = ap.__vr_offs
StmtNode *S =
Builder->CreateStmtDassign(*Offs, 0, readField(ApRes, 5, IntTy));
S->SetSrcPos(SrcPos);
Res.appendStmtBefore(S);
// if (offs >= 0), goto on_stack
ConstvalNode *ZeroNode = Builder->GetConstInt(0);
BaseNode *ReadOffs = Builder->CreateExprDread(*IntTy, 0, *Offs);
BaseNode *Cond =
Builder->CreateExprCompare(OP_ge, *IntTy, *IntTy, ReadOffs, ZeroNode);
StmtNode *CondBranch =
Builder->CreateStmtCondGoto(Cond, OP_brtrue, OnStackLabel);
CondBranch->SetSrcPos(SrcPos);
Res.appendStmtBefore(CondBranch);
// nreg = sizeof(type) / sizeof(ftype);
int Nreg = ArgTy->GetSize() / ElemTy->GetSize();
// ap.__vr_offs = offs + (nreg * 16);
BaseNode *OffsSum = Builder->CreateExprBinary(
OP_add, *IntTy, Builder->CreateExprDread(*IntTy, 0, *Offs),
Builder->GetConstInt(Nreg * 16));
StmtNode *UpdateOffs = writeField(ApRes, 5, OffsSum);
UpdateOffs->SetSrcPos(SrcPos);
Res.appendStmtBefore(UpdateOffs);
// if (ap.__vr_offs > 0) goto on_stack;
ZeroNode = Builder->GetConstInt(0);
ReadOffs = readField(ApRes, 5, IntTy);
Cond =
Builder->CreateExprCompare(OP_gt, *IntTy, *IntTy, ReadOffs, ZeroNode);
CondBranch = Builder->CreateStmtCondGoto(Cond, OP_brtrue, OnStackLabel);
CondBranch->SetSrcPos(SrcPos);
Res.appendStmtBefore(CondBranch);
// for (i = 0; i < nreg; i++, offs += 16)
// ha.field[i] = *((ftype *)(ap.__vr_top + offs));
// return ha;
BaseNode *ArgAddr = Builder->CreateExprBinary(
OP_add, *ApListTy->GetFieldType(2),
readField(ApRes, 3, ApListTy->GetFieldType(3)),
Builder->CreateExprTypeCvt(OP_cvt, *ApListTy->GetFieldType(3), *IntTy,
Builder->CreateExprDread(*IntTy, 0, *Offs)));
StmtNode *AssignPtr = Builder->CreateStmtDassign(*ArgPtr, 0, ArgAddr);
AssignPtr->SetSrcPos(SrcPos);
Res.appendStmtBefore(AssignPtr);
MIRStructType *StructTy = static_cast<MIRStructType *>(ArgTy);
MIRSymbol *Ha = Builder->CreateLocalDecl(
"vaarg_ha." + std::to_string(++UnnamedCount), *StructTy);
unsigned SrcOffset = 0;
for (size_t FID = 1; FID <= StructTy->NumberOfFieldIDs(); FID++) {
MIRType *FieldTy = StructTy->GetFieldType(FID);
MIRType *PointerToFieldTy =
GlobalTables::GetTypeTable().GetOrCreatePointerType(*FieldTy,
PointerPrimTy);
if (FieldTy->IsStructType()) {
continue;
}
if (FieldTy->GetKind() == kTypeArray) {
MIRArrayType *ArrayTy = static_cast<MIRArrayType *>(FieldTy);
MIRPtrType *PointerToElemTy =
static_cast<MIRPtrType*>(GlobalTables::GetTypeTable().GetOrCreatePointerType(*ElemTy, PointerPrimTy));
for (size_t ElemID = 0; ElemID < ArrayTy->GetSizeArrayItem(0);
ElemID++) {
BaseNode *BaseAddr = Builder->CreateExprAddrof(FID, *Ha);
BaseAddr->SetPrimType(PointerPrimTy);
BaseNode *IndexNode =
Builder->CreateIntConst(ElemID, IntPointerTy->GetPrimType());
ArrayNode *Array =
Builder->CreateExprArray(*ArrayTy, BaseAddr, IndexNode);
Array->SetBoundsCheck(false);
Array->SetPrimType(PointerPrimTy);
StmtNode *AssignElem = Builder->CreateStmtIassign(
*PointerToElemTy, 0, Array,
Builder->CreateExprIread(
*PointerToElemTy->GetPointedType(), *PointerToElemTy, 0,
Builder->CreateExprBinary(
OP_add, *PointerToElemTy,
Builder->CreateExprDread(*PointerToArgTy, *ArgPtr),
Builder->CreateIntConst(SrcOffset, PointerPrimTy))));
AssignElem->SetSrcPos(SrcPos);
Res.appendStmtBefore(AssignElem);
SrcOffset += 16;
}
} else {
StmtNode *AssignField = Builder->CreateStmtDassign(
*Ha, FID,
Builder->CreateExprIread(
*FieldTy, *PointerToFieldTy, 0,
Builder->CreateExprBinary(
OP_add, *PointerToFieldTy,
Builder->CreateExprDread(*PointerToArgTy, *ArgPtr),
Builder->CreateIntConst(SrcOffset, PointerPrimTy))));
AssignField->SetSrcPos(SrcPos);
Res.appendStmtBefore(AssignField);
SrcOffset += 16;
}
}
AssignPtr = Builder->CreateStmtDassign(*ArgPtr, 0,
Builder->CreateExprAddrof(0, *Ha));
AssignPtr->SetSrcPos(SrcPos);
Res.appendStmtBefore(AssignPtr);
GotoNode *GoToEnd = Builder->CreateStmtGoto(OP_goto, EndLabel);
GoToEnd->SetSrcPos(SrcPos);
Res.appendStmtBefore(GoToEnd);
}
// else if (type passed in fp/simd registers)
// TODO: handle simd registers
else if (passInFloatRegisters(ArgTy)) {
// offs = ap.__vr_offs
StmtNode *S =
Builder->CreateStmtDassign(*Offs, 0, readField(ApRes, 5, IntTy));
S->SetSrcPos(SrcPos);
Res.appendStmtBefore(S);
// if (offs >= 0), goto on_stack
ConstvalNode *ZeroNode = Builder->GetConstInt(0);
BaseNode *ReadOffs = Builder->CreateExprDread(*IntTy, 0, *Offs);
BaseNode *Cond =
Builder->CreateExprCompare(OP_ge, *IntTy, *IntTy, ReadOffs, ZeroNode);
StmtNode *CondBranch =
Builder->CreateStmtCondGoto(Cond, OP_brtrue, OnStackLabel);
CondBranch->SetSrcPos(SrcPos);
Res.appendStmtBefore(CondBranch);
// nreg = (sizeof(type) + 15) / 16;
// Note that we use 7, 8 here instead of 15, 16. This is because the
// sizeof a double is 8, but for varargs, it uses 16.
int Nreg = (ArgTy->GetSize() + 7) / 8;
// ap.__vr_offs = offs + (nreg * 16);
BaseNode *OffsSum = Builder->CreateExprBinary(
OP_add, *IntTy, Builder->CreateExprDread(*IntTy, 0, *Offs),
Builder->GetConstInt(Nreg * 16));
StmtNode *UpdateOffs = writeField(ApRes, 5, OffsSum);
UpdateOffs->SetSrcPos(SrcPos);
Res.appendStmtBefore(UpdateOffs);
// if (ap.__vr_offs > 0) goto on_stack;
ZeroNode = Builder->GetConstInt(0);
ReadOffs = readField(ApRes, 5, IntTy);
Cond =
Builder->CreateExprCompare(OP_gt, *IntTy, *IntTy, ReadOffs, ZeroNode);
CondBranch = Builder->CreateStmtCondGoto(Cond, OP_brtrue, OnStackLabel);
CondBranch->SetSrcPos(SrcPos);
Res.appendStmtBefore(CondBranch);
// return *(type *)(ap.__vr_top + offs);
BaseNode *ArgAddr = Builder->CreateExprBinary(
OP_add, *ApListTy->GetFieldType(2),
readField(ApRes, 3, ApListTy->GetFieldType(3)),
Builder->CreateExprTypeCvt(OP_cvt, *ApListTy->GetFieldType(3), *IntTy,
Builder->CreateExprDread(*IntTy, 0, *Offs)));
StmtNode *AssignPtr = Builder->CreateStmtDassign(*ArgPtr, 0, ArgAddr);
AssignPtr->SetSrcPos(SrcPos);
Res.appendStmtBefore(AssignPtr);
GotoNode *GoToEnd = Builder->CreateStmtGoto(OP_goto, EndLabel);
GoToEnd->SetSrcPos(SrcPos);
Res.appendStmtBefore(GoToEnd);
}
// on_stack:
StmtNode *LabelStmt = Builder->CreateStmtLabel(OnStackLabel);
LabelStmt->SetSrcPos(SrcPos);
Res.appendStmtBefore(LabelStmt);
// intptr_t arg = ap.__stack;
StmtNode *StackBase =
Builder->CreateStmtDassign(*ArgPtr, 0, readField(ApRes, 1, IntPointerTy));
StackBase->SetSrcPos(SrcPos);
Res.appendStmtBefore(StackBase);
// if (alignof(type) > 8) arg = (arg + 15) & -16;
if (ArgTy->GetAlign() > 8) {
BaseNode *SumNode = Builder->CreateExprBinary(
OP_add, *IntPointerTy,
Builder->CreateExprDread(*IntPointerTy, 0, *ArgPtr),
Builder->GetConstInt(15));
BaseNode *AndNode = Builder->CreateExprBinary(
OP_band, *IntPointerTy, SumNode, Builder->GetConstInt(-16));
StmtNode *Assign = Builder->CreateStmtDassign(*ArgPtr, 0, AndNode);
Assign->SetSrcPos(SrcPos);
Res.appendStmtBefore(Assign);
}
// ap.__stack = (void *)((arg + sizeof(type) + 7) & -8);
BaseNode *CalcArg = Builder->CreateExprBinary(
OP_add, *IntPointerTy,
Builder->CreateExprDread(*IntPointerTy, 0, *ArgPtr),
Builder->CreateIntConst(ArgTy->GetSize() + 7,
IntPointerTy->GetPrimType()));
CalcArg = Builder->CreateExprBinary(
OP_band, *IntPointerTy, CalcArg,
Builder->CreateIntConst(-8, IntPointerTy->GetPrimType()));
StmtNode *StackAssign = writeField(ApRes, 1, CalcArg);
StackAssign->SetSrcPos(SrcPos);
Res.appendStmtBefore(StackAssign);
// return *(type *)arg;
// end:
LabelStmt = Builder->CreateStmtLabel(EndLabel);
LabelStmt->SetSrcPos(SrcPos);
Res.appendStmtBefore(LabelStmt);
BaseNode *Arg = Builder->CreateExprIread(
*ArgTy, *PointerToArgTy, 0,
Builder->CreateExprDread(*PointerToArgTy, 0, *ArgPtr));
// If the argument type is a Composite Type that is larger than 16 bytes,
// then the argument is copied to memory allocated by the caller and the
// argument is replaced by a pointer to the copy.
if (CopyToStack) {
PointerToArgTy = static_cast<MIRPtrType *>(ArgTy);
ArgTy = PointerToArgTy->GetPointedType();
Arg = Builder->CreateExprIread(*ArgTy, *PointerToArgTy, 0, Arg);
}
Res.setNode(Arg, VAArg->getID(*Context), ArgTy);
return Res;
}
//
// Private methods
//
void Clang2MapleVisitor::setupBuiltinTypes(void) {
std::map<const clang::Type *, TyIdx> BuiltinTypes = {
{Context->BoolTy.getTypePtr(),
GlobalTables::GetTypeTable().GetUInt8()->GetTypeIndex()},
{Context->CharTy.getTypePtr(),
Context->CharTy->isSignedIntegerType()
? GlobalTables::GetTypeTable().GetInt8()->GetTypeIndex()
: GlobalTables::GetTypeTable().GetUInt8()->GetTypeIndex()},
{Context->SignedCharTy.getTypePtr(),
GlobalTables::GetTypeTable().GetInt8()->GetTypeIndex()},
{Context->ShortTy.getTypePtr(),
GlobalTables::GetTypeTable().GetInt16()->GetTypeIndex()},
{Context->IntTy.getTypePtr(),
GlobalTables::GetTypeTable().GetInt32()->GetTypeIndex()},
{Context->LongLongTy.getTypePtr(),
GlobalTables::GetTypeTable().GetInt64()->GetTypeIndex()},
// __int128 is handled as an i64
{Context->Int128Ty.getTypePtr(),
GlobalTables::GetTypeTable().GetInt64()->GetTypeIndex()},
{Context->UnsignedCharTy.getTypePtr(),
GlobalTables::GetTypeTable().GetUInt8()->GetTypeIndex()},
{Context->UnsignedShortTy.getTypePtr(),
GlobalTables::GetTypeTable().GetUInt16()->GetTypeIndex()},
{Context->UnsignedIntTy.getTypePtr(),
GlobalTables::GetTypeTable().GetUInt32()->GetTypeIndex()},
{Context->UnsignedLongLongTy.getTypePtr(),
GlobalTables::GetTypeTable().GetUInt64()->GetTypeIndex()},
// unsigned __int128 is handled as a u64
{Context->UnsignedInt128Ty.getTypePtr(),
GlobalTables::GetTypeTable().GetUInt64()->GetTypeIndex()},
// __fp16 is handled as a float
{Context->HalfTy.getTypePtr(),
GlobalTables::GetTypeTable().GetFloat()->GetTypeIndex()},
{Context->FloatTy.getTypePtr(),
GlobalTables::GetTypeTable().GetFloat()->GetTypeIndex()},
{Context->DoubleTy.getTypePtr(),
GlobalTables::GetTypeTable().GetDouble()->GetTypeIndex()},
// long double is handled as a double
{Context->LongDoubleTy.getTypePtr(),
GlobalTables::GetTypeTable().GetDouble()->GetTypeIndex()},
{Context->FloatComplexTy.getTypePtr(), TyIdx(PTY_c64)},
{Context->DoubleComplexTy.getTypePtr(), TyIdx(PTY_c128)},
{Context->VoidTy.getTypePtr(),
GlobalTables::GetTypeTable().GetVoid()->GetTypeIndex()}};
TypeMap.insert(BuiltinTypes.begin(), BuiltinTypes.end());
if (Context->getTypeSize(Context->LongTy) == 32) {
TypeMap[Context->LongTy.getTypePtr()] =
GlobalTables::GetTypeTable().GetInt32()->GetTypeIndex();
TypeMap[Context->UnsignedLongTy.getTypePtr()] =
GlobalTables::GetTypeTable().GetUInt32()->GetTypeIndex();
PointerPrimTy = PTY_a32;
IntPointerTy = GlobalTables::GetTypeTable().GetUInt32();
} else {
TypeMap[Context->LongTy.getTypePtr()] =
GlobalTables::GetTypeTable().GetInt64()->GetTypeIndex();
TypeMap[Context->UnsignedLongTy.getTypePtr()] =
GlobalTables::GetTypeTable().GetUInt64()->GetTypeIndex();
PointerPrimTy = PTY_a64;
IntPointerTy = GlobalTables::GetTypeTable().GetUInt64();
}
}
TyIdx Clang2MapleVisitor::type2MplIdx(clang::QualType QT, bool needComplete) {
const clang::Type *Ty = QT.getDesugaredType(*Context).getTypePtr();
auto it = TypeMap.find(Ty);
if (it != TypeMap.end()) {
return it->second;
}
// Create a new function type
if (const clang::FunctionType *FT = llvm::dyn_cast<clang::FunctionType>(Ty)) {
TyIdx ReturnTy = type2MplIdx(FT->getReturnType());
std::vector<TyIdx> ParamTypeList;
std::vector<TypeAttrs> ParamAttrsList;
bool IsVariadic = false;
bool IsFirstArgRet = false;
if (GlobalTables::GetTypeTable().GetTypeFromTyIdx(ReturnTy)->GetSize() >
16) {
MIRType *ReturnTyPtr =
GlobalTables::GetTypeTable().GetOrCreatePointerType(ReturnTy,
PointerPrimTy);
ParamTypeList.push_back(ReturnTyPtr->GetTypeIndex());
IsFirstArgRet = true;
TypeAttrs Attrs;
if (isOneElementVector(FT->getReturnType())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
// TODO: Add other attributes
ParamAttrsList.push_back(Attrs);
ReturnTy = GlobalTables::GetTypeTable().GetVoid()->GetTypeIndex();
}
if (const clang::FunctionProtoType *FPT =
llvm::dyn_cast<clang::FunctionProtoType>(Ty)) {
for (const clang::QualType &Param : FPT->param_types()) {
ParamTypeList.push_back(type2MplIdx(Param));
TypeAttrs Attrs;
if (isOneElementVector(Param.getTypePtr())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
// TODO: Add other attributes
ParamAttrsList.push_back(Attrs);
}
IsVariadic = FPT->isVariadic();
}
MIRType *MTy = GlobalTables::GetTypeTable().GetOrCreateFunctionType(
ReturnTy, ParamTypeList, ParamAttrsList, IsVariadic);
if (IsFirstArgRet) {
static_cast<MIRFuncType *>(MTy)->SetFirstArgReturn();
}
TypeMap.insert({FT, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (const clang::PointerType *PtrTy =
llvm::dyn_cast<clang::PointerType>(Ty)) {
// Create a pointer type from the pointee type
TyIdx PointeeTyIdx = type2MplIdx(PtrTy->getPointeeType(), false);
MIRPtrType *MTy = static_cast<MIRPtrType *>(
GlobalTables::GetTypeTable().GetOrCreatePointerType(PointeeTyIdx,
PointerPrimTy));
MTy->SetPrimType(PointerPrimTy);
// If this is a pointer to a type which is not yet fully-defined, record
// it to be updated later.
if (GlobalTables::GetTypeTable()
.GetTypeFromTyIdx(PointeeTyIdx)
->GetKind() == kTypeStructIncomplete) {
UnresolvedTypes.insert({PtrTy->getPointeeType()->getAsRecordDecl(), MTy});
}
TypeAttrs Attrs;
// Get alignment from the pointee type
if (unsigned int AlignmentBits =
Context->getTypeAlignIfKnown(PtrTy->getPointeeType())) {
if (AlignmentBits >
Context->getTypeUnadjustedAlign(PtrTy->getPointeeType())) {
Attrs.SetAlign(AlignmentBits / BITS_PER_BYTE);
}
}
if (TypeHasMayAlias(PtrTy->getPointeeType())) {
Attrs.SetAttr(ATTR_may_alias);
}
if (isOneElementVector(PtrTy->getPointeeType())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
MTy->SetTypeAttrs(Attrs);
TypeMap.insert({PtrTy, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (const clang::ReferenceType *RefTy =
llvm::dyn_cast<clang::ReferenceType>(Ty)) {
TyIdx BaseTyIdx = type2MplIdx(RefTy->getPointeeType(), false);
MIRType *MTy = GlobalTables::GetTypeTable().GetOrCreatePointerType(
BaseTyIdx, PointerPrimTy);
TypeMap.insert({PtrTy, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (const clang::ConstantArrayType *ArrTy =
llvm::dyn_cast<clang::ConstantArrayType>(Ty)) {
// Create a constant array type based on a known type
#ifdef MULTIDIM_ARRAYS
std::vector<maple::uint32> SizeArray;
clang::QualType BaseTy = QT.getDesugaredType(*Context);
while (BaseTy->isConstantArrayType()) {
ArrTy = llvm::dyn_cast<clang::ConstantArrayType>(BaseTy);
const llvm::APInt &APSize = ArrTy->getSize();
uint32_t Size = (uint32_t)APSize.getSExtValue();
SizeArray.push_back(Size);
BaseTy = ArrTy->getElementType().getDesugaredType(*Context);
}
MIRArrayType ArrayTy(type2MplIdx(BaseTy), SizeArray);
#else // !MULTIDIM_ARRAYS
TyIdx BaseTyIdx = type2MplIdx(ArrTy->getElementType());
const llvm::APInt &APSize = ArrTy->getSize();
uint32_t Size = (uint32_t)APSize.getSExtValue();
std::vector<maple::uint32> SizeArray{Size};
MIRArrayType ArrayTy(BaseTyIdx, SizeArray);
#endif // MULTIDIM_ARRAYS
MIRArrayType *MTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(ArrayTy));
TypeAttrs Attrs = MTy->GetTypeAttrs();
// Get alignment from the element type
if (unsigned int AlignmentBits =
Context->getTypeAlignIfKnown(ArrTy->getElementType())) {
if (AlignmentBits >
Context->getTypeUnadjustedAlign(ArrTy->getElementType())) {
Attrs.SetAlign(AlignmentBits / BITS_PER_BYTE);
}
}
if (isOneElementVector(ArrTy->getElementType())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
MTy->SetTypeAttrs(Attrs);
TypeMap.insert({Ty, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (const clang::VariableArrayType *VarArrTy =
llvm::dyn_cast<clang::VariableArrayType>(Ty)) {
// Convert this to a pointer to the element type
TyIdx BaseTyIdx = type2MplIdx(VarArrTy->getElementType());
MIRPtrType *MTy = static_cast<MIRPtrType *>(
GlobalTables::GetTypeTable().GetOrCreatePointerType(BaseTyIdx,
PointerPrimTy));
MTy->SetPrimType(PointerPrimTy);
TypeAttrs Attrs;
// Get alignment from the element type
if (unsigned int AlignmentBits =
Context->getTypeAlignIfKnown(VarArrTy->getElementType())) {
if (AlignmentBits >
Context->getTypeUnadjustedAlign(VarArrTy->getElementType())) {
Attrs.SetAlign(AlignmentBits / BITS_PER_BYTE);
}
}
if (isOneElementVector(VarArrTy->getElementType())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
MTy->SetTypeAttrs(Attrs);
TypeMap.insert({VarArrTy, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (const clang::IncompleteArrayType *IncArrTy =
llvm::dyn_cast<clang::IncompleteArrayType>(Ty)) {
// For an incomplete array type, assume a length of 1
#ifdef MULTIDIM_ARRAYS
std::vector<maple::uint32> SizeArray{1};
clang::QualType BaseTy =
IncArrTy->getElementType().getDesugaredType(*Context);
while (BaseTy->isConstantArrayType()) {
ArrTy = llvm::dyn_cast<clang::ConstantArrayType>(BaseTy);
const llvm::APInt &APSize = ArrTy->getSize();
uint32_t Size = (uint32_t)APSize.getSExtValue();
SizeArray.push_back(Size);
BaseTy = ArrTy->getElementType().getDesugaredType(*Context);
}
TyIdx BaseTyIdx = type2MplIdx(BaseTy);
#else // !MULTIDIM_ARRAYS
TyIdx BaseTyIdx = type2MplIdx(IncArrTy->getElementType());
std::vector<maple::uint32> SizeArray{1};
#endif // MULTIDIM_ARRAYS
MIRArrayType ArrayTy(BaseTyIdx, SizeArray);
MIRArrayType *MTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(ArrayTy));
TypeAttrs Attrs = MTy->GetTypeAttrs();
// Get alignment from the element type
if (unsigned int AlignmentBits =
Context->getTypeAlignIfKnown(IncArrTy->getElementType())) {
if (AlignmentBits >
Context->getTypeUnadjustedAlign(IncArrTy->getElementType())) {
Attrs.SetAlign(AlignmentBits / BITS_PER_BYTE);
}
}
if (isOneElementVector(IncArrTy->getElementType())) {
Attrs.SetAttr(ATTR_oneelem_simd);
}
MTy->SetTypeAttrs(Attrs);
TypeMap.insert({IncArrTy, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (Ty->isRecordType()) {
// Handle an undefined struct
clang::RecordDecl *Record = Ty->getAsRecordDecl();
// This could either be a forward reference, or a struct defined inline. If
// it is a forward reference, create it as an incomplete struct for now. If
// it is defined, then create a proper type for it.
if (needComplete && !Ty->isIncompleteType()) {
VisitRecordDecl(Record);
return TypeMap[Ty];
}
std::string TypeName = Record->getName().str();
MIRStructType Struct(kTypeStructIncomplete);
MIRType *MTy = GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(Struct);
GStrIdx StrIdx =
GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(TypeName);
MTy->SetNameStrIdx(StrIdx);
Module->GetTypeNameTab()->SetGStrIdxToTyIdx(StrIdx, MTy->GetTypeIndex());
Module->PushbackTypeDefOrder(StrIdx);
TypeMap.insert({Ty, MTy->GetTypeIndex()});
return MTy->GetTypeIndex();
} else if (Ty->isEnumeralType()) {
const clang::EnumType *EnumTy = llvm::dyn_cast<clang::EnumType>(Ty);
clang::QualType QT = EnumTy->getDecl()->getIntegerType();
TyIdx TI = type2MplIdx(QT);
TypeMap.insert({Ty, TI});
return TI;
} else if (Ty->isVectorType()) {
const clang::VectorType *VecTy = llvm::dyn_cast<clang::VectorType>(Ty);
MIRType *ElemTy = type2Mpl(VecTy->getElementType());
unsigned NumElements = VecTy->getNumElements();
TyIdx TI(0);
switch (ElemTy->GetPrimType()) {
case PTY_i64:
if (NumElements == 1) {
TI = GlobalTables::GetTypeTable().GetPrimType(PTY_i64)->GetTypeIndex();
} else if (NumElements == 2) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v2i64)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_i32:
if (NumElements == 1) {
TI = GlobalTables::GetTypeTable().GetPrimType(PTY_i64)->GetTypeIndex();
} else if (NumElements == 2) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v2i32)->GetTypeIndex();
} else if (NumElements == 4) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v4i32)->GetTypeIndex();
} else if (NumElements == 8) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v8i16)->GetTypeIndex();
} else if (NumElements == 16) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v16i8)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_i16:
if (NumElements == 4) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v4i16)->GetTypeIndex();
} else if (NumElements == 8) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v8i16)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_i8:
if (NumElements == 8) {
TI = GlobalTables::GetTypeTable().GetPrimType(PTY_v8i8)->GetTypeIndex();
} else if (NumElements == 16) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v16i8)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_u64:
if (NumElements == 1) {
TI = GlobalTables::GetTypeTable().GetPrimType(PTY_u64)->GetTypeIndex();
} else if (NumElements == 2) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v2u64)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_u32:
if (NumElements == 2) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v2u32)->GetTypeIndex();
} else if (NumElements == 4) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v4u32)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_u16:
if (NumElements == 4) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v4u16)->GetTypeIndex();
} else if (NumElements == 8) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v8u16)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_u8:
if (NumElements == 8) {
TI = GlobalTables::GetTypeTable().GetPrimType(PTY_v8u8)->GetTypeIndex();
} else if (NumElements == 16) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v16u8)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_f64:
if (NumElements == 1) {
TI = GlobalTables::GetTypeTable().GetPrimType(PTY_f64)->GetTypeIndex();
} else if (NumElements == 2) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v2f64)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
case PTY_f32:
if (NumElements == 2) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v2f32)->GetTypeIndex();
} else if (NumElements == 4) {
TI =
GlobalTables::GetTypeTable().GetPrimType(PTY_v4f32)->GetTypeIndex();
} else {
Ty->dump();
ASSERT(false, "Unsupported vector type");
}
break;
default:
Ty->dump();
ASSERT(false, "Unsupported vector type");
break;
}
TypeMap.insert({Ty, TI});
return TI;
}
Ty->dump();
ASSERT(false, "Failed to convert type");
return TyIdx(0);
}
MIRType *Clang2MapleVisitor::type2Mpl(clang::QualType QT) {
return GlobalTables::GetTypeTable().GetTypeFromTyIdx(type2MplIdx(QT));
}
int Clang2MapleVisitor::fileID2Mpl(clang::FileID FID) {
auto it = FileMap.find(FID.getHashValue());
if (it != FileMap.end()) {
return it->second;
}
// If this FileID is not in the map, create it
const clang::FileEntry *File =
Context->getSourceManager().getFileEntryForID(FID);
std::string FileName;
if (File) {
FileName = File->getName().str().c_str();
} else {
FileName = "invalid_file";
}
GStrIdx StrIdx =
GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(FileName);
int Idx = FileIdx++;
Module->PushbackFileInfo(MIRInfoPair(StrIdx, Idx));
FileMap.insert({FID.getHashValue(), Idx});
return Idx;
}
MIRSymbol *Clang2MapleVisitor::decl2Mpl(const clang::Decl *D) {
auto it = DeclMap.find(D);
if (it != DeclMap.end()) {
return it->second;
}
// Check for use of an implicit decl. This shows up for builtins like
// `abort`.
if (D->isImplicit()) {
return Visit(D);
}
D->dump();
ASSERT(false, "Failed to find decl");
return nullptr;
}
SrcPosition Clang2MapleVisitor::sourceLocation2Mpl(clang::SourceLocation Loc) {
SrcPosition SrcPos;
if (!Loc.isValid()) {
return SrcPos;
}
clang::SourceManager &SM = Context->getSourceManager();
if (Loc.isFileID()) {
clang::PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid()) {
return SrcPos;
}
SrcPos.SetFileNum(fileID2Mpl(PLoc.getFileID()));
SrcPos.SetLineNum(PLoc.getLine());
SrcPos.SetColumn(PLoc.getColumn());
return SrcPos;
}
return sourceLocation2Mpl(SM.getExpansionLoc(Loc));
}
void Clang2MapleVisitor::addStmtToBlock(BlockNode *Block, StmtNode *SNode) {
// Merge block into this one
if (SNode->GetOpCode() == OP_block) {
BlockNode *InnerBlock = static_cast<BlockNode *>(SNode);
Block->AppendStatementsFromBlock(*InnerBlock);
} else {
Block->AddStatement(SNode);
}
}
void Clang2MapleVisitor::addToBlock(BlockNode *Block, Result &Res) {
for (Result::iterator It = Res.beginStmtsBefore(); It != Res.endStmtsBefore();
++It) {
Block->AddStatement(*It);
}
if (!Res.mayDrop()) {
if (StmtNode *SNode = getNodeAsStmt(Res)) {
addStmtToBlock(Block, SNode);
}
}
for (Result::iterator It = Res.beginStmtsAfter(); It != Res.endStmtsAfter();
++It) {
Block->AddStatement(*It);
}
}
BaseNode *Clang2MapleVisitor::exprToCond(BaseNode *Cond) {
if (kOpcodeInfo.IsCompare(Cond->op))
return Cond;
if (Cond->op == OP_cand || Cond->op == OP_cior)
return Cond;
MIRType *IntTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_i32));
MIRType *OpndTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(Cond->GetPrimType()));
switch (Cond->GetPrimType()) {
case PTY_i8:
case PTY_i16:
case PTY_i32:
case PTY_i64:
case PTY_u8:
case PTY_u16:
case PTY_u32:
case PTY_u64:
case PTY_a32:
case PTY_a64: {
ConstvalNode *Zero = Builder->CreateIntConst(0, Cond->GetPrimType());
return Builder->CreateExprCompare(OP_ne, *IntTy, *OpndTy, Cond, Zero);
}
case PTY_f32: {
ConstvalNode *Zero = Builder->CreateFloatConst(0.0f);
return Builder->CreateExprCompare(OP_ne, *IntTy, *OpndTy, Cond, Zero);
}
case PTY_f64: {
ConstvalNode *Zero = Builder->CreateDoubleConst(0.0);
return Builder->CreateExprCompare(OP_ne, *IntTy, *OpndTy, Cond, Zero);
}
case PTY_ptr: {
ConstvalNode *Zero = Builder->CreateIntConst(0, PointerPrimTy);
return Builder->CreateExprCompare(OP_ne, *IntTy, *OpndTy, Cond, Zero);
}
default:
LogInfo::MapleLogger() << "Warning: Unhandled type in exprToCond\n";
#ifdef DEBUG
Cond->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
return Cond;
}
}
static Opcode notCondOperator(Opcode op) {
switch (op) {
case OP_eq:
return OP_ne;
case OP_ge:
return OP_lt;
case OP_gt:
return OP_le;
case OP_le:
return OP_gt;
case OP_lt:
return OP_ge;
case OP_ne:
return OP_eq;
default:
LogInfo::MapleLogger() << "Error: Unhandled operator in notCondOperator: "
<< op << "\n";
CHECK_FATAL(false, "Failing due to unsupported feature");
return OP_undef;
}
}
BaseNode *Clang2MapleVisitor::exprToNotCond(BaseNode *Cond) {
if (kOpcodeInfo.IsCompare(Cond->op)) {
CompareNode *Compare = static_cast<CompareNode *>(Cond);
Compare->SetOpCode(notCondOperator(Compare->GetOpCode()));
return Cond;
}
MIRType *IntTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_i32));
MIRType *OpndTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(Cond->GetPrimType()));
switch (Cond->GetPrimType()) {
case PTY_i8:
case PTY_i16:
case PTY_i32:
case PTY_i64:
case PTY_u8:
case PTY_u16:
case PTY_u32:
case PTY_u64:
case PTY_a32:
case PTY_a64: {
ConstvalNode *Zero = Builder->CreateIntConst(0, Cond->GetPrimType());
return Builder->CreateExprCompare(OP_eq, *IntTy, *OpndTy, Cond, Zero);
}
case PTY_f32: {
ConstvalNode *Zero = Builder->CreateFloatConst(0.0f);
return Builder->CreateExprCompare(OP_eq, *IntTy, *OpndTy, Cond, Zero);
}
case PTY_f64: {
ConstvalNode *Zero = Builder->CreateDoubleConst(0.0);
return Builder->CreateExprCompare(OP_eq, *IntTy, *OpndTy, Cond, Zero);
}
case PTY_ptr: {
ConstvalNode *Zero = Builder->CreateIntConst(0, PointerPrimTy);
return Builder->CreateExprCompare(OP_eq, *IntTy, *OpndTy, Cond, Zero);
}
default:
LogInfo::MapleLogger() << "Error: Unhandled type in exprToCond\n";
#ifdef DEBUG
Cond->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
return Cond;
}
}
FieldID Clang2MapleVisitor::recordFieldIDs(const clang::RecordDecl *Record,
const clang::RecordDecl *Ancestor,
FieldID Base) {
FieldID CurrentField = Base;
for (const auto *I : Record->fields()) {
CurrentField++;
FieldMap[Ancestor][Base][I] = CurrentField;
const clang::Type *FieldType = I->getType().getTypePtr();
// The fields of the struct type of an embedded array are assigned field
// IDs, so get down to the element of the array.
while (const clang::ArrayType *ArrTy = llvm::dyn_cast<clang::ArrayType>(
FieldType->getUnqualifiedDesugaredType())) {
FieldType = ArrTy->getElementType().getTypePtr();
}
if (FieldType->isRecordType()) {
CurrentField +=
recordFieldIDs(FieldType->getAsRecordDecl(), Ancestor, CurrentField);
}
}
return CurrentField - Base; // Number of fields
}
BaseNode *Clang2MapleVisitor::getNodeAsLVal(Result &Res) {
if (Res.isDeref()) {
// Do not dereference arrays
if (Res.getValueTy()->GetKind() == kTypeArray && Res.getField() == 0) {
return Res.getAddr();
}
return Builder->CreateExprIaddrof(*Res.getValueTy(), *Res.getAddrTy(),
Res.getField(), Res.getAddr());
}
return getNodeAsRVal(Res);
}
BaseNode *Clang2MapleVisitor::getNodeAsRVal(Result &Res) {
BaseNode *N = Res.getNode();
if (N) {
if (Res.isDeref()) {
// Do not dereference arrays
if (Res.getValueTy()->GetKind() == kTypeArray && Res.getField() == 0) {
return Res.getAddr();
}
// Do not dereference functions
if (Res.getValueTy()->GetKind() == kTypeFunction) {
return Res.getAddr();
}
return Builder->CreateExprIread(*Res.getValueTy(), *Res.getAddrTy(),
Res.getField(), Res.getAddr());
}
// If a call is used as an rvalue, we need to create a temporary to assign
// the return value to, then read from that for the rvalue.
Opcode Op = N->GetOpCode();
if (kOpcodeInfo.IsCall(Op)) {
MIRType *RetValTy = Res.getValueTy();
// If there is a field access, then we need to create a temp for the
// struct, then get the field.
if (Res.getField()) {
RetValTy = type2Mpl(Context->getRecordType(Res.getBaseRecordDecl()));
}
// Generate a temp for result of the function, then read that as the
// rval
MIRSymbol *Sym = Builder->GetOrCreateLocalDecl(
"_result" + std::to_string(Res.getUniqueID()), *RetValTy);
Sym->SetAttrs(Res.getValueTyAttrs());
StmtNode *TmpAssign = nullptr;
if (Op == OP_call) {
CallNode *Call = static_cast<CallNode *>(N);
// If the return type is a structure too big to fit in registers, then
// pass the address of the return value as an implicit first parameter
// to the function.
MapleVector<BaseNode *> &Args = Call->GetNopnd();
if (RetValTy->GetSize() > 16) {
BaseNode *AddrOf = Builder->CreateExprAddrof(0, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
Args.insert(Args.begin(), AddrOf);
Call->SetNumOpnds(Args.size());
TmpAssign = Call;
} else {
TmpAssign = Builder->CreateStmtCallAssigned(
Call->GetPUIdx(), Call->GetNopnd(), Sym, OP_callassigned);
}
} else if (Op == OP_icall) {
IcallNode *Call = static_cast<IcallNode *>(N);
// If the return type is a structure too big to fit in registers, then
// pass the address of the return value as an implicit first parameter
// to the function.
MapleVector<BaseNode *> &Args = Call->GetNopnd();
if (RetValTy->GetSize() > 16) {
BaseNode *AddrOf = Builder->CreateExprAddrof(0, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
Args.insert(Args.begin() + 1, AddrOf);
Call->SetNumOpnds(Args.size());
TmpAssign = Call;
} else {
TmpAssign = Builder->CreateStmtIcallAssigned(Call->GetNopnd(), *Sym);
}
} else if (Op == OP_intrinsiccall) {
IntrinsiccallNode *Call = static_cast<IntrinsiccallNode *>(N);
// If the return type is a structure too big to fit in registers, then
// pass the address of the return value as an implicit first parameter
// to the function.
MapleVector<BaseNode *> &Args = Call->GetNopnd();
if (RetValTy->GetSize() > 16) {
BaseNode *AddrOf = Builder->CreateExprAddrof(0, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
Args.insert(Args.begin(), AddrOf);
Call->SetNumOpnds(Args.size());
TmpAssign = Call;
} else {
TmpAssign = Builder->CreateStmtIntrinsicCallAssigned(
Call->GetIntrinsic(), Call->GetNopnd(), Sym);
}
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled call node in getNodeAsRVal:\n";
#ifdef DEBUG
N->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
TmpAssign->SetSrcPos(sourceLocation2Mpl(Res.getLoc()));
Res.appendStmtBefore(TmpAssign);
// If a struct is returned, the later passes need an assignment, other
// than the callassigned, to properly retrieve the struct.
if (RetValTy->IsStructType()) {
MIRSymbol *StructSym = Builder->GetOrCreateLocalDecl(
"_resultStruct" + std::to_string(Res.getUniqueID()), *RetValTy);
TmpAssign = Builder->CreateStmtDassign(
*StructSym, 0, Builder->CreateExprDread(*RetValTy, 0, *Sym));
TmpAssign->SetSrcPos(sourceLocation2Mpl(Res.getLoc()));
Res.appendStmtBefore(TmpAssign);
Sym = StructSym;
}
return Builder->CreateExprDread(*Res.getValueTy(), Res.getField(), *Sym);
} else if (isAssign(Op)) {
// If the RHS of an assignment is another assignment, then we need to
// emit that assignment statement first, then use the LHS of that
// assignment as the operand.
StmtNode *SNode = static_cast<StmtNode *>(N);
SNode->SetSrcPos(sourceLocation2Mpl(Res.getLoc()));
Res.appendStmtBefore(SNode);
if (Op == OP_dassign) {
DassignNode *Assign = static_cast<DassignNode *>(N);
return Builder->GetCurrentFuncCodeMp()->New<AddrofNode>(
OP_dread, Assign->GetRHS()->GetPrimType(), Assign->GetStIdx(),
Assign->GetFieldID());
} else if (Op == OP_iassign) {
IassignNode *Assign = static_cast<IassignNode *>(N);
MIRPtrType *PtrTy = static_cast<MIRPtrType *>(
GlobalTables::GetTypeTable().GetTypeFromTyIdx(Assign->GetTyIdx()));
BaseNode *Addr = Assign->Opnd(0);
MIRType *Ty = PtrTy->GetPointedType();
if (Assign->GetFieldID()) {
MIRStructType *StructTy = static_cast<MIRStructType *>(Ty);
Ty = StructTy->GetFieldType(Assign->GetFieldID());
}
return Builder->CreateExprIread(*Ty, *PtrTy, Assign->GetFieldID(),
Addr);
} else if (kOpcodeInfo.IsCallAssigned(Op)) {
if (Op == OP_callassigned) {
CallNode *Assign = static_cast<CallNode *>(N);
CallReturnPair Ret = Assign->GetReturnPair(0);
return Builder->GetCurrentFuncCodeMp()->New<AddrofNode>(
OP_dread, Assign->GetCallReturnType()->GetPrimType(), Ret.first,
Ret.second.GetFieldID());
} else if (Op == OP_icallassigned) {
IcallNode *Assign = static_cast<IcallNode *>(N);
CallReturnPair Ret = Assign->GetReturnVec()[0];
return Builder->GetCurrentFuncCodeMp()->New<AddrofNode>(
OP_dread, Assign->GetCallReturnType()->GetPrimType(), Ret.first,
Ret.second.GetFieldID());
} else {
LogInfo::MapleLogger()
<< "Unhandled call-assign node in getNodeAsRVal:\n";
#ifdef DEBUG
N->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
}
} else if (Op == OP_iread) {
FieldID origFieldID = static_cast<IreadNode*>(N)->GetFieldID();
static_cast<IreadNode*>(N)->SetFieldID(origFieldID + Res.getField());
}
return N;
} else if (Res.isSym()) {
MIRSymbol *Sym = Res.getSym();
if (Sym->GetSKind() == kStFunc) {
MIRFunction *Func = Sym->GetFunction();
BaseNode *AddrOf = Builder->CreateExprAddroffunc(Func->GetPuidx());
AddrOf->SetPrimType(PointerPrimTy);
Func->GetFuncSymbol()->SetAppearsInCode(true);
return AddrOf;
}
return Builder->CreateExprDread(*Res.getValueTy(), Res.getField(), *Sym);
}
return nullptr;
}
StmtNode *Clang2MapleVisitor::getNodeAsStmt(Result &Res) {
BaseNode *N = Res.getNode();
if (Res.isDeref()) {
// Do not dereference arrays
if (Res.getValueTy()->GetKind() == kTypeArray) {
N = Res.getAddr();
} else {
N = Builder->CreateExprIread(*Res.getValueTy(), *Res.getAddrTy(),
Res.getField(), Res.getAddr());
}
} else if (Res.isSym()) {
MIRSymbol *Sym = Res.getSym();
if (Sym->GetSKind() == kStFunc) {
MIRFunction *Func = Sym->GetFunction();
N = Builder->CreateExprAddroffunc(Func->GetPuidx());
N->SetPrimType(PointerPrimTy);
Func->GetFuncSymbol()->SetAppearsInCode(true);
} else {
N = Builder->CreateExprDread(*Res.getValueTy(), Res.getField(), *Sym);
}
}
StmtNode *SNode = nullptr;
if (N) {
Opcode Op = N->GetOpCode();
// If this is a call with a return type which must be passed by reference,
// generate a temp and pass its address as an implicit first parameter.
if (kOpcodeInfo.IsCall(Op)) {
MIRType *RetValTy = Res.getValueTy();
// If there is a field access, then we need to create a temp for the
// struct, then get the field.
if (Res.getField()) {
RetValTy = type2Mpl(Context->getRecordType(Res.getBaseRecordDecl()));
}
if (RetValTy->GetSize() > 16) {
// Generate a temp for result of the function
MIRSymbol *Sym = Builder->GetOrCreateLocalDecl(
"_result" + std::to_string(Res.getUniqueID()), *RetValTy);
Sym->SetAttrs(Res.getValueTyAttrs());
StmtNode *TmpAssign = nullptr;
if (Op == OP_call) {
CallNode *Call = static_cast<CallNode *>(N);
MapleVector<BaseNode *> &Args = Call->GetNopnd();
BaseNode *AddrOf = Builder->CreateExprAddrof(0, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
Args.insert(Args.begin(), AddrOf);
Call->SetNumOpnds(Args.size());
} else if (Op == OP_icall) {
IcallNode *Call = static_cast<IcallNode *>(N);
MapleVector<BaseNode *> &Args = Call->GetNopnd();
BaseNode *AddrOf = Builder->CreateExprAddrof(0, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
Args.insert(Args.begin() + 1, AddrOf);
Call->SetNumOpnds(Args.size());
} else if (Op == OP_intrinsiccall) {
IntrinsiccallNode *Call = static_cast<IntrinsiccallNode *>(N);
MapleVector<BaseNode *> &Args = Call->GetNopnd();
BaseNode *AddrOf = Builder->CreateExprAddrof(0, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
Args.insert(Args.begin(), AddrOf);
Call->SetNumOpnds(Args.size());
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled call node in getNodeAsRVal:\n";
#ifdef DEBUG
N->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
}
SNode = static_cast<StmtNode *>(N);
} else if (kOpcodeInfo.IsStmt(Op)) {
SNode = static_cast<StmtNode *>(N);
} else {
// If the node is an expression, not a statement, wrap it in an eval
SNode = Builder->CreateStmtUnary(OP_eval, N);
}
}
SNode->SetSrcPos(sourceLocation2Mpl(Res.getLoc()));
return SNode;
}
BaseNode *Clang2MapleVisitor::getNodeAsAddrOf(Result &Res) {
BaseNode *AddrOf = nullptr;
if (Res.isSym()) {
MIRSymbol *Sym = Res.getSym();
if (Sym->GetSKind() == kStFunc) {
AddrOf = Builder->CreateExprAddroffunc(Sym->GetFunction()->GetPuidx());
} else {
AddrOf = Builder->CreateExprAddrof(Res.getField(), *Sym);
}
AddrOf->SetPrimType(PointerPrimTy);
return AddrOf;
} else {
BaseNode *N = getNodeAsRVal(Res);
if (N->GetOpCode() == OP_array) {
AddrOf = N;
return AddrOf;
} else if (N->GetOpCode() == OP_iread) {
IreadNode *IRead = static_cast<IreadNode *>(N);
if (N->Opnd(0)->GetOpCode() == OP_array && !IRead->GetFieldID()) {
AddrOf = N->Opnd(0);
} else {
AddrOf = Builder->CreateExprIaddrof(Res.getValueTy()->GetPrimType(),
IRead->GetTyIdx(),
IRead->GetFieldID(), N->Opnd(0));
AddrOf->SetPrimType(PointerPrimTy);
}
return AddrOf;
}
LogInfo::MapleLogger()
<< "Error: Unhandled expression in getNodeAsAddrOf\n";
#ifdef DEBUG
N->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
return AddrOf;
}
void Clang2MapleVisitor::appendResultBefore(Result &To, Result R) {
for (Result::iterator It = R.beginStmtsBefore(); It != R.endStmtsBefore();
++It) {
To.appendStmtBefore(*It);
}
if (!R.mayDrop()) {
if (StmtNode *SNode = getNodeAsStmt(R)) {
To.appendStmtBefore(SNode);
}
}
for (Result::iterator It = R.beginStmtsAfter(); It != R.endStmtsAfter();
++It) {
To.appendStmtBefore(*It);
}
}
bool Clang2MapleVisitor::evaluateNodeAsInt(int64_t &Result, const BaseNode *N) {
if (N->GetOpCode() == OP_constval) {
const ConstvalNode *ConstNode = static_cast<const ConstvalNode *>(N);
const MIRConst *Const = ConstNode->GetConstVal();
if (Const->GetKind() == kConstInt) {
const MIRIntConst *IntConst = static_cast<const MIRIntConst *>(Const);
Result = IntConst->GetValue().GetSXTValue();
return true;
}
}
return false;
}
MIRConst *Clang2MapleVisitor::evaluateExprAsConst(const clang::Expr *E,
MIRType *Ty) {
clang::Expr::EvalResult InitConstResult;
if (E->EvaluateAsConstantExpr(InitConstResult, *Context)) {
clang::APValue InitConstVal = InitConstResult.Val;
if (InitConstVal.isInt()) {
llvm::APSInt IntVal = InitConstVal.getInt();
MIRConst *IntConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(
IntVal.getExtValue(), *Ty);
return IntConst;
} else if (InitConstVal.isFloat()) {
MIRConst *FloatConst = nullptr;
llvm::APFloat FloatVal = InitConstVal.getFloat();
if (&FloatVal.getSemantics() == &llvm::APFloat::IEEEsingle()) {
FloatConst = Builder->GetCurrentFuncDataMp()->New<MIRFloatConst>(
FloatVal.convertToFloat(),
*GlobalTables::GetTypeTable().GetPrimType(PTY_f32));
} else if (&FloatVal.getSemantics() == &llvm::APFloat::IEEEdouble()) {
FloatConst = Builder->GetCurrentFuncDataMp()->New<MIRDoubleConst>(
FloatVal.convertToDouble(),
*GlobalTables::GetTypeTable().GetPrimType(PTY_f64));
} else if (&FloatVal.getSemantics() == &llvm::APFloat::IEEEquad()) {
bool LosesInfo;
FloatVal.convert(llvm::APFloat::IEEEdouble(),
llvm::APFloatBase::roundingMode::NearestTiesToAway,
&LosesInfo);
FloatConst = Builder->GetCurrentFuncDataMp()->New<MIRDoubleConst>(
FloatVal.convertToDouble(),
*GlobalTables::GetTypeTable().GetPrimType(PTY_f64));
} else {
LogInfo::MapleLogger()
<< "Unexpected type of floating literal: " << Ty->GetPrimType()
<< "\n";
}
return FloatConst;
}
}
return nullptr;
}
MIRConst *Clang2MapleVisitor::createZero(MIRType *Ty) {
PrimType PTy = Ty->GetPrimType();
if (PrimitiveType(PTy).IsAddress()) {
return GlobalTables::GetIntConstTable().GetOrCreateIntConst(0,
*IntPointerTy);
} else if (PrimitiveType(PTy).IsInteger()) {
return GlobalTables::GetIntConstTable().GetOrCreateIntConst(0, *Ty);
} else if (PTy == PTY_f32) {
return Builder->GetCurrentFuncDataMp()->New<MIRFloatConst>(0.0f, *Ty);
} else if (PTy == PTY_f64) {
return Builder->GetCurrentFuncDataMp()->New<MIRDoubleConst>(0.0, *Ty);
} else if (Ty->IsStructType()) {
MIRStructType *StructTy = static_cast<MIRStructType *>(Ty);
MIRAggConst *Agg =
Builder->GetCurrentFuncDataMp()->New<MIRAggConst>(*Module, *Ty);
for (size_t Field = 0; Field < StructTy->GetFieldsSize(); Field++) {
MIRType *FieldTy = StructTy->GetElemType(Field);
MIRConst *Zero = createZero(FieldTy);
Agg->AddItem(Zero, Field + 1);
}
return Agg;
} else if (Ty->GetKind() == kTypeArray) {
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
if (PrimitiveType(ArrTy->GetElemType()->GetPrimType()).IsInteger()) {
return GlobalTables::GetIntConstTable().GetOrCreateIntConst(
0, *ArrTy->GetElemType());
} else {
MIRAggConst *Agg =
Builder->GetCurrentFuncDataMp()->New<MIRAggConst>(*Module, *Ty);
MIRConst *Zero = createZero(ArrTy->GetElemType());
for (size_t i = 0; i < ArrTy->GetSizeArrayItem(0); i++) {
Agg->PushBack(Zero);
}
return Agg;
}
}
LogInfo::MapleLogger() << "Error: createZero does not yet handle PrimType "
<< PTy << "\n";
return nullptr;
}
BaseNode *Clang2MapleVisitor::createVectorZero(MIRType *Ty) {
PrimType PTy = Ty->GetPrimType();
MapleVector<BaseNode *> Args(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
MIRConst *ScalarZero = createZero(
GlobalTables::GetTypeTable().GetPrimType(getVectorElementPrimType(PTy)));
Args.push_back(Builder->CreateConstval(ScalarZero));
switch (PTy) {
case PTY_v2i64:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v2i64,
OP_intrinsicop, *Ty, Args);
case PTY_v4i32:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v4i32,
OP_intrinsicop, *Ty, Args);
case PTY_v8i16:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v8i16,
OP_intrinsicop, *Ty, Args);
case PTY_v16i8:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v16i8,
OP_intrinsicop, *Ty, Args);
case PTY_v2u64:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v2u64,
OP_intrinsicop, *Ty, Args);
case PTY_v4u32:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v4u32,
OP_intrinsicop, *Ty, Args);
case PTY_v8u16:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v8u16,
OP_intrinsicop, *Ty, Args);
case PTY_v16u8:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v16u8,
OP_intrinsicop, *Ty, Args);
case PTY_v2f64:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v2f64,
OP_intrinsicop, *Ty, Args);
case PTY_v4f32:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v4f32,
OP_intrinsicop, *Ty, Args);
case PTY_v2i32:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v2i32,
OP_intrinsicop, *Ty, Args);
case PTY_v4i16:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v4i16,
OP_intrinsicop, *Ty, Args);
case PTY_v8i8:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v8i8,
OP_intrinsicop, *Ty, Args);
case PTY_v2u32:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v2u32,
OP_intrinsicop, *Ty, Args);
case PTY_v4u16:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v4u16,
OP_intrinsicop, *Ty, Args);
case PTY_v8u8:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v8u8,
OP_intrinsicop, *Ty, Args);
case PTY_v2f32:
return Builder->CreateExprIntrinsicop(INTRN_vector_from_scalar_v2f32,
OP_intrinsicop, *Ty, Args);
default:
LogInfo::MapleLogger()
<< "Error: Unhandled vector type in createVectorZero\n";
#ifdef DEBUG
Ty->Dump(0);
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
return nullptr;
}
Result
Clang2MapleVisitor::buildExprToComputeSizeFromVLA(const clang::Expr *E,
const clang::QualType &QT) {
Result Res(E->getBeginLoc());
const clang::Type *Ty = QT.getCanonicalType().getTypePtrOrNull();
MIRType *SizeTy = type2Mpl(Context->getSizeType());
MIR_ASSERT(!Ty->isArrayType() ||
(Ty->isConstantArrayType() || Ty->isVariableArrayType()));
if (Ty->isArrayType()) {
BaseNode *LHS = nullptr, *RHS = nullptr;
Result ResLHS = buildExprToComputeSizeFromVLA(
E, llvm::dyn_cast<clang::ArrayType>(Ty)->getElementType());
Res.appendStmts(ResLHS);
LHS = getNodeAsRVal(ResLHS);
if (Ty->isVariableArrayType()) {
clang::Expr *Size =
llvm::dyn_cast<clang::VariableArrayType>(Ty)->getSizeExpr();
Result ResRHS = Visit(Size);
Res.appendStmts(ResRHS);
RHS = getNodeAsRVal(ResRHS);
MIR_ASSERT(Size->getType()->isIntegerType());
if (!Size->getType()->hasUnsignedIntegerRepresentation()) {
RHS = Builder->CreateExprTypeCvt(OP_cvt, SizeTy->GetPrimType(),
RHS->GetPrimType(), *RHS);
}
} else {
llvm::APInt Size =
llvm::dyn_cast<clang::ConstantArrayType>(Ty)->getSize();
RHS = Builder->CreateIntConst(Size.getSExtValue(),
IntPointerTy->GetPrimType());
}
Res.setNode(Builder->CreateExprBinary(OP_mul, *SizeTy, LHS, RHS),
E->getID(*Context), SizeTy);
} else {
MIRType *MTy = type2Mpl(QT);
Res.setNode(Builder->CreateIntConst(MTy->GetSize(), SizeTy->GetPrimType()),
E->getID(*Context), SizeTy);
}
return Res;
}
BaseNode *Clang2MapleVisitor::constToNode(MIRConst *Const) {
// Maple cannot handle an addrof node with an offset. Expand it into an
// addition.
if (Const->GetKind() == kConstAddrof) {
MIRAddrofConst *AddrOf = static_cast<MIRAddrofConst *>(Const);
if (AddrOf->GetOffset()) {
BaseNode *Offset =
Builder->CreateIntConst(AddrOf->GetOffset(), PointerPrimTy);
BaseNode *Addr = Builder->CreateExprAddrof(AddrOf->GetFieldID(),
AddrOf->GetSymbolIndex());
Addr->SetPrimType(PointerPrimTy);
return Builder->CreateExprBinary(OP_add, Const->GetType(), Addr, Offset);
} else {
BaseNode *Node = Builder->CreateExprAddrof(AddrOf->GetFieldID(),
AddrOf->GetSymbolIndex());
Node->SetPrimType(PointerPrimTy);
return Node;
}
} else if (Const->GetKind() == kConstAddrofFunc) {
MIRAddroffuncConst *AOFConst = static_cast<MIRAddroffuncConst *>(Const);
BaseNode *AddrOf = Builder->CreateExprAddroffunc(AOFConst->GetValue());
AddrOf->SetPrimType(PointerPrimTy);
return AddrOf;
} else if (Const->GetKind() == kConstLblConst) {
MIRLblConst *LabelConst = static_cast<MIRLblConst *>(Const);
AddroflabelNode *AOL =
Builder->GetCurrentFuncCodeMp()->New<AddroflabelNode>(
LabelConst->GetValue());
AOL->SetPrimType(PointerPrimTy);
return AOL;
} else if (Const->GetKind() == kConstStrConst) {
MIRStrConst *StrConst = static_cast<MIRStrConst *>(Const);
return Builder->GetCurrentFuncCodeMp()->New<ConststrNode>(
PointerPrimTy, StrConst->GetValue());
}
return Builder->CreateConstval(Const);
}
unsigned Clang2MapleVisitor::assignStruct(Result &Res, MIRSymbol *BaseSym,
BaseNode *BaseAddr,
MIRStructType *StructTy,
BaseNode *Src, FieldID Base) {
MIRType *StructPtrTy = GlobalTables::GetTypeTable().GetOrCreatePointerType(
*StructTy, PointerPrimTy);
SrcPosition Pos = sourceLocation2Mpl(Res.getLoc());
if (Src->op == OP_constval) { // constant initializers
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(Src);
MIRConst *Const = ConstNode->GetConstVal();
ASSERT(Const->GetKind() == kConstAggConst,
"Expected agg constant in struct initializer\n");
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
unsigned Size = Agg->GetConstVec().size();
for (unsigned i = 0; i < Size; i++) {
MIRConst *FieldConst = Agg->GetConstVecItem(i);
FieldID Field = Base + Agg->GetFieldIdItem(i);
MIRType *FieldTy = StructTy->GetFieldType(Field);
if (FieldTy->GetKind() == kTypeScalar ||
FieldTy->GetKind() == kTypePointer ||
FieldTy->GetKind() == kTypeBitField) {
BaseNode *FieldNode = constToNode(FieldConst);
StmtNode *FieldAssign;
if (BaseSym) {
FieldAssign = Builder->CreateStmtDassign(*BaseSym, Field, FieldNode);
} else {
FieldAssign = Builder->CreateStmtIassign(
*StructPtrTy, Field,
BaseAddr->CloneTree(*Builder->GetCurrentFuncCodeMpAllocator()),
FieldNode);
}
FieldAssign->SetSrcPos(Pos);
Res.appendStmtBefore(FieldAssign);
} else {
ConstvalNode FieldNode(FieldConst);
if (FieldTy->IsStructType()) {
assignStruct(Res, BaseSym, BaseAddr, StructTy, &FieldNode, Field);
} else if (FieldTy->GetKind() == kTypeArray) {
BaseNode *ElemBaseAddr = getBase(BaseSym, BaseAddr, Base);
MIRArrayType *ArrayTy = static_cast<MIRArrayType *>(FieldTy);
if (ElemBaseAddr->GetOpCode() == OP_iread ||
ElemBaseAddr->GetOpCode() == OP_iaddrof) {
IreadNode *IRead = static_cast<IreadNode *>(ElemBaseAddr);
IRead->SetFieldID(Field);
} else if (ElemBaseAddr->GetOpCode() == OP_addrof ||
ElemBaseAddr->GetOpCode() == OP_dread) {
AddrofNode *AddrOf = static_cast<AddrofNode *>(ElemBaseAddr);
AddrOf->SetFieldID(Field);
} else {
ElemBaseAddr->Dump();
ASSERT(false, "Unexpected base address in assignStruct");
}
assignArray(Res, ElemBaseAddr, ArrayTy, &FieldNode);
} else {
FieldConst->Dump(nullptr);
LogInfo::MapleLogger() << "\n";
FieldTy->Dump(0, false);
ASSERT(false, "Error: field is not a scalar, struct, or array\n");
}
}
}
return Size + 1;
} else if (Src->GetOpCode() ==
OP_intrinsicopwithtype) { // non-constant initializers
IntrinsicopNode *N = static_cast<IntrinsicopNode *>(Src);
unsigned Size = N->NumOpnds();
for (unsigned i = 0; i < Size; i++) {
IreadNode *WrapperNode = static_cast<IreadNode *>(N->Opnd(i));
BaseNode *FieldNode = WrapperNode->Opnd(0);
FieldID Field = Base + WrapperNode->GetFieldID();
if (FieldNode->GetPrimType() == PTY_agg &&
(FieldNode->GetOpCode() == OP_intrinsicopwithtype ||
FieldNode->GetOpCode() == OP_constval)) {
MIRType *FieldTy;
if (FieldNode->GetOpCode() == OP_intrinsicopwithtype) {
IntrinsicopNode *NField = static_cast<IntrinsicopNode *>(FieldNode);
FieldTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(NField->GetTyIdx());
} else { // FieldNode->GetOpCode() == OP_constval
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(FieldNode);
MIRConst *Const = ConstNode->GetConstVal();
FieldTy = &Const->GetType();
}
if (FieldTy->GetKind() == kTypeArray) {
BaseNode *ElemBaseAddr = getBase(BaseSym, BaseAddr, Base);
MIRArrayType *ArrayTy = static_cast<MIRArrayType *>(FieldTy);
if (ElemBaseAddr->GetOpCode() == OP_iread ||
ElemBaseAddr->GetOpCode() == OP_iaddrof) {
IreadNode *IRead = static_cast<IreadNode *>(ElemBaseAddr);
IRead->SetFieldID(Field);
} else if (ElemBaseAddr->GetOpCode() == OP_addrof ||
ElemBaseAddr->GetOpCode() == OP_dread) {
AddrofNode *AddrOf = static_cast<AddrofNode *>(ElemBaseAddr);
AddrOf->SetFieldID(Field);
} else {
ElemBaseAddr->Dump();
ASSERT(false, "Unexpected base address in assignStruct");
}
assignArray(Res, ElemBaseAddr, ArrayTy, FieldNode);
} else {
assignStruct(Res, BaseSym, BaseAddr, StructTy, FieldNode, Field);
}
} else {
if (WrapperNode->GetPrimType() == PTY_agg && FieldNode->GetPrimType() != PTY_agg) {
MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(WrapperNode->GetTyIdx());
if (WrapperNode->GetFieldID() != 0) {
TyIdx fldTyIdx = static_cast<MIRStructType *>(mirType)->GetFieldTyIdx(WrapperNode->GetFieldID());
mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fldTyIdx);
}
if (mirType->GetKind() == kTypeArray) {
continue; // skip array field intiializing with a scalar constant
}
}
StmtNode *FieldAssign;
if (BaseSym) {
FieldAssign = Builder->CreateStmtDassign(*BaseSym, Field, FieldNode);
} else {
FieldAssign = Builder->CreateStmtIassign(*StructPtrTy, Field,
BaseAddr, FieldNode);
}
FieldAssign->SetSrcPos(Pos);
Res.appendStmtBefore(FieldAssign);
}
}
return Size + 1;
} else { // Direct assignment of the structure
StmtNode *Assign;
if (BaseSym) {
Assign = Builder->CreateStmtDassign(*BaseSym, Base, Src);
} else {
Assign = Builder->CreateStmtIassign(*StructPtrTy, 0, BaseAddr, Src);
}
Assign->SetSrcPos(Pos);
Res.appendStmtBefore(Assign);
return StructTy->GetSize();
}
}
BaseNode *Clang2MapleVisitor::getBase(MIRSymbol *Sym, BaseNode *Base,
FieldID Field) {
ASSERT(Sym || Base, "getBase requires weither Sym or Base to be set");
if (Sym) {
BaseNode *AddrOf = Builder->CreateExprAddrof(Field, *Sym);
AddrOf->SetPrimType(PointerPrimTy);
return AddrOf;
} else {
return Base->CloneTree(*Builder->GetCurrentFuncCodeMpAllocator());
}
}
#ifdef MULTIDIM_ARRAYS
AddrofNode *Clang2MapleVisitor::computeArrayOffset(size_t &Offset,
ArrayNode *Array) {
Offset = 0;
MIRType *Ty = Array->GetArrayType(GlobalTables::GetTypeTable());
ASSERT(Ty->GetKind() == kTypeArray, "Invalid indexing of non-array type");
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
size_t Multiplier = ArrTy->GetElemType()->GetSize();
// Multiply for size of inner dimensions
for (int m = ArrTy->GetDim() - 1; m >= Array->NumOpnds() - 1; m--) {
Multiplier *= ArrTy->GetSizeArrayItem(m);
}
for (int i = Array->NumOpnds() - 1; i >= 1; i--) {
BaseNode *IndexNode = Array->GetNopndAt(i);
int64_t Val;
if (!evaluateNodeAsInt(Val, IndexNode)) {
return nullptr;
}
Offset += Val * Multiplier;
Multiplier *= ArrTy->GetSizeArrayItem(i - 1);
}
BaseNode *Base = Array->GetBase();
ASSERT(Base->GetOpCode() == OP_addrof, "Expected addrof node as array base");
return static_cast<AddrofNode *>(Base);
}
#else // !MULTIDIM_ARRAYS
AddrofNode *Clang2MapleVisitor::computeArrayOffset(size_t &Offset,
ArrayNode *Array) {
Offset = 0;
BaseNode *Base = Array;
while (Base->GetOpCode() == OP_array) {
Array = static_cast<ArrayNode *>(Base);
MIRType *Ty = Array->GetArrayType(GlobalTables::GetTypeTable());
ASSERT(Ty->GetKind() == kTypeArray, "Invalid indexing of non-array type");
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
MIRType *ElemTy = ArrTy->GetElemType();
BaseNode *IndexNode = Array->GetNopndAt(1);
int64_t Val;
if (!evaluateNodeAsInt(Val, IndexNode)) {
return nullptr;
}
Offset += Val * ElemTy->GetSize();
Base = Array->GetBase();
}
ASSERT(Base->GetOpCode() == OP_addrof, "Expected addrof node as array base");
return static_cast<AddrofNode *>(Base);
}
#endif // MULTIDIM_ARRAYS
BaseNode *Clang2MapleVisitor::getAddrOfNode(BaseNode *N) {
switch (N->GetOpCode()) {
case OP_dread:
N->SetOpCode(OP_addrof);
N->SetPrimType(PointerPrimTy);
return N;
case OP_iread:
N->SetOpCode(OP_iaddrof);
N->SetPrimType(PointerPrimTy);
return N;
default:
ASSERT(false, "Unsupported node in addrOfNode");
return nullptr;
}
}
unsigned Clang2MapleVisitor::assignArray(Result &Res, BaseNode *BaseAddr,
MIRArrayType *ArrayTy, BaseNode *Src) {
MIRType *ElemTy = ArrayTy->GetElemType();
size_t ElemSize = ElemTy->GetSize();
MIRType *PtrTy = GlobalTables::GetTypeTable().GetOrCreatePointerType(
*ElemTy, PointerPrimTy);
SrcPosition Pos = sourceLocation2Mpl(Res.getLoc());
size_t SizeInited = 0;
if (Src->op == OP_constval) { // constant initializers
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(Src);
MIRConst *Const = ConstNode->GetConstVal();
if (Const->GetKind() == kConstAggConst) {
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
for (unsigned ElemID = 0; ElemID < Agg->GetConstVec().size(); ++ElemID) {
BaseNode *IndexNode =
Builder->CreateIntConst(ElemID, IntPointerTy->GetPrimType());
ArrayNode *Array;
#ifdef MULTIDIM_ARRAYS
if (BaseAddr->GetOpCode() == OP_array) {
Array = static_cast<ArrayNode *>(
BaseAddr->CloneTree(*Builder->GetCurrentFuncCodeMpAllocator()));
MapleVector<BaseNode *> &Opnds = Array->GetNopnd();
Opnds.push_back(IndexNode);
Array->SetNumOpnds(Opnds.size());
} else {
#endif // MULTIDIM_ARRAYS
Array = Builder->CreateExprArray(*ArrayTy, BaseAddr, IndexNode);
Array->SetBoundsCheck(false);
Array->SetPrimType(PointerPrimTy);
#ifdef MULTIDIM_ARRAYS
}
#endif // MULTIDIM_ARRAYS
MIRConst *ElemConst = Agg->GetConstVecItem(ElemID);
if (ElemTy->GetKind() == kTypeArray) {
MIRArrayType *ElemArrayTy = static_cast<MIRArrayType *>(ElemTy);
ConstvalNode Elem(ElemConst);
SizeInited += assignArray(Res, Array, ElemArrayTy, &Elem);
} else if (ArrayTy->GetDim() > 1) {
std::vector<maple::uint32> SizeArray;
for (size_t d = 1; d < ArrayTy->GetDim(); d++) {
SizeArray.push_back(ArrayTy->GetSizeArrayItem(d));
}
MIRArrayType NestedArrayTy(ElemTy->GetTypeIndex(), SizeArray);
MIRArrayType *ElemArrayTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(
NestedArrayTy));
ConstvalNode Elem(ElemConst);
SizeInited += assignArray(Res, Array, ElemArrayTy, &Elem);
} else if (ElemTy->GetKind() == kTypeStruct ||
ElemTy->GetKind() == kTypeUnion) {
MIRStructType *ElemStructTy = static_cast<MIRStructType *>(ElemTy);
MIRType *StructPtrTy =
GlobalTables::GetTypeTable().GetOrCreatePointerType(
*ElemStructTy, PointerPrimTy);
ConstvalNode Elem(ElemConst);
BaseNode *StructBase =
Builder->CreateExprIaddrof(*StructPtrTy, *StructPtrTy, 0, Array);
assignStruct(Res, nullptr, StructBase, ElemStructTy, &Elem);
SizeInited += ElemStructTy->GetSize();
} else {
BaseNode *Elem = constToNode(ElemConst);
IassignNode *ElemAssign =
Builder->CreateStmtIassign(*PtrTy, 0, Array, Elem);
ElemAssign->SetSrcPos(Pos);
Res.appendStmtBefore(ElemAssign);
SizeInited += ElemSize;
}
}
} else if (Const->GetKind() == kConstInt) {
// Use memset to set the whole array to the specified value
MIRIntConst *IConst = static_cast<MIRIntConst *>(Const);
MapleVector<BaseNode *> MemsetArgs(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
MemsetArgs.push_back(BaseAddr);
BaseNode *Value = Builder->CreateIntConst(IConst->GetValue().GetZXTValue(), PTY_i32);
MemsetArgs.push_back(Value);
BaseNode *Size = Builder->CreateIntConst(ArrayTy->GetSize(),
IntPointerTy->GetPrimType());
MemsetArgs.push_back(Size);
StmtNode *MemsetCall =
Builder->CreateStmtIntrinsicCall(INTRN_C_memset, MemsetArgs);
MemsetCall->SetSrcPos(Pos);
Res.appendStmtBefore(MemsetCall);
SizeInited += ArrayTy->GetSize();
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled aggregate initializer in assignArray\n";
#ifdef DEBUG
Const->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
} else if (Src->op == OP_conststr) {
// Generate a memcpy to copy the string literal into the local variable
ConststrNode *ConstStr = static_cast<ConststrNode *>(Src);
UStrIdx SIdx = ConstStr->GetStrIdx();
std::string Str = GlobalTables::GetUStrTable().GetStringFromStrIdx(SIdx);
MapleVector<BaseNode *> MemcpyArgs(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
MemcpyArgs.push_back(BaseAddr);
MemcpyArgs.push_back(ConstStr);
MemcpyArgs.push_back(Builder->GetConstInt(Str.size() + 1));
StmtNode *MemcpyCall =
Builder->CreateStmtIntrinsicCall(INTRN_C_memcpy, MemcpyArgs);
MemcpyCall->SetSrcPos(Pos);
Res.appendStmtBefore(MemcpyCall);
SizeInited = Str.size() + 1;
} else if (Src->op == OP_intrinsicopwithtype) { // non-constant initializers
NaryNode *N = static_cast<NaryNode *>(Src);
for (size_t ElemID = 0; ElemID < N->NumOpnds(); ++ElemID) {
BaseNode *IndexNode =
Builder->CreateIntConst(ElemID, IntPointerTy->GetPrimType());
ArrayNode *Array =
Builder->CreateExprArray(*ArrayTy, BaseAddr, IndexNode);
Array->SetBoundsCheck(false);
Array->SetPrimType(PointerPrimTy);
if (ElemTy->GetKind() == kTypeArray) {
MIRArrayType *ElemArrayTy = static_cast<MIRArrayType *>(ElemTy);
SizeInited += assignArray(Res, Array, ElemArrayTy, N->Opnd(ElemID));
} else if (ArrayTy->GetDim() > 1) {
std::vector<maple::uint32> SizeArray;
for (size_t d = 1; d < ArrayTy->GetDim(); d++) {
SizeArray.push_back(ArrayTy->GetSizeArrayItem(d));
}
MIRArrayType NestedArrayTy(ElemTy->GetTypeIndex(), SizeArray);
MIRArrayType *ElemArrayTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(NestedArrayTy));
SizeInited += assignArray(Res, Array, ElemArrayTy, N->Opnd(ElemID));
} else if (ElemTy->GetKind() == kTypeStruct ||
ElemTy->GetKind() == kTypeUnion) {
MIRStructType *ElemStructTy = static_cast<MIRStructType *>(ElemTy);
MIRType *StructPtrTy =
GlobalTables::GetTypeTable().GetOrCreatePointerType(*ElemStructTy,
PointerPrimTy);
BaseNode *StructBase =
Builder->CreateExprIaddrof(*StructPtrTy, *StructPtrTy, 0, Array);
assignStruct(Res, nullptr, StructBase, ElemStructTy, N->Opnd(ElemID));
SizeInited += ElemStructTy->GetSize();
} else {
IassignNode *ElemAssign =
Builder->CreateStmtIassign(*PtrTy, 0, Array, N->Opnd(ElemID));
ElemAssign->SetSrcPos(Pos);
Res.appendStmtBefore(ElemAssign);
SizeInited += ElemSize;
}
}
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled aggregate initializer in assignArray\n";
#ifdef DEBUG
Src->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
// Fill in uninitialized elements with 0 using memset
if (SizeInited < ArrayTy->GetSize()) {
MapleVector<BaseNode *> MemsetArgs(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
BaseNode *Offset = Builder->CreateIntConst(SizeInited, PointerPrimTy);
BaseNode *Base =
Builder->CreateExprBinary(OP_add, *IntPointerTy, BaseAddr, Offset);
MemsetArgs.push_back(Base);
BaseNode *Zero = Builder->CreateIntConst(0, PTY_i32);
MemsetArgs.push_back(Zero);
BaseNode *SizeLeft = Builder->CreateIntConst(
ArrayTy->GetSize() - SizeInited, IntPointerTy->GetPrimType());
MemsetArgs.push_back(SizeLeft);
StmtNode *MemsetCall =
Builder->CreateStmtIntrinsicCall(INTRN_C_memset, MemsetArgs);
MemsetCall->SetSrcPos(Pos);
Res.appendStmtBefore(MemsetCall);
}
return ArrayTy->GetSize();
}
unsigned Clang2MapleVisitor::assignVector(Result &Res, MIRSymbol *VecSym,
MIRType *Ty, BaseNode *Src) {
Result VecRes(VecSym, Ty, Res.getLoc());
SrcPosition Pos = sourceLocation2Mpl(Res.getLoc());
size_t SizeInited = 0;
if (Src->op == OP_constval) { // constant initializers
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(Src);
MIRConst *Const = ConstNode->GetConstVal();
if (Const->GetKind() == kConstAggConst) {
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
for (unsigned ElemID = 0; ElemID < Agg->GetConstVec().size(); ++ElemID) {
BaseNode *IndexNode =
Builder->CreateIntConst(ElemID, IntPointerTy->GetPrimType());
MIRConst *ElemConst = Agg->GetConstVecItem(ElemID);
BaseNode *Elem = constToNode(ElemConst);
StmtNode *ElemAssign = vectorSetLane(Ty, VecRes, IndexNode, Elem);
ElemAssign->SetSrcPos(Pos);
Res.appendStmtBefore(ElemAssign);
SizeInited += 1;
}
}
} else if (Src->op == OP_intrinsicopwithtype) { // non-constant initializers
NaryNode *N = static_cast<NaryNode *>(Src);
for (size_t ElemID = 0; ElemID < N->NumOpnds(); ++ElemID) {
BaseNode *IndexNode =
Builder->CreateIntConst(ElemID, IntPointerTy->GetPrimType());
StmtNode *ElemAssign =
vectorSetLane(Ty, VecRes, IndexNode, N->Opnd(ElemID));
ElemAssign->SetSrcPos(Pos);
Res.appendStmtBefore(ElemAssign);
SizeInited += 1;
}
} else {
StmtNode *Init = Builder->CreateStmtDassign(*VecSym, 0, Src);
Res.appendStmtBefore(Init);
SizeInited += Ty->GetSize();
}
return SizeInited;
}
StmtNode *Clang2MapleVisitor::vectorSetLane(MIRType *Ty, Result &VecRes,
BaseNode *Index, BaseNode *Src) {
MapleVector<BaseNode *> Args(
Builder->GetCurrentFuncCodeMpAllocator()->Adapter());
Args.push_back(Src);
Args.push_back(getNodeAsRVal(VecRes));
Args.push_back(Index);
MIRIntrinsicID Intrinsic;
switch (Ty->GetPrimType()) {
#define SETQ_LANE(TY) \
case PTY_##TY: \
Intrinsic = INTRN_vector_set_element_##TY; \
break;
SETQ_LANE(v2i64)
SETQ_LANE(v4i32)
SETQ_LANE(v8i16)
SETQ_LANE(v16i8)
SETQ_LANE(v2u64)
SETQ_LANE(v4u32)
SETQ_LANE(v8u16)
SETQ_LANE(v16u8)
SETQ_LANE(v2f64)
SETQ_LANE(v4f32)
SETQ_LANE(v2i32)
SETQ_LANE(v4i16)
SETQ_LANE(v8i8)
SETQ_LANE(v2u32)
SETQ_LANE(v4u16)
SETQ_LANE(v8u8)
SETQ_LANE(v2f32)
case PTY_i64:
Intrinsic = INTRN_vector_set_element_v1i64;
break;
case PTY_u64:
Intrinsic = INTRN_vector_set_element_v1u64;
break;
case PTY_f64:
Intrinsic = INTRN_vector_set_element_v1f64;
break;
default:
LogInfo::MapleLogger() << "Error: Unhandled vector type in vectorSetLane\n";
#ifdef DEBUG
Ty->Dump(0);
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
return nullptr;
}
BaseNode *CallIntrinsic =
Builder->CreateExprIntrinsicop(Intrinsic, OP_intrinsicop, *Ty, Args);
StmtNode *Assign;
if (VecRes.isDeref()) {
Assign = Builder->CreateStmtIassign(*VecRes.getAddrTy(), VecRes.getField(),
VecRes.getAddr(), CallIntrinsic);
} else if (VecRes.isSym()) {
Assign = Builder->CreateStmtDassign(*VecRes.getSym(), VecRes.getField(),
CallIntrinsic);
} else {
ASSERT(false, "Error: Destination vector is neither deref or symbol");
}
return Assign;
}
PrimType Clang2MapleVisitor::getVectorElementPrimType(PrimType VectorPrimType) {
switch (VectorPrimType) {
case PTY_v2i64:
return PTY_i64;
case PTY_v4i32:
case PTY_v2i32:
return PTY_i32;
case PTY_v8i16:
case PTY_v4i16:
return PTY_i16;
case PTY_v16i8:
case PTY_v8i8:
return PTY_i8;
case PTY_v2u64:
return PTY_u64;
case PTY_v4u32:
case PTY_v2u32:
return PTY_u32;
case PTY_v8u16:
case PTY_v4u16:
return PTY_u16;
case PTY_v16u8:
case PTY_v8u8:
return PTY_u8;
case PTY_v2f64:
return PTY_f64;
case PTY_v4f32:
case PTY_v2f32:
return PTY_f32;
case PTY_i64:
return PTY_i64;
case PTY_u64:
return PTY_u64;
case PTY_f64:
return PTY_f64;
default:
LogInfo::MapleLogger()
<< "Error: Unhandled vector type in getVectorElementPrimType: "
<< VectorPrimType << "\n";
CHECK_FATAL(false, "Failing due to unsupported feature");
return PTY_unknown;
}
}
// TODO: This function has a lot of duplication and may miss some possible
// combinations. It should be improved, possibly using some recursion to
// evaluate sub-expressions.
MIRConst *Clang2MapleVisitor::getInitializer(MIRType *Ty,
const clang::Expr *InitExpr) {
Result InitRes = Visit(InitExpr);
BaseNode *InitNode = getNodeAsRVal(InitRes);
// This case should only happen with an array of size 0
if (!InitNode) {
return nullptr;
}
if (InitNode->op == OP_constval) {
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(InitNode);
// For array types, if there are less initializers than elements of the
// array, we need to fill in the rest.
MIRConst *Const = ConstNode->GetConstVal();
if (Ty->GetKind() == kTypeArray) {
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
if (Const->GetKind() == kConstAggConst) {
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
completeArrayInitializer(Agg, ArrTy);
}
}
// For bitfields, assign the corresponding bitfield types to the
// initializers.
if (Ty->IsMIRStructType() && Const->GetKind() == kConstAggConst) {
MIRStructType *StructTy = static_cast<MIRStructType *>(Ty);
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
for (unsigned Item = 0; Item < Agg->GetConstVec().size(); Item++) {
MIRType *FieldTy = StructTy->GetElemType(Agg->GetFieldIdItem(Item) - 1);
if (FieldTy->GetKind() == kTypeBitField) {
MIRConst *FieldConst = Agg->GetConstVecItem(Item);
ASSERT(FieldConst->GetKind() == kConstInt,
"bitfield initializer must be an integer");
MIRIntConst *FieldInit = static_cast<MIRIntConst *>(FieldConst);
Agg->SetItem(Item,
GlobalTables::GetIntConstTable().GetOrCreateIntConst(
FieldInit->GetValue().GetZXTValue(), *FieldTy),
Agg->GetFieldIdItem(Item));
}
}
}
return Const;
} else if (InitNode->op == OP_conststr) {
ConststrNode *ConstStr = static_cast<ConststrNode *>(InitNode);
UStrIdx SIdx = ConstStr->GetStrIdx();
if (Ty->GetKind() == kTypeArray) {
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
// Expand the string to an array of characters
std::string Str = GlobalTables::GetUStrTable().GetStringFromStrIdx(SIdx);
MIRAggConst *Agg =
Builder->GetCurrentFuncCodeMp()->New<MIRAggConst>(*Module, *Ty);
int Remaining = ArrTy->GetSizeArrayItem(0);
for (char &C : Str) {
Agg->PushBack(GlobalTables::GetIntConstTable().GetOrCreateIntConst(
C, *ArrTy->GetElemType()));
if (--Remaining == 0)
break;
}
// Add the terminator, if it fits
if (Remaining > 0) {
Agg->PushBack(createZero(ArrTy->GetElemType()));
}
return Agg;
} else {
return Builder->GetCurrentFuncCodeMp()->New<MIRStrConst>(SIdx, *Ty);
}
} else if (InitNode->op == OP_addrof) {
AddrofNode *AddrOf = static_cast<AddrofNode *>(InitNode);
return Builder->GetCurrentFuncCodeMp()->New<MIRAddrofConst>(
AddrOf->GetStIdx(), AddrOf->GetFieldID(), *Ty);
} else if (InitNode->op == OP_addroflabel) {
AddroflabelNode *AddrOf = static_cast<AddroflabelNode *>(InitNode);
return Builder->GetCurrentFuncCodeMp()->New<MIRLblConst>(
AddrOf->GetOffset(), Builder->GetCurrentFunction()->GetPuidx(), *Ty);
} else if (InitNode->op == OP_addroffunc) {
AddroffuncNode *AOF = static_cast<AddroffuncNode *>(InitNode);
return Builder->GetCurrentFuncCodeMp()->New<MIRAddroffuncConst>(
AOF->GetPUIdx(), *Ty);
} else if (InitNode->op == OP_iaddrof) {
IaddrofNode *IAddrOf = static_cast<IaddrofNode *>(InitNode);
BaseNode *Base = IAddrOf->Opnd(0);
// Find the offset of the field.
size_t FieldOffset = 0;
if (IAddrOf->GetFieldID()) {
auto UO =
llvm::dyn_cast<clang::UnaryOperator>(InitExpr->IgnoreParenCasts());
ASSERT(UO, "Expected unary operator");
auto ME = llvm::dyn_cast<clang::MemberExpr>(
UO->getSubExpr()->IgnoreParenCasts());
ASSERT(ME, "Expected member expression");
uint64_t OffsetBits = Context->getFieldOffset(ME->getMemberDecl());
FieldOffset += (OffsetBits / BITS_PER_BYTE);
}
// Handle an address of an array element, e.g. &x[4]
if (Base->GetOpCode() == OP_array) {
ArrayNode *Array = static_cast<ArrayNode *>(Base);
BaseNode *ArrayBase = Array->GetBase();
if (ArrayBase->GetOpCode() == OP_addrof) {
size_t ArrayOffset = 0;
AddrofNode *ArrayAddr = computeArrayOffset(ArrayOffset, Array);
ASSERT(ArrayAddr, "Unable to compute array offset");
return Builder->GetCurrentFuncCodeMp()->New<MIRAddrofConst>(
ArrayAddr->GetStIdx(), ArrayAddr->GetFieldID(), *Ty,
ArrayOffset + FieldOffset);
} else if (ArrayBase->GetOpCode() == OP_conststr) {
ConststrNode *ConstStr = static_cast<ConststrNode *>(ArrayBase);
ASSERT(Array->NumOpnds() == 2,
"Invalid array access on string constant");
BaseNode *IndexNode = Array->GetNopndAt(1);
int64_t Val;
bool Safe = evaluateNodeAsInt(Val, IndexNode);
ASSERT(Safe, "Unable to determine array offset");
const std::string &InitialString =
GlobalTables::GetUStrTable().GetStringFromStrIdx(
ConstStr->GetStrIdx());
return Builder->GetCurrentFuncCodeMp()->New<MIRStrConst>(
InitialString.substr(Val), *Ty);
}
} else if (Base->GetOpCode() == OP_constval) {
// This handles the case where the code is attempting to get the offset
// of a structure field by using the following type of expression:
// &((struct s *)0)->b)
if (auto UO = llvm::dyn_cast<clang::UnaryOperator>(
InitExpr->IgnoreParenCasts())) {
if (auto ME = llvm::dyn_cast<clang::MemberExpr>(
UO->getSubExpr()->IgnoreParenCasts())) {
ConstvalNode *ConstNode = static_cast<ConstvalNode *>(Base);
MIRConst *Const = ConstNode->GetConstVal();
ASSERT(Const->GetKind() == kConstInt,
"Only an integer is allowed here");
MIRIntConst *IntConst = static_cast<MIRIntConst *>(Const);
int64_t Base = IntConst->GetValue().GetSXTValue();
uint64_t OffsetBits = Context->getFieldOffset(ME->getMemberDecl());
return GlobalTables::GetIntConstTable().GetOrCreateIntConst(
Base + OffsetBits / BITS_PER_BYTE, *Ty);
}
}
} else if (Base->GetOpCode() == OP_addrof) {
AddrofNode *AddrOf = static_cast<AddrofNode *>(Base);
return Builder->GetCurrentFuncCodeMp()->New<MIRAddrofConst>(
AddrOf->GetStIdx(), AddrOf->GetFieldID(), *Ty, FieldOffset);
} else if (Base->GetOpCode() == OP_add) {
BinaryNode *AddNode = static_cast<BinaryNode *>(Base);
BaseNode *LhsNode = AddNode->GetBOpnd(0);
BaseNode *RhsNode = AddNode->GetBOpnd(1);
if (LhsNode->GetOpCode() == OP_addrof &&
RhsNode->GetOpCode() == OP_constval) {
AddrofNode *AddrOf = static_cast<AddrofNode *>(LhsNode);
ConstvalNode *RhsConst = static_cast<ConstvalNode *>(RhsNode);
ASSERT(RhsConst->GetConstVal()->GetKind() == kConstInt,
"expected int const");
MIRIntConst *IntConst =
static_cast<MIRIntConst *>(RhsConst->GetConstVal());
int64_t Val = IntConst->GetValue().GetSXTValue();
return Builder->GetCurrentFuncCodeMp()->New<MIRAddrofConst>(
AddrOf->GetStIdx(), AddrOf->GetFieldID(), *Ty, Val + FieldOffset);
} else if (RhsNode->GetOpCode() == OP_addrof &&
LhsNode->GetOpCode() == OP_constval) {
AddrofNode *AddrOf = static_cast<AddrofNode *>(RhsNode);
ConstvalNode *LhsConst = static_cast<ConstvalNode *>(LhsNode);
ASSERT(LhsConst->GetConstVal()->GetKind() == kConstInt,
"expected int const");
MIRIntConst *IntConst =
static_cast<MIRIntConst *>(LhsConst->GetConstVal());
int64_t Val = IntConst->GetValue().GetSXTValue();
return Builder->GetCurrentFuncCodeMp()->New<MIRAddrofConst>(
AddrOf->GetStIdx(), AddrOf->GetFieldID(), *Ty, Val + FieldOffset);
}
}
} else if (InitNode->GetOpCode() == OP_array) {
ArrayNode *Array = static_cast<ArrayNode *>(InitNode);
BaseNode *ArrayBase = Array->GetBase();
if (ArrayBase->GetOpCode() == OP_conststr) {
ConststrNode *ConstStr = static_cast<ConststrNode *>(ArrayBase);
ASSERT(Array->NumOpnds() == 2, "Invalid array access on string constant");
BaseNode *IndexNode = Array->GetNopndAt(1);
int64_t Val;
bool Safe = evaluateNodeAsInt(Val, IndexNode);
ASSERT(Safe, "Unable to determine array offset");
const std::string &InitialString =
GlobalTables::GetUStrTable().GetStringFromStrIdx(
ConstStr->GetStrIdx());
return Builder->GetCurrentFuncCodeMp()->New<MIRStrConst>(
InitialString.substr(Val), *Ty);
} else {
size_t ArrayOffset = 0;
AddrofNode *ArrayAddr = computeArrayOffset(ArrayOffset, Array);
ASSERT(ArrayAddr, "Unable to compute array offset");
return Builder->GetCurrentFuncCodeMp()->New<MIRAddrofConst>(
ArrayAddr->GetStIdx(), ArrayAddr->GetFieldID(), *Ty, ArrayOffset);
}
} else if (InitNode->GetOpCode() == OP_add) {
BinaryNode *Bin = static_cast<BinaryNode *>(InitNode);
BaseNode *Lhs = Bin->GetBOpnd(0);
BaseNode *Rhs = Bin->GetBOpnd(1);
// Look for this type of expression: "foo" + 1
if (Lhs->GetOpCode() == OP_conststr && Rhs->GetOpCode() == OP_constval) {
ConststrNode *LhsConstStr = static_cast<ConststrNode *>(Lhs);
ConstvalNode *RhsConstNode = static_cast<ConstvalNode *>(Rhs);
MIRConst *RhsConst = RhsConstNode->GetConstVal();
ASSERT(RhsConst->GetKind() == kConstInt, "Expected int offset");
MIRIntConst *IntConst = static_cast<MIRIntConst *>(RhsConst);
std::string Str = GlobalTables::GetUStrTable().GetStringFromStrIdx(
LhsConstStr->GetStrIdx());
int64_t Offset = IntConst->GetValue().GetSXTValue();
ASSERT(Offset >= 0 && Offset < (int64_t)Str.length(),
"Invalid offset beyond length of string constant");
return Builder->GetCurrentFuncCodeMp()->New<MIRStrConst>(
Str.substr(Offset), *Ty);
}
}
if (MIRConst *ConstVal = evaluateExprAsConst(InitExpr, Ty)) {
return ConstVal;
}
LogInfo::MapleLogger()
<< "Error: Unable to evaluate initializer as a constant\n";
InitNode->Dump();
return nullptr;
}
MIRConst *Clang2MapleVisitor::expandConstants(MIRType *Ty, MIRConst *Const) {
if (Ty->IsStructType()) {
MIRStructType *StructTy = static_cast<MIRStructType *>(Ty);
if (Const->GetKind() == kConstAggConst) {
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
for (size_t Index = 0, ItemIndex = 0; Index < StructTy->GetFieldsSize();
Index++) {
FieldID Field = Index + 1;
if (StructTy->GetKind() == kTypeUnion && Agg->GetConstVec().size() <= Index) {
continue;
}
MIRType *FieldTy = StructTy->GetElemType(Index);
if (MIRConst *FieldConst = Agg->GetAggConstElement(Field)) {
Agg->SetItem(ItemIndex++, expandConstants(FieldTy, FieldConst),
Field);
}
}
return Agg;
} else {
LogInfo::MapleLogger()
<< "Error: Unhandled constant in expandConstants\n";
#ifdef DEBUG
Const->Dump();
#endif
CHECK_FATAL(false, "Failing due to unsupported feature");
}
} else if (Ty->GetKind() == kTypeArray) {
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
if (Const->GetKind() == kConstAggConst) {
MIRAggConst *Agg = static_cast<MIRAggConst *>(Const);
MapleVector<MIRConst *> &Items = Agg->GetConstVec();
MIRType *ElemTy;
#ifdef MULTIDIM_ARRAYS
if (ArrTy->GetDim() > 1) {
std::vector<maple::uint32> SizeArray;
for (size_t d = 1; d < ArrTy->GetDim(); d++) {
SizeArray.push_back(ArrTy->GetSizeArrayItem(d));
}
MIRArrayType NewArrTy(ArrTy->GetElemTyIdx(), SizeArray);
ElemTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(NewArrTy));
} else {
#endif // MULTIDIM_ARRAYS
ElemTy = ArrTy->GetElemType();
#ifdef MULTIDIM_ARRAYS
}
#endif // MULTIDIM_ARRAYS
size_t Index;
for (Index = 0; Index < Items.size(); Index++) {
MIRConst *ElemConst = Agg->GetConstVecItem(Index);
Items[Index] = expandConstants(ElemTy, ElemConst);
}
return Agg;
} else if (Const->GetKind() == kConstInt) {
MIRAggConst *Agg =
Builder->GetCurrentFuncDataMp()->New<MIRAggConst>(*Module, *Ty);
for (size_t i = 0; i < ArrTy->GetSizeArrayItem(0); i++) {
Agg->PushBack(Const);
}
return Agg;
}
}
return Const;
}
MIRConst *Clang2MapleVisitor::completeArrayInitializer(MIRAggConst *Agg,
MIRArrayType *ArrTy) {
MIRType *ElemTy;
#ifdef MULTIDIM_ARRAYS
if (ArrTy->GetDim() > 1) {
std::vector<maple::uint32> SizeArray;
for (size_t d = 1; d < ArrTy->GetDim(); d++) {
SizeArray.push_back(ArrTy->GetSizeArrayItem(d));
}
MIRArrayType NewArrTy(ArrTy->GetElemTyIdx(), SizeArray);
ElemTy = static_cast<MIRArrayType *>(
GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(NewArrTy));
} else {
#endif // MULTIDIM_ARRAYS
ElemTy = ArrTy->GetElemType();
#ifdef MULTIDIM_ARRAYS
}
#endif // MULTIDIM_ARRAYS
// First, complete any partially initialized inner arrays
for (size_t Elem = 0; Elem < Agg->GetConstVec().size(); Elem++) {
MIRConst *Const = Agg->GetConstVecItem(Elem);
if (Const->GetKind() == kConstAggConst) {
// An agg is also used for a struct, but we only care about arrays here
if (ElemTy->GetKind() == kTypeArray) {
completeArrayInitializer(static_cast<MIRAggConst *>(Const),
static_cast<MIRArrayType *>(ElemTy));
}
}
}
// Then complete this level of the array
MIRConst *Zero = createZero(ElemTy);
for (size_t Inited = Agg->GetConstVec().size(),
ArraySize = ArrTy->GetSizeArrayItem(0);
Inited < ArraySize; ++Inited) {
Agg->PushBack(Zero);
}
return Agg;
}
MIRType *Clang2MapleVisitor::isHomogenousAggregate(MIRType *Ty) {
MIRType *ElemTy = nullptr;
if (Ty->IsStructType()) {
MIRStructType *StructTy = static_cast<MIRStructType *>(Ty);
for (auto FieldPair : StructTy->GetFields()) {
MIRType *FieldTy =
GlobalTables::GetTypeTable().GetTypeFromTyIdx(FieldPair.second.first);
if (FieldTy->GetKind() == kTypeArray) {
MIRArrayType *ArrayTy = static_cast<MIRArrayType *>(FieldTy);
MIRType *ArrayElemTy = ArrayTy->GetElemType();
if (!PrimitiveType(ArrayElemTy->GetPrimType()).IsFloat()) {
return nullptr;
}
FieldTy = ArrayElemTy;
} else if (!PrimitiveType(FieldTy->GetPrimType()).IsFloat()) {
return nullptr;
}
if (!ElemTy) {
ElemTy = FieldTy;
} else if (ElemTy != FieldTy) {
return nullptr;
}
}
}
return ElemTy;
}
bool Clang2MapleVisitor::passInGeneralRegisters(MIRType *Ty) {
if (Ty->GetSize() > 16)
return false;
if (PrimitiveType(Ty->GetPrimType()).IsFloat())
return false;
if (isHomogenousAggregate(Ty))
return false;
return true;
}
bool Clang2MapleVisitor::passInFloatRegisters(MIRType *Ty) {
if (Ty->GetSize() > 16)
return false;
return PrimitiveType(Ty->GetPrimType()).IsFloat();
}
bool Clang2MapleVisitor::shouldEvaluateArgs(const clang::FunctionDecl *FD) {
if (!FD)
return true;
switch (FD->getBuiltinID()) {
case clang::Builtin::BI__builtin_constant_p:
case clang::Builtin::BI__builtin_classify_type:
case clang::Builtin::BI__builtin_object_size:
case clang::Builtin::BI__builtin_dynamic_object_size:
return false;
default:
return true;
}
}
bool Clang2MapleVisitor::isNoCvtNeeded(PrimType ToPTy, PrimType FromPTy) {
if (ToPTy == FromPTy || ToPTy == GetRegPrimType(FromPTy))
return true;
switch (ToPTy) {
case PTY_i32:
return FromPTy == PTY_i16 || FromPTy == PTY_i8;
case PTY_u32:
return FromPTy == PTY_u16 || FromPTy == PTY_u8 || FromPTy == PTY_a32 ||
(PointerPrimTy == PTY_a32 && FromPTy == PTY_ptr);
case PTY_a32:
return FromPTy == PTY_u32;
case PTY_i64:
return FromPTy == PTY_i32;
case PTY_u64:
return FromPTy == PTY_u32 || FromPTy == PTY_a64 ||
(PointerPrimTy == PTY_a64 && FromPTy == PTY_ptr);
case PTY_a64:
return FromPTy == PTY_u64;
case PTY_ptr:
return FromPTy == PointerPrimTy;
default:
return false;
}
}
bool Clang2MapleVisitor::isPointerIntConvert(PrimType ToPTy, PrimType FromPTy) {
switch (ToPTy) {
case PTY_u32:
return FromPTy == PTY_a32 ||
(PointerPrimTy == PTY_a32 && FromPTy == PTY_ptr);
case PTY_a32:
return FromPTy == PTY_u32;
case PTY_u64:
return FromPTy == PTY_a64 ||
(PointerPrimTy == PTY_a64 && FromPTy == PTY_ptr);
case PTY_a64:
return FromPTy == PTY_u64;
case PTY_ptr:
return FromPTy == PointerPrimTy;
default:
return false;
}
}
static MIRType *getIntType(unsigned BitSize, bool Signed) {
PrimType PTy;
switch (BitSize) {
case 8:
PTy = Signed ? PTY_i8 : PTY_u8;
break;
case 16:
PTy = Signed ? PTY_i16 : PTY_u16;
break;
case 32:
PTy = Signed ? PTY_i32 : PTY_u32;
break;
case 64:
PTy = Signed ? PTY_i64 : PTY_u64;
break;
default:
ASSERT(false, "unexpected BitSize in GetPrimType");
}
return GlobalTables::GetTypeTable().GetPrimType(PTy);
}
BaseNode *Clang2MapleVisitor::createNumericCast(MIRType *ToTy, BaseNode *N) {
PrimType FromPTy = N->GetPrimType();
PrimType ToPTy = ToTy->GetPrimType();
if (FromPTy == ToPTy || isPointerIntConvert(FromPTy, ToPTy))
return N;
if (PrimitiveType(FromPTy).IsInteger() && PrimitiveType(ToPTy).IsInteger()) {
if (N->GetOpCode() == OP_constval) {
N->SetPrimType(GetRegPrimType(ToPTy));
return N;
}
if (isNoCvtNeeded(ToPTy, FromPTy) &&
(N->GetOpCode() == OP_dread || N->GetOpCode() == OP_iread)) {
N->SetPrimType(GetRegPrimType(ToPTy));
return N;
}
// Only generate sext/zext for < 32-bit types
if (GetPrimTypeSize(ToPTy) < 4 || GetPrimTypeSize(FromPTy) < 4) {
if (GetPrimTypeSize(ToPTy) <= GetPrimTypeSize(FromPTy)) {
if (PrimitiveType(ToPTy).IsUnsigned()) {
return Builder->CreateExprExtractbits(
OP_zext, *getIntType(GetPrimTypeBitSize(FromPTy), false), 0,
GetPrimTypeBitSize(ToPTy), N);
} else {
return Builder->CreateExprExtractbits(
OP_sext, *getIntType(GetPrimTypeBitSize(FromPTy), true), 0,
GetPrimTypeBitSize(ToPTy), N);
}
}
// GetPrimTypeSize(FromPTy) < GetPrimTypeSize(ToPTy)
if (PrimitiveType(FromPTy).IsUnsigned()) {
return Builder->CreateExprExtractbits(
OP_zext, *getIntType(GetPrimTypeBitSize(ToPTy), false), 0,
GetPrimTypeBitSize(FromPTy), N);
} else {
return Builder->CreateExprExtractbits(
OP_sext, *getIntType(GetPrimTypeBitSize(ToPTy), true), 0,
GetPrimTypeBitSize(FromPTy), N);
}
}
}
return Builder->CreateExprTypeCvt(OP_cvt, ToPTy, FromPTy, *N);
}
std::unique_ptr<clang::tooling::FrontendActionFactory>
clang2MapleFrontendActionFactory() {
class Clang2MapleFrontendActionFactory
: public clang::tooling::FrontendActionFactory {
public:
Clang2MapleFrontendActionFactory() {}
std::unique_ptr<clang::FrontendAction> create() override {
return std::make_unique<Clang2MapleAction>();
}
};
return std::unique_ptr<clang::tooling::FrontendActionFactory>(
new Clang2MapleFrontendActionFactory());
}
static MIRStorageClass StorageClass2Mpl(clang::StorageClass SC) {
switch (SC) {
case clang::SC_None:
return kScGlobal; // FIXME: Not sure what should return here
case clang::SC_Extern:
case clang::SC_PrivateExtern:
return kScExtern;
case clang::SC_Static:
return kScFstatic; // FIXME: Need to differentiate between pstatic and
// fstatic
case clang::SC_Auto:
return kScAuto;
case clang::SC_Register:
return kScInvalid; // FIXME: Find the correct alternative for this
}
return kScInvalid;
}
static Opcode BinOpcode2Mpl(clang::BinaryOperatorKind Op, bool isSigned) {
switch (Op) {
case clang::BO_Mul:
case clang::BO_MulAssign:
return OP_mul;
case clang::BO_Div:
case clang::BO_DivAssign:
return OP_div;
case clang::BO_Rem:
case clang::BO_RemAssign:
return OP_rem;
case clang::BO_Add:
case clang::BO_AddAssign:
return OP_add;
case clang::BO_Sub:
case clang::BO_SubAssign:
return OP_sub;
case clang::BO_Shl:
case clang::BO_ShlAssign:
return OP_shl;
case clang::BO_Shr:
case clang::BO_ShrAssign:
if (isSigned)
return OP_ashr;
else
return OP_lshr;
case clang::BO_Cmp:
return OP_cmp;
case clang::BO_LT:
return OP_lt;
case clang::BO_GT:
return OP_gt;
case clang::BO_LE:
return OP_le;
case clang::BO_GE:
return OP_ge;
case clang::BO_EQ:
return OP_eq;
case clang::BO_NE:
return OP_ne;
case clang::BO_And:
case clang::BO_AndAssign:
return OP_band;
case clang::BO_Xor:
case clang::BO_XorAssign:
return OP_bxor;
case clang::BO_Or:
case clang::BO_OrAssign:
return OP_bior;
case clang::BO_LAnd:
return OP_cand;
case clang::BO_LOr:
return OP_cior;
default:
return OP_undef;
}
}
static bool isAssign(Opcode Op) {
return Op == OP_dassign || Op == OP_iassign || kOpcodeInfo.IsCallAssigned(Op);
}
static bool isPointerType(MIRType *Ty) {
return Ty->IsMIRPtrType() || Ty->GetKind() == kTypeArray;
}
static size_t getPointedToSize(MIRType *Ty) {
if (Ty->IsMIRPtrType()) {
return static_cast<MIRPtrType *>(Ty)->GetPointedType()->GetSize();
} else if (Ty->GetKind() == kTypeArray) {
MIRArrayType *ArrTy = static_cast<MIRArrayType *>(Ty);
#ifdef MULTIDIM_ARRAYS
size_t Size = ArrTy->GetElemType()->GetSize();
for (int d = 1; d < ArrTy->GetDim(); d++) {
Size *= ArrTy->GetSizeArrayItem(d);
}
return Size;
#else // !MULTIDIM_ARRAYS
return ArrTy->GetElemType()->GetSize();
#endif // MULTIDIM_ARRAYS
}
ASSERT(false, "Unexpected type in getPointedToSize");
return -1;
}
static bool isOneElementVector(clang::QualType QT) {
return isOneElementVector(QT.getTypePtr());
}
static bool isOneElementVector(const clang::Type *Ty) {
if (const clang::VectorType *VecTy = llvm::dyn_cast<clang::VectorType>(
Ty->getUnqualifiedDesugaredType())) {
if (VecTy->getNumElements() == 1) {
return true;
}
}
return false;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/xcoderun/clang2mpl.git
[email protected]:xcoderun/clang2mpl.git
xcoderun
clang2mpl
clang2mpl
master

搜索帮助