-
Notifications
You must be signed in to change notification settings - Fork 2
Compilation Schemas
La traduction d’instructions d’une machine a pile vers une machine a registre exige une certaine adaptation du code.
Il est donc important de comprendre que dans le générateur, l’Accu n’est pas une variable explicite LLVM, mais une variable du compilateur qui contient le dernier registreutilisé, qui correspond a l’accumulateur dans la version a pile.
De la même manière, les opérations “PUSH” et “POP” dans les schémas de compilations ne donnent lieu a aucune génération d’instructions llvm. Elles influent sur la pile de compilation, soit sur une pile qui dans le compilateur maintient la correspondance Pile<→Registres LLVM. Cette pile est locale a chaque bloc généré. La manière dont la cohérence des opérations sur la pile entre différents blocs est maintenue est complexe et dépasse le cadre de ce prérapport.
Pour des besoins de rapidité d’implantation et de simplicité du compilateur, de nombreuses instructions sont compilées a l’aide d’une ou plusieurs fonctions implantées en C. Ceci n’implique pas de pertes de performances, car LLVM peut inliner ces fonctions, que nous lui fournissons sous forme de bytecode LLVM.
Dans les schemas de compilation, la syntaxe LLVM est simplifiée (les types ne sont pas présents par exemple) pour des besoins de lisibilité.
compile(CONST N) ->
%[Accu] = Const(N)
compile(PUSHCONST N) ->
%[Accu] = Const(N)
[push()]
compile(POP N) ->
[pop() N times]
compile(PUSHTRAP) ->
%buffer = @call getNewBuffer()
%setJmpRes = @call setJump(%buffer)
br %setJmpRes exceptionBlock continueBlock
[push() unit 4 times]
compile(POPTRAP) ->
call removeExceptionContext();
[pop() 4 times]
compile(RAISE) ->
call throwException(%[Accu]);
ret %[Accu]
compile(ACC N) ->
%[Accu] = %[get compile stack value N]
compile(PUSHACC N) ->
[push()]
%[Accu] = %[get compile stack value N]
compile(ENVACC N) ->
%env = call getEnv();
%[Accu] = call getField(env, N)
compile(PUSHENVACC N) ->
[push()]
%env = call getEnv();
%[Accu] = call getField(env, N)
compile(ADDINT) ->
%tmp = sub %[get stack @ 0], 1
[pop()]
%[Accu] = add %[Accu], %tmp
compile(NEGINT) ->
%[Accu] = sub 2, %[Accu]
compile(SUBINT) ->
%tmp = sub %[Accu], %[get stack @ 1]
[pop()]
%[Accu] = add %tmp, 1
compile(MULINT) ->
%[Accu] = ~valInt(mul ~intVal(%[Accu]), ~intVal(%[get stack @ 1]))
[pop()]
compile(DIVINT) ->
%[Accu] = ~valInt(div ~intVal(%[Accu]), ~intVal(%[get stack @ 1]))
[pop()]
compile(MODINT) ->
%[Accu] = ~valInt(srem ~intVal(%[Accu]), ~intVal(%[get stack @ 1]))
[pop()]
compile(OFFSETINT N) ->
%[Accu] = add %[Accu], N << 1