12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972 |
- /*
- * Copyright 2012-2013 Ecole Normale Superieure
- *
- * Use of this software is governed by the MIT license
- *
- * Written by Sven Verdoolaege,
- * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
- */
- #include <string.h>
- #include <isl/id.h>
- #include <isl/val.h>
- #include <isl_ast_private.h>
- #undef EL_BASE
- #define EL_BASE ast_expr
- #include <isl_list_templ.c>
- #undef EL_BASE
- #define EL_BASE ast_node
- #include <isl_list_templ.c>
- isl_ctx *isl_ast_print_options_get_ctx(
- __isl_keep isl_ast_print_options *options)
- {
- return options ? options->ctx : NULL;
- }
- __isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx)
- {
- isl_ast_print_options *options;
- options = isl_calloc_type(ctx, isl_ast_print_options);
- if (!options)
- return NULL;
- options->ctx = ctx;
- isl_ctx_ref(ctx);
- options->ref = 1;
- return options;
- }
- __isl_give isl_ast_print_options *isl_ast_print_options_dup(
- __isl_keep isl_ast_print_options *options)
- {
- isl_ctx *ctx;
- isl_ast_print_options *dup;
- if (!options)
- return NULL;
- ctx = isl_ast_print_options_get_ctx(options);
- dup = isl_ast_print_options_alloc(ctx);
- if (!dup)
- return NULL;
- dup->print_for = options->print_for;
- dup->print_for_user = options->print_for_user;
- dup->print_user = options->print_user;
- dup->print_user_user = options->print_user_user;
- return dup;
- }
- __isl_give isl_ast_print_options *isl_ast_print_options_cow(
- __isl_take isl_ast_print_options *options)
- {
- if (!options)
- return NULL;
- if (options->ref == 1)
- return options;
- options->ref--;
- return isl_ast_print_options_dup(options);
- }
- __isl_give isl_ast_print_options *isl_ast_print_options_copy(
- __isl_keep isl_ast_print_options *options)
- {
- if (!options)
- return NULL;
- options->ref++;
- return options;
- }
- __isl_null isl_ast_print_options *isl_ast_print_options_free(
- __isl_take isl_ast_print_options *options)
- {
- if (!options)
- return NULL;
- if (--options->ref > 0)
- return NULL;
- isl_ctx_deref(options->ctx);
- free(options);
- return NULL;
- }
- /* Set the print_user callback of "options" to "print_user".
- *
- * If this callback is set, then it is used to print user nodes in the AST.
- * Otherwise, the expression associated to the user node is printed.
- */
- __isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
- __isl_take isl_ast_print_options *options,
- __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
- __isl_take isl_ast_print_options *options,
- __isl_keep isl_ast_node *node, void *user),
- void *user)
- {
- options = isl_ast_print_options_cow(options);
- if (!options)
- return NULL;
- options->print_user = print_user;
- options->print_user_user = user;
- return options;
- }
- /* Set the print_for callback of "options" to "print_for".
- *
- * If this callback is set, then it used to print for nodes in the AST.
- */
- __isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
- __isl_take isl_ast_print_options *options,
- __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
- __isl_take isl_ast_print_options *options,
- __isl_keep isl_ast_node *node, void *user),
- void *user)
- {
- options = isl_ast_print_options_cow(options);
- if (!options)
- return NULL;
- options->print_for = print_for;
- options->print_for_user = user;
- return options;
- }
- __isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)
- {
- if (!expr)
- return NULL;
- expr->ref++;
- return expr;
- }
- __isl_give isl_ast_expr *isl_ast_expr_dup(__isl_keep isl_ast_expr *expr)
- {
- int i;
- isl_ctx *ctx;
- isl_ast_expr *dup;
- if (!expr)
- return NULL;
- ctx = isl_ast_expr_get_ctx(expr);
- switch (expr->type) {
- case isl_ast_expr_int:
- dup = isl_ast_expr_from_val(isl_val_copy(expr->u.v));
- break;
- case isl_ast_expr_id:
- dup = isl_ast_expr_from_id(isl_id_copy(expr->u.id));
- break;
- case isl_ast_expr_op:
- dup = isl_ast_expr_alloc_op(ctx,
- expr->u.op.op, expr->u.op.n_arg);
- if (!dup)
- return NULL;
- for (i = 0; i < expr->u.op.n_arg; ++i)
- dup->u.op.args[i] =
- isl_ast_expr_copy(expr->u.op.args[i]);
- break;
- case isl_ast_expr_error:
- dup = NULL;
- }
- if (!dup)
- return NULL;
- return dup;
- }
- __isl_give isl_ast_expr *isl_ast_expr_cow(__isl_take isl_ast_expr *expr)
- {
- if (!expr)
- return NULL;
- if (expr->ref == 1)
- return expr;
- expr->ref--;
- return isl_ast_expr_dup(expr);
- }
- __isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr)
- {
- int i;
- if (!expr)
- return NULL;
- if (--expr->ref > 0)
- return NULL;
- isl_ctx_deref(expr->ctx);
- switch (expr->type) {
- case isl_ast_expr_int:
- isl_val_free(expr->u.v);
- break;
- case isl_ast_expr_id:
- isl_id_free(expr->u.id);
- break;
- case isl_ast_expr_op:
- if (expr->u.op.args)
- for (i = 0; i < expr->u.op.n_arg; ++i)
- isl_ast_expr_free(expr->u.op.args[i]);
- free(expr->u.op.args);
- break;
- case isl_ast_expr_error:
- break;
- }
- free(expr);
- return NULL;
- }
- isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr)
- {
- return expr ? expr->ctx : NULL;
- }
- enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
- {
- return expr ? expr->type : isl_ast_expr_error;
- }
- /* Return the integer value represented by "expr".
- */
- __isl_give isl_val *isl_ast_expr_int_get_val(__isl_keep isl_ast_expr *expr)
- {
- if (!expr)
- return NULL;
- if (expr->type != isl_ast_expr_int)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "expression not an int", return NULL);
- return isl_val_copy(expr->u.v);
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
- {
- return isl_ast_expr_int_get_val(expr);
- }
- __isl_give isl_id *isl_ast_expr_id_get_id(__isl_keep isl_ast_expr *expr)
- {
- if (!expr)
- return NULL;
- if (expr->type != isl_ast_expr_id)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "expression not an identifier", return NULL);
- return isl_id_copy(expr->u.id);
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
- {
- return isl_ast_expr_id_get_id(expr);
- }
- /* Return the type of operation represented by "expr".
- */
- enum isl_ast_expr_op_type isl_ast_expr_op_get_type(
- __isl_keep isl_ast_expr *expr)
- {
- if (!expr)
- return isl_ast_expr_op_error;
- if (expr->type != isl_ast_expr_op)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "expression not an operation",
- return isl_ast_expr_op_error);
- return expr->u.op.op;
- }
- /* This is an alternative name for the function above.
- */
- enum isl_ast_expr_op_type isl_ast_expr_get_op_type(
- __isl_keep isl_ast_expr *expr)
- {
- return isl_ast_expr_op_get_type(expr);
- }
- /* Return the number of arguments of the operation represented by "expr".
- */
- isl_size isl_ast_expr_op_get_n_arg(__isl_keep isl_ast_expr *expr)
- {
- if (!expr)
- return isl_size_error;
- if (expr->type != isl_ast_expr_op)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "expression not an operation", return isl_size_error);
- return expr->u.op.n_arg;
- }
- /* This is an alternative name for the function above.
- */
- isl_size isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
- {
- return isl_ast_expr_op_get_n_arg(expr);
- }
- /* Return the argument at position "pos" of the operation represented by "expr".
- */
- __isl_give isl_ast_expr *isl_ast_expr_op_get_arg(__isl_keep isl_ast_expr *expr,
- int pos)
- {
- if (!expr)
- return NULL;
- if (expr->type != isl_ast_expr_op)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "expression not an operation", return NULL);
- if (pos < 0 || pos >= expr->u.op.n_arg)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "index out of bounds", return NULL);
- return isl_ast_expr_copy(expr->u.op.args[pos]);
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
- int pos)
- {
- return isl_ast_expr_op_get_arg(expr, pos);
- }
- /* Replace the argument at position "pos" of "expr" by "arg".
- */
- __isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
- int pos, __isl_take isl_ast_expr *arg)
- {
- expr = isl_ast_expr_cow(expr);
- if (!expr || !arg)
- goto error;
- if (expr->type != isl_ast_expr_op)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "expression not an operation", goto error);
- if (pos < 0 || pos >= expr->u.op.n_arg)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "index out of bounds", goto error);
- isl_ast_expr_free(expr->u.op.args[pos]);
- expr->u.op.args[pos] = arg;
- return expr;
- error:
- isl_ast_expr_free(arg);
- return isl_ast_expr_free(expr);
- }
- /* Is "expr1" equal to "expr2"?
- */
- isl_bool isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
- __isl_keep isl_ast_expr *expr2)
- {
- int i;
- if (!expr1 || !expr2)
- return isl_bool_error;
- if (expr1 == expr2)
- return isl_bool_true;
- if (expr1->type != expr2->type)
- return isl_bool_false;
- switch (expr1->type) {
- case isl_ast_expr_int:
- return isl_val_eq(expr1->u.v, expr2->u.v);
- case isl_ast_expr_id:
- return isl_bool_ok(expr1->u.id == expr2->u.id);
- case isl_ast_expr_op:
- if (expr1->u.op.op != expr2->u.op.op)
- return isl_bool_false;
- if (expr1->u.op.n_arg != expr2->u.op.n_arg)
- return isl_bool_false;
- for (i = 0; i < expr1->u.op.n_arg; ++i) {
- isl_bool equal;
- equal = isl_ast_expr_is_equal(expr1->u.op.args[i],
- expr2->u.op.args[i]);
- if (equal < 0 || !equal)
- return equal;
- }
- return isl_bool_true;
- case isl_ast_expr_error:
- return isl_bool_error;
- }
- isl_die(isl_ast_expr_get_ctx(expr1), isl_error_internal,
- "unhandled case", return isl_bool_error);
- }
- /* Create a new operation expression of operation type "op",
- * with "n_arg" as yet unspecified arguments.
- */
- __isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
- enum isl_ast_expr_op_type op, int n_arg)
- {
- isl_ast_expr *expr;
- expr = isl_calloc_type(ctx, isl_ast_expr);
- if (!expr)
- return NULL;
- expr->ctx = ctx;
- isl_ctx_ref(ctx);
- expr->ref = 1;
- expr->type = isl_ast_expr_op;
- expr->u.op.op = op;
- expr->u.op.n_arg = n_arg;
- expr->u.op.args = isl_calloc_array(ctx, isl_ast_expr *, n_arg);
- if (n_arg && !expr->u.op.args)
- return isl_ast_expr_free(expr);
- return expr;
- }
- /* Create a new id expression representing "id".
- */
- __isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id)
- {
- isl_ctx *ctx;
- isl_ast_expr *expr;
- if (!id)
- return NULL;
- ctx = isl_id_get_ctx(id);
- expr = isl_calloc_type(ctx, isl_ast_expr);
- if (!expr)
- goto error;
- expr->ctx = ctx;
- isl_ctx_ref(ctx);
- expr->ref = 1;
- expr->type = isl_ast_expr_id;
- expr->u.id = id;
- return expr;
- error:
- isl_id_free(id);
- return NULL;
- }
- /* Create a new integer expression representing "i".
- */
- __isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i)
- {
- isl_ast_expr *expr;
- expr = isl_calloc_type(ctx, isl_ast_expr);
- if (!expr)
- return NULL;
- expr->ctx = ctx;
- isl_ctx_ref(ctx);
- expr->ref = 1;
- expr->type = isl_ast_expr_int;
- expr->u.v = isl_val_int_from_si(ctx, i);
- if (!expr->u.v)
- return isl_ast_expr_free(expr);
- return expr;
- }
- /* Create a new integer expression representing "v".
- */
- __isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v)
- {
- isl_ctx *ctx;
- isl_ast_expr *expr;
- if (!v)
- return NULL;
- if (!isl_val_is_int(v))
- isl_die(isl_val_get_ctx(v), isl_error_invalid,
- "expecting integer value", goto error);
- ctx = isl_val_get_ctx(v);
- expr = isl_calloc_type(ctx, isl_ast_expr);
- if (!expr)
- goto error;
- expr->ctx = ctx;
- isl_ctx_ref(ctx);
- expr->ref = 1;
- expr->type = isl_ast_expr_int;
- expr->u.v = v;
- return expr;
- error:
- isl_val_free(v);
- return NULL;
- }
- /* Create an expression representing the unary operation "type" applied to
- * "arg".
- */
- __isl_give isl_ast_expr *isl_ast_expr_alloc_unary(
- enum isl_ast_expr_op_type type, __isl_take isl_ast_expr *arg)
- {
- isl_ctx *ctx;
- isl_ast_expr *expr = NULL;
- if (!arg)
- return NULL;
- ctx = isl_ast_expr_get_ctx(arg);
- expr = isl_ast_expr_alloc_op(ctx, type, 1);
- if (!expr)
- goto error;
- expr->u.op.args[0] = arg;
- return expr;
- error:
- isl_ast_expr_free(arg);
- return NULL;
- }
- /* Create an expression representing the negation of "arg".
- */
- __isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *arg)
- {
- return isl_ast_expr_alloc_unary(isl_ast_expr_op_minus, arg);
- }
- /* Create an expression representing the address of "expr".
- */
- __isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr)
- {
- if (!expr)
- return NULL;
- if (isl_ast_expr_get_type(expr) != isl_ast_expr_op ||
- isl_ast_expr_get_op_type(expr) != isl_ast_expr_op_access)
- isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
- "can only take address of access expressions",
- return isl_ast_expr_free(expr));
- return isl_ast_expr_alloc_unary(isl_ast_expr_op_address_of, expr);
- }
- /* Create an expression representing the binary operation "type"
- * applied to "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_alloc_binary(
- enum isl_ast_expr_op_type type,
- __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)
- {
- isl_ctx *ctx;
- isl_ast_expr *expr = NULL;
- if (!expr1 || !expr2)
- goto error;
- ctx = isl_ast_expr_get_ctx(expr1);
- expr = isl_ast_expr_alloc_op(ctx, type, 2);
- if (!expr)
- goto error;
- expr->u.op.args[0] = expr1;
- expr->u.op.args[1] = expr2;
- return expr;
- error:
- isl_ast_expr_free(expr1);
- isl_ast_expr_free(expr2);
- return NULL;
- }
- /* Create an expression representing the sum of "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_add, expr1, expr2);
- }
- /* Create an expression representing the difference of "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_sub, expr1, expr2);
- }
- /* Create an expression representing the product of "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_mul, expr1, expr2);
- }
- /* Create an expression representing the quotient of "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_div, expr1, expr2);
- }
- /* Create an expression representing the quotient of the integer
- * division of "expr1" by "expr2", where "expr1" is known to be
- * non-negative.
- */
- __isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_q, expr1, expr2);
- }
- /* Create an expression representing the remainder of the integer
- * division of "expr1" by "expr2", where "expr1" is known to be
- * non-negative.
- */
- __isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_r, expr1, expr2);
- }
- /* Create an expression representing the conjunction of "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_and, expr1, expr2);
- }
- /* Create an expression representing the conjunction of "expr1" and "expr2",
- * where "expr2" is evaluated only if "expr1" is evaluated to true.
- */
- __isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_and_then, expr1, expr2);
- }
- /* Create an expression representing the disjunction of "expr1" and "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_or, expr1, expr2);
- }
- /* Create an expression representing the disjunction of "expr1" and "expr2",
- * where "expr2" is evaluated only if "expr1" is evaluated to false.
- */
- __isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_or_else, expr1, expr2);
- }
- /* Create an expression representing "expr1" less than or equal to "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_le, expr1, expr2);
- }
- /* Create an expression representing "expr1" less than "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_lt, expr1, expr2);
- }
- /* Create an expression representing "expr1" greater than or equal to "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_ge, expr1, expr2);
- }
- /* Create an expression representing "expr1" greater than "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_gt, expr1, expr2);
- }
- /* Create an expression representing "expr1" equal to "expr2".
- */
- __isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,
- __isl_take isl_ast_expr *expr2)
- {
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_eq, expr1, expr2);
- }
- /* Create an expression of type "type" with as arguments "arg0" followed
- * by "arguments".
- */
- static __isl_give isl_ast_expr *ast_expr_with_arguments(
- enum isl_ast_expr_op_type type, __isl_take isl_ast_expr *arg0,
- __isl_take isl_ast_expr_list *arguments)
- {
- int i;
- isl_size n;
- isl_ctx *ctx;
- isl_ast_expr *res = NULL;
- if (!arg0 || !arguments)
- goto error;
- ctx = isl_ast_expr_get_ctx(arg0);
- n = isl_ast_expr_list_n_ast_expr(arguments);
- if (n < 0)
- goto error;
- res = isl_ast_expr_alloc_op(ctx, type, 1 + n);
- if (!res)
- goto error;
- for (i = 0; i < n; ++i) {
- isl_ast_expr *arg;
- arg = isl_ast_expr_list_get_ast_expr(arguments, i);
- res->u.op.args[1 + i] = arg;
- if (!arg)
- goto error;
- }
- res->u.op.args[0] = arg0;
- isl_ast_expr_list_free(arguments);
- return res;
- error:
- isl_ast_expr_free(arg0);
- isl_ast_expr_list_free(arguments);
- isl_ast_expr_free(res);
- return NULL;
- }
- /* Create an expression representing an access to "array" with index
- * expressions "indices".
- */
- __isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
- __isl_take isl_ast_expr_list *indices)
- {
- return ast_expr_with_arguments(isl_ast_expr_op_access, array, indices);
- }
- /* Create an expression representing a call to "function" with argument
- * expressions "arguments".
- */
- __isl_give isl_ast_expr *isl_ast_expr_call(__isl_take isl_ast_expr *function,
- __isl_take isl_ast_expr_list *arguments)
- {
- return ast_expr_with_arguments(isl_ast_expr_op_call, function, arguments);
- }
- /* For each subexpression of "expr" of type isl_ast_expr_id,
- * if it appears in "id2expr", then replace it by the corresponding
- * expression.
- */
- __isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
- __isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr)
- {
- int i;
- isl_maybe_isl_ast_expr m;
- if (!expr || !id2expr)
- goto error;
- switch (expr->type) {
- case isl_ast_expr_int:
- break;
- case isl_ast_expr_id:
- m = isl_id_to_ast_expr_try_get(id2expr, expr->u.id);
- if (m.valid < 0)
- goto error;
- if (!m.valid)
- break;
- isl_ast_expr_free(expr);
- expr = m.value;
- break;
- case isl_ast_expr_op:
- for (i = 0; i < expr->u.op.n_arg; ++i) {
- isl_ast_expr *arg;
- arg = isl_ast_expr_copy(expr->u.op.args[i]);
- arg = isl_ast_expr_substitute_ids(arg,
- isl_id_to_ast_expr_copy(id2expr));
- if (arg == expr->u.op.args[i]) {
- isl_ast_expr_free(arg);
- continue;
- }
- if (!arg)
- expr = isl_ast_expr_free(expr);
- expr = isl_ast_expr_cow(expr);
- if (!expr) {
- isl_ast_expr_free(arg);
- break;
- }
- isl_ast_expr_free(expr->u.op.args[i]);
- expr->u.op.args[i] = arg;
- }
- break;
- case isl_ast_expr_error:
- expr = isl_ast_expr_free(expr);
- break;
- }
- isl_id_to_ast_expr_free(id2expr);
- return expr;
- error:
- isl_ast_expr_free(expr);
- isl_id_to_ast_expr_free(id2expr);
- return NULL;
- }
- isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node)
- {
- return node ? node->ctx : NULL;
- }
- enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)
- {
- return node ? node->type : isl_ast_node_error;
- }
- __isl_give isl_ast_node *isl_ast_node_alloc(isl_ctx *ctx,
- enum isl_ast_node_type type)
- {
- isl_ast_node *node;
- node = isl_calloc_type(ctx, isl_ast_node);
- if (!node)
- return NULL;
- node->ctx = ctx;
- isl_ctx_ref(ctx);
- node->ref = 1;
- node->type = type;
- return node;
- }
- /* Create an if node with the given guard.
- *
- * The then body needs to be filled in later.
- */
- __isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard)
- {
- isl_ast_node *node;
- if (!guard)
- return NULL;
- node = isl_ast_node_alloc(isl_ast_expr_get_ctx(guard), isl_ast_node_if);
- if (!node)
- goto error;
- node->u.i.guard = guard;
- return node;
- error:
- isl_ast_expr_free(guard);
- return NULL;
- }
- /* Create a for node with the given iterator.
- *
- * The remaining fields need to be filled in later.
- */
- __isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id)
- {
- isl_ast_node *node;
- isl_ctx *ctx;
- if (!id)
- return NULL;
- ctx = isl_id_get_ctx(id);
- node = isl_ast_node_alloc(ctx, isl_ast_node_for);
- if (!node)
- goto error;
- node->u.f.iterator = isl_ast_expr_from_id(id);
- if (!node->u.f.iterator)
- return isl_ast_node_free(node);
- return node;
- error:
- isl_id_free(id);
- return NULL;
- }
- /* Create a mark node, marking "node" with "id".
- */
- __isl_give isl_ast_node *isl_ast_node_alloc_mark(__isl_take isl_id *id,
- __isl_take isl_ast_node *node)
- {
- isl_ctx *ctx;
- isl_ast_node *mark;
- if (!id || !node)
- goto error;
- ctx = isl_id_get_ctx(id);
- mark = isl_ast_node_alloc(ctx, isl_ast_node_mark);
- if (!mark)
- goto error;
- mark->u.m.mark = id;
- mark->u.m.node = node;
- return mark;
- error:
- isl_id_free(id);
- isl_ast_node_free(node);
- return NULL;
- }
- /* Create a user node evaluating "expr".
- */
- __isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr)
- {
- isl_ctx *ctx;
- isl_ast_node *node;
- if (!expr)
- return NULL;
- ctx = isl_ast_expr_get_ctx(expr);
- node = isl_ast_node_alloc(ctx, isl_ast_node_user);
- if (!node)
- goto error;
- node->u.e.expr = expr;
- return node;
- error:
- isl_ast_expr_free(expr);
- return NULL;
- }
- /* Create a block node with the given children.
- */
- __isl_give isl_ast_node *isl_ast_node_alloc_block(
- __isl_take isl_ast_node_list *list)
- {
- isl_ast_node *node;
- isl_ctx *ctx;
- if (!list)
- return NULL;
- ctx = isl_ast_node_list_get_ctx(list);
- node = isl_ast_node_alloc(ctx, isl_ast_node_block);
- if (!node)
- goto error;
- node->u.b.children = list;
- return node;
- error:
- isl_ast_node_list_free(list);
- return NULL;
- }
- /* Represent the given list of nodes as a single node, either by
- * extract the node from a single element list or by creating
- * a block node with the list of nodes as children.
- */
- __isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
- __isl_take isl_ast_node_list *list)
- {
- isl_size n;
- isl_ast_node *node;
- n = isl_ast_node_list_n_ast_node(list);
- if (n < 0)
- goto error;
- if (n != 1)
- return isl_ast_node_alloc_block(list);
- node = isl_ast_node_list_get_ast_node(list, 0);
- isl_ast_node_list_free(list);
- return node;
- error:
- isl_ast_node_list_free(list);
- return NULL;
- }
- __isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- node->ref++;
- return node;
- }
- __isl_give isl_ast_node *isl_ast_node_dup(__isl_keep isl_ast_node *node)
- {
- isl_ast_node *dup;
- if (!node)
- return NULL;
- dup = isl_ast_node_alloc(isl_ast_node_get_ctx(node), node->type);
- if (!dup)
- return NULL;
- switch (node->type) {
- case isl_ast_node_if:
- dup->u.i.guard = isl_ast_expr_copy(node->u.i.guard);
- dup->u.i.then = isl_ast_node_copy(node->u.i.then);
- dup->u.i.else_node = isl_ast_node_copy(node->u.i.else_node);
- if (!dup->u.i.guard || !dup->u.i.then ||
- (node->u.i.else_node && !dup->u.i.else_node))
- return isl_ast_node_free(dup);
- break;
- case isl_ast_node_for:
- dup->u.f.iterator = isl_ast_expr_copy(node->u.f.iterator);
- dup->u.f.init = isl_ast_expr_copy(node->u.f.init);
- dup->u.f.cond = isl_ast_expr_copy(node->u.f.cond);
- dup->u.f.inc = isl_ast_expr_copy(node->u.f.inc);
- dup->u.f.body = isl_ast_node_copy(node->u.f.body);
- if (!dup->u.f.iterator || !dup->u.f.init || !dup->u.f.cond ||
- !dup->u.f.inc || !dup->u.f.body)
- return isl_ast_node_free(dup);
- break;
- case isl_ast_node_block:
- dup->u.b.children = isl_ast_node_list_copy(node->u.b.children);
- if (!dup->u.b.children)
- return isl_ast_node_free(dup);
- break;
- case isl_ast_node_mark:
- dup->u.m.mark = isl_id_copy(node->u.m.mark);
- dup->u.m.node = isl_ast_node_copy(node->u.m.node);
- if (!dup->u.m.mark || !dup->u.m.node)
- return isl_ast_node_free(dup);
- break;
- case isl_ast_node_user:
- dup->u.e.expr = isl_ast_expr_copy(node->u.e.expr);
- if (!dup->u.e.expr)
- return isl_ast_node_free(dup);
- break;
- case isl_ast_node_error:
- break;
- }
- return dup;
- }
- __isl_give isl_ast_node *isl_ast_node_cow(__isl_take isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->ref == 1)
- return node;
- node->ref--;
- return isl_ast_node_dup(node);
- }
- __isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (--node->ref > 0)
- return NULL;
- switch (node->type) {
- case isl_ast_node_if:
- isl_ast_expr_free(node->u.i.guard);
- isl_ast_node_free(node->u.i.then);
- isl_ast_node_free(node->u.i.else_node);
- break;
- case isl_ast_node_for:
- isl_ast_expr_free(node->u.f.iterator);
- isl_ast_expr_free(node->u.f.init);
- isl_ast_expr_free(node->u.f.cond);
- isl_ast_expr_free(node->u.f.inc);
- isl_ast_node_free(node->u.f.body);
- break;
- case isl_ast_node_block:
- isl_ast_node_list_free(node->u.b.children);
- break;
- case isl_ast_node_mark:
- isl_id_free(node->u.m.mark);
- isl_ast_node_free(node->u.m.node);
- break;
- case isl_ast_node_user:
- isl_ast_expr_free(node->u.e.expr);
- break;
- case isl_ast_node_error:
- break;
- }
- isl_id_free(node->annotation);
- isl_ctx_deref(node->ctx);
- free(node);
- return NULL;
- }
- /* Replace the body of the for node "node" by "body".
- */
- __isl_give isl_ast_node *isl_ast_node_for_set_body(
- __isl_take isl_ast_node *node, __isl_take isl_ast_node *body)
- {
- node = isl_ast_node_cow(node);
- if (!node || !body)
- goto error;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", goto error);
- isl_ast_node_free(node->u.f.body);
- node->u.f.body = body;
- return node;
- error:
- isl_ast_node_free(node);
- isl_ast_node_free(body);
- return NULL;
- }
- __isl_give isl_ast_node *isl_ast_node_for_get_body(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", return NULL);
- return isl_ast_node_copy(node->u.f.body);
- }
- /* Mark the given for node as being degenerate.
- */
- __isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
- __isl_take isl_ast_node *node)
- {
- node = isl_ast_node_cow(node);
- if (!node)
- return NULL;
- node->u.f.degenerate = 1;
- return node;
- }
- isl_bool isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)
- {
- if (!node)
- return isl_bool_error;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", return isl_bool_error);
- return isl_bool_ok(node->u.f.degenerate);
- }
- __isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", return NULL);
- return isl_ast_expr_copy(node->u.f.iterator);
- }
- __isl_give isl_ast_expr *isl_ast_node_for_get_init(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", return NULL);
- return isl_ast_expr_copy(node->u.f.init);
- }
- /* Return the condition expression of the given for node.
- *
- * If the for node is degenerate, then the condition is not explicitly
- * stored in the node. Instead, it is constructed as
- *
- * iterator <= init
- */
- __isl_give isl_ast_expr *isl_ast_node_for_get_cond(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", return NULL);
- if (!node->u.f.degenerate)
- return isl_ast_expr_copy(node->u.f.cond);
- return isl_ast_expr_alloc_binary(isl_ast_expr_op_le,
- isl_ast_expr_copy(node->u.f.iterator),
- isl_ast_expr_copy(node->u.f.init));
- }
- /* Return the increment of the given for node.
- *
- * If the for node is degenerate, then the increment is not explicitly
- * stored in the node. We simply return "1".
- */
- __isl_give isl_ast_expr *isl_ast_node_for_get_inc(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", return NULL);
- if (!node->u.f.degenerate)
- return isl_ast_expr_copy(node->u.f.inc);
- return isl_ast_expr_alloc_int_si(isl_ast_node_get_ctx(node), 1);
- }
- /* Replace the then branch of the if node "node" by "child".
- */
- __isl_give isl_ast_node *isl_ast_node_if_set_then(
- __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)
- {
- node = isl_ast_node_cow(node);
- if (!node || !child)
- goto error;
- if (node->type != isl_ast_node_if)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not an if node", goto error);
- isl_ast_node_free(node->u.i.then);
- node->u.i.then = child;
- return node;
- error:
- isl_ast_node_free(node);
- isl_ast_node_free(child);
- return NULL;
- }
- /* Return the then-node of the given if-node.
- */
- __isl_give isl_ast_node *isl_ast_node_if_get_then_node(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_if)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not an if node", return NULL);
- return isl_ast_node_copy(node->u.i.then);
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_ast_node *isl_ast_node_if_get_then(
- __isl_keep isl_ast_node *node)
- {
- return isl_ast_node_if_get_then_node(node);
- }
- /* Does the given if-node have an else-node?
- */
- isl_bool isl_ast_node_if_has_else_node(__isl_keep isl_ast_node *node)
- {
- if (!node)
- return isl_bool_error;
- if (node->type != isl_ast_node_if)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not an if node", return isl_bool_error);
- return isl_bool_ok(node->u.i.else_node != NULL);
- }
- /* This is an alternative name for the function above.
- */
- isl_bool isl_ast_node_if_has_else(__isl_keep isl_ast_node *node)
- {
- return isl_ast_node_if_has_else_node(node);
- }
- /* Return the else-node of the given if-node,
- * assuming there is one.
- */
- __isl_give isl_ast_node *isl_ast_node_if_get_else_node(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_if)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not an if node", return NULL);
- return isl_ast_node_copy(node->u.i.else_node);
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_ast_node *isl_ast_node_if_get_else(
- __isl_keep isl_ast_node *node)
- {
- return isl_ast_node_if_get_else_node(node);
- }
- __isl_give isl_ast_expr *isl_ast_node_if_get_cond(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_if)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a guard node", return NULL);
- return isl_ast_expr_copy(node->u.i.guard);
- }
- __isl_give isl_ast_node_list *isl_ast_node_block_get_children(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_block)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a block node", return NULL);
- return isl_ast_node_list_copy(node->u.b.children);
- }
- __isl_give isl_ast_expr *isl_ast_node_user_get_expr(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_user)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a user node", return NULL);
- return isl_ast_expr_copy(node->u.e.expr);
- }
- /* Return the mark identifier of the mark node "node".
- */
- __isl_give isl_id *isl_ast_node_mark_get_id(__isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_mark)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a mark node", return NULL);
- return isl_id_copy(node->u.m.mark);
- }
- /* Return the node marked by mark node "node".
- */
- __isl_give isl_ast_node *isl_ast_node_mark_get_node(
- __isl_keep isl_ast_node *node)
- {
- if (!node)
- return NULL;
- if (node->type != isl_ast_node_mark)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a mark node", return NULL);
- return isl_ast_node_copy(node->u.m.node);
- }
- __isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node)
- {
- return node ? isl_id_copy(node->annotation) : NULL;
- }
- /* Replace node->annotation by "annotation".
- */
- __isl_give isl_ast_node *isl_ast_node_set_annotation(
- __isl_take isl_ast_node *node, __isl_take isl_id *annotation)
- {
- node = isl_ast_node_cow(node);
- if (!node || !annotation)
- goto error;
- isl_id_free(node->annotation);
- node->annotation = annotation;
- return node;
- error:
- isl_id_free(annotation);
- return isl_ast_node_free(node);
- }
- /* Traverse the elements of "list" and all their descendants
- * in depth first preorder.
- *
- * Return isl_stat_ok on success and isl_stat_error on failure.
- */
- static isl_stat nodelist_foreach(__isl_keep isl_ast_node_list *list,
- isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user), void *user)
- {
- int i;
- if (!list)
- return isl_stat_error;
- for (i = 0; i < list->n; ++i) {
- isl_stat ok;
- isl_ast_node *node = list->p[i];
- ok = isl_ast_node_foreach_descendant_top_down(node, fn, user);
- if (ok < 0)
- return isl_stat_error;
- }
- return isl_stat_ok;
- }
- /* Traverse the descendants of "node" (including the node itself)
- * in depth first preorder.
- *
- * If "fn" returns isl_bool_error on any of the nodes, then the traversal
- * is aborted.
- * If "fn" returns isl_bool_false on any of the nodes, then the subtree rooted
- * at that node is skipped.
- *
- * Return isl_stat_ok on success and isl_stat_error on failure.
- */
- isl_stat isl_ast_node_foreach_descendant_top_down(
- __isl_keep isl_ast_node *node,
- isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user), void *user)
- {
- isl_bool more;
- isl_stat ok;
- if (!node)
- return isl_stat_error;
- more = fn(node, user);
- if (more < 0)
- return isl_stat_error;
- if (!more)
- return isl_stat_ok;
- switch (node->type) {
- case isl_ast_node_for:
- node = node->u.f.body;
- return isl_ast_node_foreach_descendant_top_down(node, fn, user);
- case isl_ast_node_if:
- ok = isl_ast_node_foreach_descendant_top_down(node->u.i.then,
- fn, user);
- if (ok < 0)
- return isl_stat_error;
- if (!node->u.i.else_node)
- return isl_stat_ok;
- node = node->u.i.else_node;
- return isl_ast_node_foreach_descendant_top_down(node, fn, user);
- case isl_ast_node_block:
- return nodelist_foreach(node->u.b.children, fn, user);
- case isl_ast_node_mark:
- node = node->u.m.node;
- return isl_ast_node_foreach_descendant_top_down(node, fn, user);
- case isl_ast_node_user:
- break;
- case isl_ast_node_error:
- return isl_stat_error;
- }
- return isl_stat_ok;
- }
- /* Textual C representation of the various operators.
- */
- static char *op_str_c[] = {
- [isl_ast_expr_op_and] = "&&",
- [isl_ast_expr_op_and_then] = "&&",
- [isl_ast_expr_op_or] = "||",
- [isl_ast_expr_op_or_else] = "||",
- [isl_ast_expr_op_max] = "max",
- [isl_ast_expr_op_min] = "min",
- [isl_ast_expr_op_minus] = "-",
- [isl_ast_expr_op_add] = "+",
- [isl_ast_expr_op_sub] = "-",
- [isl_ast_expr_op_mul] = "*",
- [isl_ast_expr_op_fdiv_q] = "floord",
- [isl_ast_expr_op_pdiv_q] = "/",
- [isl_ast_expr_op_pdiv_r] = "%",
- [isl_ast_expr_op_zdiv_r] = "%",
- [isl_ast_expr_op_div] = "/",
- [isl_ast_expr_op_eq] = "==",
- [isl_ast_expr_op_le] = "<=",
- [isl_ast_expr_op_ge] = ">=",
- [isl_ast_expr_op_lt] = "<",
- [isl_ast_expr_op_gt] = ">",
- [isl_ast_expr_op_member] = ".",
- [isl_ast_expr_op_address_of] = "&"
- };
- /* Precedence in C of the various operators.
- * Based on http://en.wikipedia.org/wiki/Operators_in_C_and_C++
- * Lowest value means highest precedence.
- */
- static int op_prec[] = {
- [isl_ast_expr_op_and] = 13,
- [isl_ast_expr_op_and_then] = 13,
- [isl_ast_expr_op_or] = 14,
- [isl_ast_expr_op_or_else] = 14,
- [isl_ast_expr_op_max] = 2,
- [isl_ast_expr_op_min] = 2,
- [isl_ast_expr_op_minus] = 3,
- [isl_ast_expr_op_add] = 6,
- [isl_ast_expr_op_sub] = 6,
- [isl_ast_expr_op_mul] = 5,
- [isl_ast_expr_op_div] = 5,
- [isl_ast_expr_op_fdiv_q] = 2,
- [isl_ast_expr_op_pdiv_q] = 5,
- [isl_ast_expr_op_pdiv_r] = 5,
- [isl_ast_expr_op_zdiv_r] = 5,
- [isl_ast_expr_op_cond] = 15,
- [isl_ast_expr_op_select] = 15,
- [isl_ast_expr_op_eq] = 9,
- [isl_ast_expr_op_le] = 8,
- [isl_ast_expr_op_ge] = 8,
- [isl_ast_expr_op_lt] = 8,
- [isl_ast_expr_op_gt] = 8,
- [isl_ast_expr_op_call] = 2,
- [isl_ast_expr_op_access] = 2,
- [isl_ast_expr_op_member] = 2,
- [isl_ast_expr_op_address_of] = 3
- };
- /* Is the operator left-to-right associative?
- */
- static int op_left[] = {
- [isl_ast_expr_op_and] = 1,
- [isl_ast_expr_op_and_then] = 1,
- [isl_ast_expr_op_or] = 1,
- [isl_ast_expr_op_or_else] = 1,
- [isl_ast_expr_op_max] = 1,
- [isl_ast_expr_op_min] = 1,
- [isl_ast_expr_op_minus] = 0,
- [isl_ast_expr_op_add] = 1,
- [isl_ast_expr_op_sub] = 1,
- [isl_ast_expr_op_mul] = 1,
- [isl_ast_expr_op_div] = 1,
- [isl_ast_expr_op_fdiv_q] = 1,
- [isl_ast_expr_op_pdiv_q] = 1,
- [isl_ast_expr_op_pdiv_r] = 1,
- [isl_ast_expr_op_zdiv_r] = 1,
- [isl_ast_expr_op_cond] = 0,
- [isl_ast_expr_op_select] = 0,
- [isl_ast_expr_op_eq] = 1,
- [isl_ast_expr_op_le] = 1,
- [isl_ast_expr_op_ge] = 1,
- [isl_ast_expr_op_lt] = 1,
- [isl_ast_expr_op_gt] = 1,
- [isl_ast_expr_op_call] = 1,
- [isl_ast_expr_op_access] = 1,
- [isl_ast_expr_op_member] = 1,
- [isl_ast_expr_op_address_of] = 0
- };
- static int is_and(enum isl_ast_expr_op_type op)
- {
- return op == isl_ast_expr_op_and || op == isl_ast_expr_op_and_then;
- }
- static int is_or(enum isl_ast_expr_op_type op)
- {
- return op == isl_ast_expr_op_or || op == isl_ast_expr_op_or_else;
- }
- static int is_add_sub(enum isl_ast_expr_op_type op)
- {
- return op == isl_ast_expr_op_add || op == isl_ast_expr_op_sub;
- }
- static int is_div_mod(enum isl_ast_expr_op_type op)
- {
- return op == isl_ast_expr_op_div ||
- op == isl_ast_expr_op_pdiv_r ||
- op == isl_ast_expr_op_zdiv_r;
- }
- static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr);
- /* Do we need/want parentheses around "expr" as a subexpression of
- * an "op" operation? If "left" is set, then "expr" is the left-most
- * operand.
- *
- * We only need parentheses if "expr" represents an operation.
- *
- * If op has a higher precedence than expr->u.op.op, then we need
- * parentheses.
- * If op and expr->u.op.op have the same precedence, but the operations
- * are performed in an order that is different from the associativity,
- * then we need parentheses.
- *
- * An and inside an or technically does not require parentheses,
- * but some compilers complain about that, so we add them anyway.
- *
- * Computations such as "a / b * c" and "a % b + c" can be somewhat
- * difficult to read, so we add parentheses for those as well.
- */
- static int sub_expr_need_parens(enum isl_ast_expr_op_type op,
- __isl_keep isl_ast_expr *expr, int left)
- {
- if (expr->type != isl_ast_expr_op)
- return 0;
- if (op_prec[expr->u.op.op] > op_prec[op])
- return 1;
- if (op_prec[expr->u.op.op] == op_prec[op] && left != op_left[op])
- return 1;
- if (is_or(op) && is_and(expr->u.op.op))
- return 1;
- if (op == isl_ast_expr_op_mul && expr->u.op.op != isl_ast_expr_op_mul &&
- op_prec[expr->u.op.op] == op_prec[op])
- return 1;
- if (is_add_sub(op) && is_div_mod(expr->u.op.op))
- return 1;
- return 0;
- }
- /* Print "expr" as a subexpression of an "op" operation in C format.
- * If "left" is set, then "expr" is the left-most operand.
- */
- static __isl_give isl_printer *print_sub_expr_c(__isl_take isl_printer *p,
- enum isl_ast_expr_op_type op, __isl_keep isl_ast_expr *expr, int left)
- {
- int need_parens;
- need_parens = sub_expr_need_parens(op, expr, left);
- if (need_parens)
- p = isl_printer_print_str(p, "(");
- p = print_ast_expr_c(p, expr);
- if (need_parens)
- p = isl_printer_print_str(p, ")");
- return p;
- }
- #define isl_ast_expr_op_last isl_ast_expr_op_address_of
- /* Data structure that holds the user-specified textual
- * representations for the operators in C format.
- * The entries are either NULL or copies of strings.
- * A NULL entry means that the default name should be used.
- */
- struct isl_ast_expr_op_names {
- char *op_str[isl_ast_expr_op_last + 1];
- };
- /* Create an empty struct isl_ast_expr_op_names.
- */
- static void *create_names(isl_ctx *ctx)
- {
- return isl_calloc_type(ctx, struct isl_ast_expr_op_names);
- }
- /* Free a struct isl_ast_expr_op_names along with all memory
- * owned by the struct.
- */
- static void free_names(void *user)
- {
- int i;
- struct isl_ast_expr_op_names *names = user;
- if (!user)
- return;
- for (i = 0; i <= isl_ast_expr_op_last; ++i)
- free(names->op_str[i]);
- free(user);
- }
- /* Create an identifier that is used to store
- * an isl_ast_expr_op_names note.
- */
- static __isl_give isl_id *names_id(isl_ctx *ctx)
- {
- return isl_id_alloc(ctx, "isl_ast_expr_op_type_names", NULL);
- }
- /* Ensure that "p" has a note identified by "id".
- * If there is no such note yet, then it is created by "note_create" and
- * scheduled do be freed by "note_free".
- */
- static __isl_give isl_printer *alloc_note(__isl_take isl_printer *p,
- __isl_keep isl_id *id, void *(*note_create)(isl_ctx *),
- void (*note_free)(void *))
- {
- isl_ctx *ctx;
- isl_id *note_id;
- isl_bool has_note;
- void *note;
- has_note = isl_printer_has_note(p, id);
- if (has_note < 0)
- return isl_printer_free(p);
- if (has_note)
- return p;
- ctx = isl_printer_get_ctx(p);
- note = note_create(ctx);
- if (!note)
- return isl_printer_free(p);
- note_id = isl_id_alloc(ctx, NULL, note);
- if (!note_id)
- note_free(note);
- else
- note_id = isl_id_set_free_user(note_id, note_free);
- p = isl_printer_set_note(p, isl_id_copy(id), note_id);
- return p;
- }
- /* Ensure that "p" has an isl_ast_expr_op_names note identified by "id".
- */
- static __isl_give isl_printer *alloc_names(__isl_take isl_printer *p,
- __isl_keep isl_id *id)
- {
- return alloc_note(p, id, &create_names, &free_names);
- }
- /* Retrieve the note identified by "id" from "p".
- * The note is assumed to exist.
- */
- static void *get_note(__isl_keep isl_printer *p, __isl_keep isl_id *id)
- {
- void *note;
- id = isl_printer_get_note(p, isl_id_copy(id));
- note = isl_id_get_user(id);
- isl_id_free(id);
- return note;
- }
- /* Use "name" to print operations of type "type" to "p".
- *
- * Store the name in an isl_ast_expr_op_names note attached to "p", such that
- * it can be retrieved by get_op_str.
- */
- __isl_give isl_printer *isl_ast_expr_op_type_set_print_name(
- __isl_take isl_printer *p, enum isl_ast_expr_op_type type,
- __isl_keep const char *name)
- {
- isl_id *id;
- struct isl_ast_expr_op_names *names;
- if (!p)
- return NULL;
- if (type > isl_ast_expr_op_last)
- isl_die(isl_printer_get_ctx(p), isl_error_invalid,
- "invalid type", return isl_printer_free(p));
- id = names_id(isl_printer_get_ctx(p));
- p = alloc_names(p, id);
- names = get_note(p, id);
- isl_id_free(id);
- if (!names)
- return isl_printer_free(p);
- free(names->op_str[type]);
- names->op_str[type] = strdup(name);
- return p;
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_printer *isl_ast_op_type_set_print_name(
- __isl_take isl_printer *p, enum isl_ast_expr_op_type type,
- __isl_keep const char *name)
- {
- return isl_ast_expr_op_type_set_print_name(p, type, name);
- }
- /* Return the textual representation of "type" in C format.
- *
- * If there is a user-specified name in an isl_ast_expr_op_names note
- * associated to "p", then return that.
- * Otherwise, return the default name in op_str_c.
- */
- static const char *get_op_str_c(__isl_keep isl_printer *p,
- enum isl_ast_expr_op_type type)
- {
- isl_id *id;
- isl_bool has_names;
- struct isl_ast_expr_op_names *names = NULL;
- id = names_id(isl_printer_get_ctx(p));
- has_names = isl_printer_has_note(p, id);
- if (has_names >= 0 && has_names)
- names = get_note(p, id);
- isl_id_free(id);
- if (names && names->op_str[type])
- return names->op_str[type];
- return op_str_c[type];
- }
- /* Print a min or max reduction "expr" in C format.
- */
- static __isl_give isl_printer *print_min_max_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- int i = 0;
- for (i = 1; i < expr->u.op.n_arg; ++i) {
- p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
- p = isl_printer_print_str(p, "(");
- }
- p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
- for (i = 1; i < expr->u.op.n_arg; ++i) {
- p = isl_printer_print_str(p, ", ");
- p = print_ast_expr_c(p, expr->u.op.args[i]);
- p = isl_printer_print_str(p, ")");
- }
- return p;
- }
- /* Print a function call "expr" in C format.
- *
- * The first argument represents the function to be called.
- */
- static __isl_give isl_printer *print_call_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- int i = 0;
- p = print_ast_expr_c(p, expr->u.op.args[0]);
- p = isl_printer_print_str(p, "(");
- for (i = 1; i < expr->u.op.n_arg; ++i) {
- if (i != 1)
- p = isl_printer_print_str(p, ", ");
- p = print_ast_expr_c(p, expr->u.op.args[i]);
- }
- p = isl_printer_print_str(p, ")");
- return p;
- }
- /* Print an array access "expr" in C format.
- *
- * The first argument represents the array being accessed.
- */
- static __isl_give isl_printer *print_access_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- int i = 0;
- p = print_ast_expr_c(p, expr->u.op.args[0]);
- for (i = 1; i < expr->u.op.n_arg; ++i) {
- p = isl_printer_print_str(p, "[");
- p = print_ast_expr_c(p, expr->u.op.args[i]);
- p = isl_printer_print_str(p, "]");
- }
- return p;
- }
- /* Print "expr" to "p" in C format.
- */
- static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- if (!p)
- return NULL;
- if (!expr)
- return isl_printer_free(p);
- switch (expr->type) {
- case isl_ast_expr_op:
- if (expr->u.op.op == isl_ast_expr_op_call) {
- p = print_call_c(p, expr);
- break;
- }
- if (expr->u.op.op == isl_ast_expr_op_access) {
- p = print_access_c(p, expr);
- break;
- }
- if (expr->u.op.n_arg == 1) {
- p = isl_printer_print_str(p,
- get_op_str_c(p, expr->u.op.op));
- p = print_sub_expr_c(p, expr->u.op.op,
- expr->u.op.args[0], 0);
- break;
- }
- if (expr->u.op.op == isl_ast_expr_op_fdiv_q) {
- const char *name;
- name = get_op_str_c(p, isl_ast_expr_op_fdiv_q);
- p = isl_printer_print_str(p, name);
- p = isl_printer_print_str(p, "(");
- p = print_ast_expr_c(p, expr->u.op.args[0]);
- p = isl_printer_print_str(p, ", ");
- p = print_ast_expr_c(p, expr->u.op.args[1]);
- p = isl_printer_print_str(p, ")");
- break;
- }
- if (expr->u.op.op == isl_ast_expr_op_max ||
- expr->u.op.op == isl_ast_expr_op_min) {
- p = print_min_max_c(p, expr);
- break;
- }
- if (expr->u.op.op == isl_ast_expr_op_cond ||
- expr->u.op.op == isl_ast_expr_op_select) {
- p = print_ast_expr_c(p, expr->u.op.args[0]);
- p = isl_printer_print_str(p, " ? ");
- p = print_ast_expr_c(p, expr->u.op.args[1]);
- p = isl_printer_print_str(p, " : ");
- p = print_ast_expr_c(p, expr->u.op.args[2]);
- break;
- }
- if (expr->u.op.n_arg != 2)
- isl_die(isl_printer_get_ctx(p), isl_error_internal,
- "operation should have two arguments",
- return isl_printer_free(p));
- p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[0], 1);
- if (expr->u.op.op != isl_ast_expr_op_member)
- p = isl_printer_print_str(p, " ");
- p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
- if (expr->u.op.op != isl_ast_expr_op_member)
- p = isl_printer_print_str(p, " ");
- p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[1], 0);
- break;
- case isl_ast_expr_id:
- p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));
- break;
- case isl_ast_expr_int:
- p = isl_printer_print_val(p, expr->u.v);
- break;
- case isl_ast_expr_error:
- break;
- }
- return p;
- }
- /* Textual representation of the isl_ast_expr_op_type elements
- * for use in a YAML representation of an isl_ast_expr.
- */
- static char *op_str[] = {
- [isl_ast_expr_op_and] = "and",
- [isl_ast_expr_op_and_then] = "and_then",
- [isl_ast_expr_op_or] = "or",
- [isl_ast_expr_op_or_else] = "or_else",
- [isl_ast_expr_op_max] = "max",
- [isl_ast_expr_op_min] = "min",
- [isl_ast_expr_op_minus] = "minus",
- [isl_ast_expr_op_add] = "add",
- [isl_ast_expr_op_sub] = "sub",
- [isl_ast_expr_op_mul] = "mul",
- [isl_ast_expr_op_div] = "div",
- [isl_ast_expr_op_fdiv_q] = "fdiv_q",
- [isl_ast_expr_op_pdiv_q] = "pdiv_q",
- [isl_ast_expr_op_pdiv_r] = "pdiv_r",
- [isl_ast_expr_op_zdiv_r] = "zdiv_r",
- [isl_ast_expr_op_cond] = "cond",
- [isl_ast_expr_op_select] = "select",
- [isl_ast_expr_op_eq] = "eq",
- [isl_ast_expr_op_le] = "le",
- [isl_ast_expr_op_lt] = "lt",
- [isl_ast_expr_op_ge] = "ge",
- [isl_ast_expr_op_gt] = "gt",
- [isl_ast_expr_op_call] = "call",
- [isl_ast_expr_op_access] = "access",
- [isl_ast_expr_op_member] = "member",
- [isl_ast_expr_op_address_of] = "address_of"
- };
- static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr);
- /* Print the arguments of "expr" to "p" in isl format.
- *
- * If there are no arguments, then nothing needs to be printed.
- * Otherwise add an "args" key to the current mapping with as value
- * the list of arguments of "expr".
- */
- static __isl_give isl_printer *print_arguments(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- int i;
- isl_size n;
- n = isl_ast_expr_get_op_n_arg(expr);
- if (n < 0)
- return isl_printer_free(p);
- if (n == 0)
- return p;
- p = isl_printer_print_str(p, "args");
- p = isl_printer_yaml_next(p);
- p = isl_printer_yaml_start_sequence(p);
- for (i = 0; i < n; ++i) {
- isl_ast_expr *arg;
- arg = isl_ast_expr_get_op_arg(expr, i);
- p = print_ast_expr_isl(p, arg);
- isl_ast_expr_free(arg);
- p = isl_printer_yaml_next(p);
- }
- p = isl_printer_yaml_end_sequence(p);
- return p;
- }
- /* Print "expr" to "p" in isl format.
- *
- * In particular, print the isl_ast_expr as a YAML document.
- */
- static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- enum isl_ast_expr_type type;
- enum isl_ast_expr_op_type op;
- isl_id *id;
- isl_val *v;
- if (!expr)
- return isl_printer_free(p);
- p = isl_printer_yaml_start_mapping(p);
- type = isl_ast_expr_get_type(expr);
- switch (type) {
- case isl_ast_expr_error:
- return isl_printer_free(p);
- case isl_ast_expr_op:
- op = isl_ast_expr_get_op_type(expr);
- if (op == isl_ast_expr_op_error)
- return isl_printer_free(p);
- p = isl_printer_print_str(p, "op");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_str(p, op_str[op]);
- p = isl_printer_yaml_next(p);
- p = print_arguments(p, expr);
- break;
- case isl_ast_expr_id:
- p = isl_printer_print_str(p, "id");
- p = isl_printer_yaml_next(p);
- id = isl_ast_expr_get_id(expr);
- p = isl_printer_print_id(p, id);
- isl_id_free(id);
- break;
- case isl_ast_expr_int:
- p = isl_printer_print_str(p, "val");
- p = isl_printer_yaml_next(p);
- v = isl_ast_expr_get_val(expr);
- p = isl_printer_print_val(p, v);
- isl_val_free(v);
- break;
- }
- p = isl_printer_yaml_end_mapping(p);
- return p;
- }
- /* Print "expr" to "p".
- *
- * Only an isl and a C format are supported.
- */
- __isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
- __isl_keep isl_ast_expr *expr)
- {
- int format;
- if (!p)
- return NULL;
- format = isl_printer_get_output_format(p);
- switch (format) {
- case ISL_FORMAT_ISL:
- p = print_ast_expr_isl(p, expr);
- break;
- case ISL_FORMAT_C:
- p = print_ast_expr_c(p, expr);
- break;
- default:
- isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
- "output format not supported for ast_expr",
- return isl_printer_free(p));
- }
- return p;
- }
- static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node);
- /* Print a YAML sequence containing the entries in "list" to "p".
- */
- static __isl_give isl_printer *print_ast_node_list(__isl_take isl_printer *p,
- __isl_keep isl_ast_node_list *list)
- {
- int i;
- isl_size n;
- n = isl_ast_node_list_n_ast_node(list);
- if (n < 0)
- return isl_printer_free(p);
- p = isl_printer_yaml_start_sequence(p);
- for (i = 0; i < n; ++i) {
- isl_ast_node *node;
- node = isl_ast_node_list_get_ast_node(list, i);
- p = print_ast_node_isl(p, node);
- isl_ast_node_free(node);
- p = isl_printer_yaml_next(p);
- }
- p = isl_printer_yaml_end_sequence(p);
- return p;
- }
- /* Print "node" to "p" in "isl format".
- *
- * In particular, print the isl_ast_node as a YAML document.
- */
- static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node)
- {
- switch (node->type) {
- case isl_ast_node_for:
- p = isl_printer_yaml_start_mapping(p);
- p = isl_printer_print_str(p, "iterator");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.f.iterator);
- p = isl_printer_yaml_next(p);
- if (node->u.f.degenerate) {
- p = isl_printer_print_str(p, "value");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.f.init);
- p = isl_printer_yaml_next(p);
- } else {
- p = isl_printer_print_str(p, "init");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.f.init);
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_str(p, "cond");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.f.cond);
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_str(p, "inc");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.f.inc);
- p = isl_printer_yaml_next(p);
- }
- if (node->u.f.body) {
- p = isl_printer_print_str(p, "body");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_node(p, node->u.f.body);
- p = isl_printer_yaml_next(p);
- }
- p = isl_printer_yaml_end_mapping(p);
- break;
- case isl_ast_node_mark:
- p = isl_printer_yaml_start_mapping(p);
- p = isl_printer_print_str(p, "mark");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_id(p, node->u.m.mark);
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_str(p, "node");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_node(p, node->u.m.node);
- p = isl_printer_yaml_end_mapping(p);
- break;
- case isl_ast_node_user:
- p = isl_printer_yaml_start_mapping(p);
- p = isl_printer_print_str(p, "user");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.e.expr);
- p = isl_printer_yaml_end_mapping(p);
- break;
- case isl_ast_node_if:
- p = isl_printer_yaml_start_mapping(p);
- p = isl_printer_print_str(p, "guard");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_expr(p, node->u.i.guard);
- p = isl_printer_yaml_next(p);
- if (node->u.i.then) {
- p = isl_printer_print_str(p, "then");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_node(p, node->u.i.then);
- p = isl_printer_yaml_next(p);
- }
- if (node->u.i.else_node) {
- p = isl_printer_print_str(p, "else");
- p = isl_printer_yaml_next(p);
- p = isl_printer_print_ast_node(p, node->u.i.else_node);
- }
- p = isl_printer_yaml_end_mapping(p);
- break;
- case isl_ast_node_block:
- p = print_ast_node_list(p, node->u.b.children);
- break;
- case isl_ast_node_error:
- break;
- }
- return p;
- }
- /* Do we need to print a block around the body "node" of a for or if node?
- *
- * If the node is a block, then we need to print a block.
- * Also if the node is a degenerate for then we will print it as
- * an assignment followed by the body of the for loop, so we need a block
- * as well.
- * If the node is an if node with an else, then we print a block
- * to avoid spurious dangling else warnings emitted by some compilers.
- * If the node is a mark, then in principle, we would have to check
- * the child of the mark node. However, even if the child would not
- * require us to print a block, for readability it is probably best
- * to print a block anyway.
- * If the ast_always_print_block option has been set, then we print a block.
- */
- static int need_block(__isl_keep isl_ast_node *node)
- {
- isl_ctx *ctx;
- if (node->type == isl_ast_node_block)
- return 1;
- if (node->type == isl_ast_node_for && node->u.f.degenerate)
- return 1;
- if (node->type == isl_ast_node_if && node->u.i.else_node)
- return 1;
- if (node->type == isl_ast_node_mark)
- return 1;
- ctx = isl_ast_node_get_ctx(node);
- return isl_options_get_ast_always_print_block(ctx);
- }
- static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node,
- __isl_keep isl_ast_print_options *options, int in_block, int in_list);
- static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node,
- __isl_keep isl_ast_print_options *options, int new_line,
- int force_block);
- /* Print the body "node" of a for or if node.
- * If "else_node" is set, then it is printed as well.
- * If "force_block" is set, then print out the body as a block.
- *
- * We first check if we need to print out a block.
- * We always print out a block if there is an else node to make
- * sure that the else node is matched to the correct if node.
- * For consistency, the corresponding else node is also printed as a block.
- *
- * If the else node is itself an if, then we print it as
- *
- * } else if (..) {
- * }
- *
- * Otherwise the else node is printed as
- *
- * } else {
- * node
- * }
- */
- static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node, __isl_keep isl_ast_node *else_node,
- __isl_keep isl_ast_print_options *options, int force_block)
- {
- if (!node)
- return isl_printer_free(p);
- if (!force_block && !else_node && !need_block(node)) {
- p = isl_printer_end_line(p);
- p = isl_printer_indent(p, 2);
- p = isl_ast_node_print(node, p,
- isl_ast_print_options_copy(options));
- p = isl_printer_indent(p, -2);
- return p;
- }
- p = isl_printer_print_str(p, " {");
- p = isl_printer_end_line(p);
- p = isl_printer_indent(p, 2);
- p = print_ast_node_c(p, node, options, 1, 0);
- p = isl_printer_indent(p, -2);
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "}");
- if (else_node) {
- if (else_node->type == isl_ast_node_if) {
- p = isl_printer_print_str(p, " else ");
- p = print_if_c(p, else_node, options, 0, 1);
- } else {
- p = isl_printer_print_str(p, " else");
- p = print_body_c(p, else_node, NULL, options, 1);
- }
- } else
- p = isl_printer_end_line(p);
- return p;
- }
- /* Print the start of a compound statement.
- */
- static __isl_give isl_printer *start_block(__isl_take isl_printer *p)
- {
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "{");
- p = isl_printer_end_line(p);
- p = isl_printer_indent(p, 2);
- return p;
- }
- /* Print the end of a compound statement.
- */
- static __isl_give isl_printer *end_block(__isl_take isl_printer *p)
- {
- p = isl_printer_indent(p, -2);
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "}");
- p = isl_printer_end_line(p);
- return p;
- }
- /* Print the for node "node".
- *
- * If the for node is degenerate, it is printed as
- *
- * type iterator = init;
- * body
- *
- * Otherwise, it is printed as
- *
- * for (type iterator = init; cond; iterator += inc)
- * body
- *
- * "in_block" is set if we are currently inside a block.
- * "in_list" is set if the current node is not alone in the block.
- * If we are not in a block or if the current not is not alone in the block
- * then we print a block around a degenerate for loop such that the variable
- * declaration will not conflict with any potential other declaration
- * of the same variable.
- */
- static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node,
- __isl_keep isl_ast_print_options *options, int in_block, int in_list)
- {
- isl_id *id;
- const char *name;
- const char *type;
- type = isl_options_get_ast_iterator_type(isl_printer_get_ctx(p));
- if (!node->u.f.degenerate) {
- id = isl_ast_expr_get_id(node->u.f.iterator);
- name = isl_id_get_name(id);
- isl_id_free(id);
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "for (");
- p = isl_printer_print_str(p, type);
- p = isl_printer_print_str(p, " ");
- p = isl_printer_print_str(p, name);
- p = isl_printer_print_str(p, " = ");
- p = isl_printer_print_ast_expr(p, node->u.f.init);
- p = isl_printer_print_str(p, "; ");
- p = isl_printer_print_ast_expr(p, node->u.f.cond);
- p = isl_printer_print_str(p, "; ");
- p = isl_printer_print_str(p, name);
- p = isl_printer_print_str(p, " += ");
- p = isl_printer_print_ast_expr(p, node->u.f.inc);
- p = isl_printer_print_str(p, ")");
- p = print_body_c(p, node->u.f.body, NULL, options, 0);
- } else {
- id = isl_ast_expr_get_id(node->u.f.iterator);
- name = isl_id_get_name(id);
- isl_id_free(id);
- if (!in_block || in_list)
- p = start_block(p);
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, type);
- p = isl_printer_print_str(p, " ");
- p = isl_printer_print_str(p, name);
- p = isl_printer_print_str(p, " = ");
- p = isl_printer_print_ast_expr(p, node->u.f.init);
- p = isl_printer_print_str(p, ";");
- p = isl_printer_end_line(p);
- p = print_ast_node_c(p, node->u.f.body, options, 1, 0);
- if (!in_block || in_list)
- p = end_block(p);
- }
- return p;
- }
- /* Print the if node "node".
- * If "new_line" is set then the if node should be printed on a new line.
- * If "force_block" is set, then print out the body as a block.
- */
- static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node,
- __isl_keep isl_ast_print_options *options, int new_line,
- int force_block)
- {
- if (new_line)
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "if (");
- p = isl_printer_print_ast_expr(p, node->u.i.guard);
- p = isl_printer_print_str(p, ")");
- p = print_body_c(p, node->u.i.then, node->u.i.else_node, options,
- force_block);
- return p;
- }
- /* Print the "node" to "p".
- *
- * "in_block" is set if we are currently inside a block.
- * If so, we do not print a block around the children of a block node.
- * We do this to avoid an extra block around the body of a degenerate
- * for node.
- *
- * "in_list" is set if the current node is not alone in the block.
- */
- static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node,
- __isl_keep isl_ast_print_options *options, int in_block, int in_list)
- {
- switch (node->type) {
- case isl_ast_node_for:
- if (options->print_for)
- return options->print_for(p,
- isl_ast_print_options_copy(options),
- node, options->print_for_user);
- p = print_for_c(p, node, options, in_block, in_list);
- break;
- case isl_ast_node_if:
- p = print_if_c(p, node, options, 1, 0);
- break;
- case isl_ast_node_block:
- if (!in_block)
- p = start_block(p);
- p = isl_ast_node_list_print(node->u.b.children, p, options);
- if (!in_block)
- p = end_block(p);
- break;
- case isl_ast_node_mark:
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "// ");
- p = isl_printer_print_str(p, isl_id_get_name(node->u.m.mark));
- p = isl_printer_end_line(p);
- p = print_ast_node_c(p, node->u.m.node, options, 0, in_list);
- break;
- case isl_ast_node_user:
- if (options->print_user)
- return options->print_user(p,
- isl_ast_print_options_copy(options),
- node, options->print_user_user);
- p = isl_printer_start_line(p);
- p = isl_printer_print_ast_expr(p, node->u.e.expr);
- p = isl_printer_print_str(p, ";");
- p = isl_printer_end_line(p);
- break;
- case isl_ast_node_error:
- break;
- }
- return p;
- }
- /* Print the for node "node" to "p".
- */
- __isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
- __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
- {
- if (!node || !options)
- goto error;
- if (node->type != isl_ast_node_for)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not a for node", goto error);
- p = print_for_c(p, node, options, 0, 0);
- isl_ast_print_options_free(options);
- return p;
- error:
- isl_ast_print_options_free(options);
- isl_printer_free(p);
- return NULL;
- }
- /* Print the if node "node" to "p".
- */
- __isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
- __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
- {
- if (!node || !options)
- goto error;
- if (node->type != isl_ast_node_if)
- isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
- "not an if node", goto error);
- p = print_if_c(p, node, options, 1, 0);
- isl_ast_print_options_free(options);
- return p;
- error:
- isl_ast_print_options_free(options);
- isl_printer_free(p);
- return NULL;
- }
- /* Print "node" to "p".
- *
- * "node" is assumed to be either the outermost node in an AST or
- * a node that is known not to be a block.
- * If "node" is a block (and is therefore outermost) and
- * if the ast_print_outermost_block options is not set,
- * then act as if the printing occurs inside a block, such
- * that no "extra" block will get printed.
- */
- __isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
- __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
- {
- int in_block = 0;
- if (!options || !node)
- goto error;
- if (node->type == isl_ast_node_block) {
- isl_ctx *ctx;
- ctx = isl_ast_node_get_ctx(node);
- in_block = !isl_options_get_ast_print_outermost_block(ctx);
- }
- p = print_ast_node_c(p, node, options, in_block, 0);
- isl_ast_print_options_free(options);
- return p;
- error:
- isl_ast_print_options_free(options);
- isl_printer_free(p);
- return NULL;
- }
- /* Print "node" to "p".
- */
- __isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node)
- {
- int format;
- isl_ast_print_options *options;
- if (!p)
- return NULL;
- format = isl_printer_get_output_format(p);
- switch (format) {
- case ISL_FORMAT_ISL:
- p = print_ast_node_isl(p, node);
- break;
- case ISL_FORMAT_C:
- options = isl_ast_print_options_alloc(isl_printer_get_ctx(p));
- p = isl_ast_node_print(node, p, options);
- break;
- default:
- isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
- "output format not supported for ast_node",
- return isl_printer_free(p));
- }
- return p;
- }
- /* Print the list of nodes "list" to "p".
- */
- __isl_give isl_printer *isl_ast_node_list_print(
- __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
- __isl_keep isl_ast_print_options *options)
- {
- int i;
- if (!p || !list || !options)
- return isl_printer_free(p);
- for (i = 0; i < list->n; ++i)
- p = print_ast_node_c(p, list->p[i], options, 1, 1);
- return p;
- }
- #define ISL_AST_MACRO_FDIV_Q (1 << 0)
- #define ISL_AST_MACRO_MIN (1 << 1)
- #define ISL_AST_MACRO_MAX (1 << 2)
- #define ISL_AST_MACRO_ALL (ISL_AST_MACRO_FDIV_Q | \
- ISL_AST_MACRO_MIN | \
- ISL_AST_MACRO_MAX)
- /* If "expr" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or
- * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".
- */
- static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
- {
- int i;
- if (macros == ISL_AST_MACRO_ALL)
- return macros;
- if (expr->type != isl_ast_expr_op)
- return macros;
- if (expr->u.op.op == isl_ast_expr_op_min)
- macros |= ISL_AST_MACRO_MIN;
- if (expr->u.op.op == isl_ast_expr_op_max)
- macros |= ISL_AST_MACRO_MAX;
- if (expr->u.op.op == isl_ast_expr_op_fdiv_q)
- macros |= ISL_AST_MACRO_FDIV_Q;
- for (i = 0; i < expr->u.op.n_arg; ++i)
- macros = ast_expr_required_macros(expr->u.op.args[i], macros);
- return macros;
- }
- static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
- int macros);
- /* If "node" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or
- * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".
- */
- static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
- {
- if (macros == ISL_AST_MACRO_ALL)
- return macros;
- switch (node->type) {
- case isl_ast_node_for:
- macros = ast_expr_required_macros(node->u.f.init, macros);
- if (!node->u.f.degenerate) {
- macros = ast_expr_required_macros(node->u.f.cond,
- macros);
- macros = ast_expr_required_macros(node->u.f.inc,
- macros);
- }
- macros = ast_node_required_macros(node->u.f.body, macros);
- break;
- case isl_ast_node_if:
- macros = ast_expr_required_macros(node->u.i.guard, macros);
- macros = ast_node_required_macros(node->u.i.then, macros);
- if (node->u.i.else_node)
- macros = ast_node_required_macros(node->u.i.else_node,
- macros);
- break;
- case isl_ast_node_block:
- macros = ast_node_list_required_macros(node->u.b.children,
- macros);
- break;
- case isl_ast_node_mark:
- macros = ast_node_required_macros(node->u.m.node, macros);
- break;
- case isl_ast_node_user:
- macros = ast_expr_required_macros(node->u.e.expr, macros);
- break;
- case isl_ast_node_error:
- break;
- }
- return macros;
- }
- /* If "list" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or
- * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".
- */
- static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
- int macros)
- {
- int i;
- for (i = 0; i < list->n; ++i)
- macros = ast_node_required_macros(list->p[i], macros);
- return macros;
- }
- /* Data structure for keeping track of whether a macro definition
- * for a given type has already been printed.
- * The value is zero if no definition has been printed and non-zero otherwise.
- */
- struct isl_ast_expr_op_printed {
- char printed[isl_ast_expr_op_last + 1];
- };
- /* Create an empty struct isl_ast_expr_op_printed.
- */
- static void *create_printed(isl_ctx *ctx)
- {
- return isl_calloc_type(ctx, struct isl_ast_expr_op_printed);
- }
- /* Free a struct isl_ast_expr_op_printed.
- */
- static void free_printed(void *user)
- {
- free(user);
- }
- /* Ensure that "p" has an isl_ast_expr_op_printed note identified by "id".
- */
- static __isl_give isl_printer *alloc_printed(__isl_take isl_printer *p,
- __isl_keep isl_id *id)
- {
- return alloc_note(p, id, &create_printed, &free_printed);
- }
- /* Create an identifier that is used to store
- * an isl_ast_expr_op_printed note.
- */
- static __isl_give isl_id *printed_id(isl_ctx *ctx)
- {
- return isl_id_alloc(ctx, "isl_ast_expr_op_type_printed", NULL);
- }
- /* Did the user specify that a macro definition should only be
- * printed once and has a macro definition for "type" already
- * been printed to "p"?
- * If definitions should only be printed once, but a definition
- * for "p" has not yet been printed, then mark it as having been
- * printed so that it will not printed again.
- * The actual printing is taken care of by the caller.
- */
- static isl_bool already_printed_once(__isl_keep isl_printer *p,
- enum isl_ast_expr_op_type type)
- {
- isl_ctx *ctx;
- isl_id *id;
- struct isl_ast_expr_op_printed *printed;
- if (!p)
- return isl_bool_error;
- ctx = isl_printer_get_ctx(p);
- if (!isl_options_get_ast_print_macro_once(ctx))
- return isl_bool_false;
- if (type > isl_ast_expr_op_last)
- isl_die(isl_printer_get_ctx(p), isl_error_invalid,
- "invalid type", return isl_bool_error);
- id = printed_id(isl_printer_get_ctx(p));
- p = alloc_printed(p, id);
- printed = get_note(p, id);
- isl_id_free(id);
- if (!printed)
- return isl_bool_error;
- if (printed->printed[type])
- return isl_bool_true;
- printed->printed[type] = 1;
- return isl_bool_false;
- }
- /* Print a macro definition for the operator "type".
- *
- * If the user has specified that a macro definition should
- * only be printed once to any given printer and if the macro definition
- * has already been printed to "p", then do not print the definition.
- */
- __isl_give isl_printer *isl_ast_expr_op_type_print_macro(
- enum isl_ast_expr_op_type type, __isl_take isl_printer *p)
- {
- isl_bool skip;
- skip = already_printed_once(p, type);
- if (skip < 0)
- return isl_printer_free(p);
- if (skip)
- return p;
- switch (type) {
- case isl_ast_expr_op_min:
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "#define ");
- p = isl_printer_print_str(p, get_op_str_c(p, type));
- p = isl_printer_print_str(p,
- "(x,y) ((x) < (y) ? (x) : (y))");
- p = isl_printer_end_line(p);
- break;
- case isl_ast_expr_op_max:
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "#define ");
- p = isl_printer_print_str(p, get_op_str_c(p, type));
- p = isl_printer_print_str(p,
- "(x,y) ((x) > (y) ? (x) : (y))");
- p = isl_printer_end_line(p);
- break;
- case isl_ast_expr_op_fdiv_q:
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, "#define ");
- p = isl_printer_print_str(p, get_op_str_c(p, type));
- p = isl_printer_print_str(p,
- "(n,d) "
- "(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");
- p = isl_printer_end_line(p);
- break;
- default:
- break;
- }
- return p;
- }
- /* This is an alternative name for the function above.
- */
- __isl_give isl_printer *isl_ast_op_type_print_macro(
- enum isl_ast_expr_op_type type, __isl_take isl_printer *p)
- {
- return isl_ast_expr_op_type_print_macro(type, p);
- }
- /* Call "fn" for each type of operation represented in the "macros"
- * bit vector.
- */
- static isl_stat foreach_ast_expr_op_type(int macros,
- isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
- {
- if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_expr_op_min, user) < 0)
- return isl_stat_error;
- if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_expr_op_max, user) < 0)
- return isl_stat_error;
- if (macros & ISL_AST_MACRO_FDIV_Q &&
- fn(isl_ast_expr_op_fdiv_q, user) < 0)
- return isl_stat_error;
- return isl_stat_ok;
- }
- /* Call "fn" for each type of operation that appears in "expr"
- * and that requires a macro definition.
- */
- isl_stat isl_ast_expr_foreach_ast_expr_op_type(__isl_keep isl_ast_expr *expr,
- isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
- {
- int macros;
- if (!expr)
- return isl_stat_error;
- macros = ast_expr_required_macros(expr, 0);
- return foreach_ast_expr_op_type(macros, fn, user);
- }
- /* This is an alternative name for the function above.
- */
- isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,
- isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
- {
- return isl_ast_expr_foreach_ast_expr_op_type(expr, fn, user);
- }
- /* Call "fn" for each type of operation that appears in "node"
- * and that requires a macro definition.
- */
- isl_stat isl_ast_node_foreach_ast_expr_op_type(__isl_keep isl_ast_node *node,
- isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
- {
- int macros;
- if (!node)
- return isl_stat_error;
- macros = ast_node_required_macros(node, 0);
- return foreach_ast_expr_op_type(macros, fn, user);
- }
- /* This is an alternative name for the function above.
- */
- isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
- isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
- {
- return isl_ast_node_foreach_ast_expr_op_type(node, fn, user);
- }
- static isl_stat ast_op_type_print_macro(enum isl_ast_expr_op_type type,
- void *user)
- {
- isl_printer **p = user;
- *p = isl_ast_expr_op_type_print_macro(type, *p);
- return isl_stat_ok;
- }
- /* Print macro definitions for all the macros used in the result
- * of printing "expr".
- */
- __isl_give isl_printer *isl_ast_expr_print_macros(
- __isl_keep isl_ast_expr *expr, __isl_take isl_printer *p)
- {
- if (isl_ast_expr_foreach_ast_expr_op_type(expr,
- &ast_op_type_print_macro, &p) < 0)
- return isl_printer_free(p);
- return p;
- }
- /* Print macro definitions for all the macros used in the result
- * of printing "node".
- */
- __isl_give isl_printer *isl_ast_node_print_macros(
- __isl_keep isl_ast_node *node, __isl_take isl_printer *p)
- {
- if (isl_ast_node_foreach_ast_expr_op_type(node,
- &ast_op_type_print_macro, &p) < 0)
- return isl_printer_free(p);
- return p;
- }
- /* Return a string containing C code representing this isl_ast_expr.
- */
- __isl_give char *isl_ast_expr_to_C_str(__isl_keep isl_ast_expr *expr)
- {
- isl_printer *p;
- char *str;
- if (!expr)
- return NULL;
- p = isl_printer_to_str(isl_ast_expr_get_ctx(expr));
- p = isl_printer_set_output_format(p, ISL_FORMAT_C);
- p = isl_printer_print_ast_expr(p, expr);
- str = isl_printer_get_str(p);
- isl_printer_free(p);
- return str;
- }
- /* Return a string containing C code representing this isl_ast_node.
- */
- __isl_give char *isl_ast_node_to_C_str(__isl_keep isl_ast_node *node)
- {
- isl_printer *p;
- char *str;
- if (!node)
- return NULL;
- p = isl_printer_to_str(isl_ast_node_get_ctx(node));
- p = isl_printer_set_output_format(p, ISL_FORMAT_C);
- p = isl_printer_print_ast_node(p, node);
- str = isl_printer_get_str(p);
- isl_printer_free(p);
- return str;
- }
|