Mercurial > hg > Members > anatofuz > MoarVM
view src/mast/driver.c @ 64:da6d6597bd69 default tip
rollback
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 15 Feb 2019 20:51:54 +0900 |
parents | 2cf249471370 |
children |
line wrap: on
line source
#include "moar.h" #include "nodes.h" #include "compiler.h" /* Takes a hash of types and produces a MASTNodeTypes structure. */ #define grab_type(name) do { \ MVMString *key = MVM_string_utf8_decode(tc, tc->instance->VMString, #name, strlen(#name)); \ result->name = MVM_repr_at_key_o(tc, types, key); \ } while (0) static MASTNodeTypes * node_types_struct(MVMThreadContext *tc, MVMObject *types) { MASTNodeTypes *result = MVM_malloc(sizeof(MASTNodeTypes)); MVMROOT(tc, types, { grab_type(CompUnit); grab_type(Frame); grab_type(Op); grab_type(ExtOp); grab_type(SVal); grab_type(IVal); grab_type(NVal); grab_type(Label); grab_type(Local); grab_type(Lexical); grab_type(Call); grab_type(Annotated); grab_type(HandlerScope); }); return result; } /* Compiles MAST down to bytecode, then loads it as a compilation unit, * running deserialize and load frames as appropriate. */ void MVM_mast_to_cu(MVMThreadContext *tc, MVMObject *mast, MVMObject *types, MVMRegister *res) { MVMCompUnit *loaded; MVMROOT(tc, mast, { /* Get node types into struct. */ MASTNodeTypes *mnt = node_types_struct(tc, types); /* Turn the MAST tree into bytecode. Switch to gen2 GC allocation to be * sure nothing moves, though we'd really rather not have compiler * temporaries live longer. */ unsigned int size; char *bytecode; MVM_gc_allocate_gen2_default_set(tc); bytecode = MVM_mast_compile(tc, mast, mnt, &size); MVM_free(mnt); MVM_gc_allocate_gen2_default_clear(tc); /* Load it as a compilation unit; it is a kind of MVMObject, so cast * it to that. */ loaded = MVM_cu_from_bytes(tc, (MVMuint8 *)bytecode, (MVMuint32)size); loaded->body.deallocate = MVM_DEALLOCATE_FREE; }); /* Stash loaded comp unit in result register. */ res->o = (MVMObject *)loaded; /* If there's a deserialization frame, need to run that. */ if (loaded->body.deserialize_frame) { /* Set up special return to delegate to running the load frame, * if any. */ tc->cur_frame->return_value = NULL; tc->cur_frame->return_type = MVM_RETURN_VOID; /* Invoke the deserialization frame and return to the runloop. */ MVM_frame_invoke(tc, loaded->body.deserialize_frame, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_NULL_ARGS), NULL, NULL, NULL, -1); } } /* Compiles MAST down to bytecode, then writes it to disk. */ void MVM_mast_to_file(MVMThreadContext *tc, MVMObject *mast, MVMObject *types, MVMString *filename) { MVMROOT(tc, mast, { FILE *fh; char *c_filename; /* Get node types into struct. */ MASTNodeTypes *mnt = node_types_struct(tc, types); /* Turn the MAST tree into bytecode. */ unsigned int size; char *bytecode; MVM_gc_allocate_gen2_default_set(tc); bytecode = MVM_mast_compile(tc, mast, mnt, &size); MVM_free(mnt); MVM_gc_allocate_gen2_default_clear(tc); /* Write it out to a file. (Not using VM-level IO for this right now; * may want to do that in the future.) */ c_filename = MVM_string_utf8_c8_encode_C_string(tc, filename); if ((fh = fopen(c_filename, "wb+"))) { fwrite(bytecode, 1, size, fh); fclose(fh); MVM_free(c_filename); MVM_free(bytecode); } else { char *waste[2]; waste[0] = c_filename; waste[1] = NULL; MVM_free(bytecode); MVM_exception_throw_adhoc_free(tc, waste, "Unable to write bytecode to '%s'", c_filename); } }); }