/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: chuck_emit.cpp// desc: chuck instruction emitter//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Autumn 2002 - first version// Autumn 2004 - redesign//-----------------------------------------------------------------------------#include "chuck_emit.h"#include "chuck_vm.h"#include "chuck_errmsg.h"#include "chuck_instr.h"#include "chuck_globals.h" // added 1.4.1.0#include "chuck_parse.h" // added 1.5.0.0#include <sstream>#include <iostream> using namespace std; //-----------------------------------------------------------------------------// function prototypes//-----------------------------------------------------------------------------t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list );t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop = TRUE );t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt );t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt );t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt );t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt );t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt );t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt );t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt );t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br );t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont );t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt );t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt );t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef = FALSE );t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary );t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary );t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp );t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast );t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix );t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur );t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array );t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func, Chuck_Type * type, int linepos, t_CKBOOL spork = FALSE );t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call, t_CKBOOL spork = FALSE );t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call );t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member );t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if );t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp );t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array );t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val );t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val );t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val );t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt, t_CKBOOL push = TRUE );t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def );t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def );t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type );t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, a_Array_Sub array, t_CKBOOL is_ref );t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp );t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from );t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, Chuck_Value * v, t_CKBOOL emit_var, int linepos );// disabled until further notice (added 1.3.0.0)// t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Stmt stmt ); //-----------------------------------------------------------------------------// name: emit_engine_init()// desc: ...//-----------------------------------------------------------------------------Chuck_Emitter * emit_engine_init( Chuck_Env * env ){ // log EM_log( CK_LOG_SEVERE, "initializing emitter..." ); // TODO: ensure this in a better way assert( sizeof(t_CKUINT) == sizeof(void *) ); // allocate new emit Chuck_Emitter * emit = new Chuck_Emitter; // set the reference emit->env = env; return emit;} //-----------------------------------------------------------------------------// name: emit_engine_shutdown()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ){ if( !emit ) return FALSE; // log EM_log( CK_LOG_SYSTEM, "shutting down emitter..." ); // delete delete emit; emit = NULL; return TRUE;} //-----------------------------------------------------------------------------// name: emit_engine_emit_prog()// desc: ...//-----------------------------------------------------------------------------Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, te_HowMuch how_much ){ // make sure the code is NULL assert( emit->code == NULL ); // make sure the stack is empty assert( emit->stack.size() == 0 ); // make sure there is a context to emit assert( emit->env->context != NULL ); // make sure no code assert( emit->env->context->nspc->pre_ctor == NULL ); // log EM_log( CK_LOG_FINER, "(pass 4) emitting VM code '%s'...", emit->env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // return t_CKBOOL ret = TRUE; // allocate the code emit->code = new Chuck_Code; // set the current context emit->context = emit->env->context; // set the namespace emit->nspc = emit->context->nspc; // reset the func emit->func = NULL; // clear the code stack emit->stack.clear(); // name the code // emit->code->name = "(main)"; // whether code need this emit->code->need_this = TRUE; // keep track of full path (added 1.3.0.0) emit->code->filename = emit->context->full_path; // push global scope (added 1.3.0.0) emit->push_scope(); // loop over the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // code section // if only classes, then skip if( how_much == te_do_classes_only ) break; // emit statement list ret = emit_engine_emit_stmt_list( emit, prog->section->stmt_list ); break; case ae_section_func: // function definition // if only classes, then skip if( how_much == te_do_classes_only ) break; // check function definition ret = emit_engine_emit_func_def( emit, prog->section->func_def ); break; case ae_section_class: // class definition // if no classes, then skip if( how_much == te_do_no_classes ) break; // check class definition ret = emit_engine_emit_class_def( emit, prog->section->class_def ); break; default: // bad EM_error2( 0, "internal compiler error: unrecognized program section..." ); ret = FALSE; break; } // the next prog = prog->next; } // 1.4.1.0 (jack): error-checking: was dac-replacement initted? // (see chuck_compile.h for an explanation on replacement dacs) if( emit->should_replace_dac ) { if( !emit->env->vm()->globals_manager()->is_global_ugen_init( emit->dac_replacement ) ) { EM_error2( 0, "compiler error: dac replacement '%s' was never initialized...", emit->dac_replacement.c_str() ); EM_error2( 0, " ... (hint: need to declare this variable as a global UGen)" ); ret = FALSE; } // (also need to make sure it was constructed; see runtime error in // Chuck_Instr_Reg_Push_Global) } if( ret ) { // pop global scope (added 1.3.0.0) emit->pop_scope(); // append end of code emit->append( new Chuck_Instr_EOC ); // make sure assert( emit->context->nspc->pre_ctor == NULL ); // converted to virtual machine code emit->context->nspc->pre_ctor = emit_to_code( emit->code, NULL, emit->dump ); // add reference emit->context->nspc->pre_ctor->add_ref(); } // clear the code delete emit->code; emit->code = NULL; // pop indent EM_poplog(); // return the code return emit->context->nspc->pre_ctor;} //-----------------------------------------------------------------------------// name: emit_to_code()// desc: ...//-----------------------------------------------------------------------------Chuck_VM_Code * emit_to_code( Chuck_Code * in, Chuck_VM_Code * out, t_CKBOOL dump ){ // log EM_log( CK_LOG_FINER, "emitting code: %d VM instructions...", in->code.size() ); // allocate the vm code Chuck_VM_Code * code = out ? out : new Chuck_VM_Code; // make sure assert( code->num_instr == 0 ); // size code->num_instr = in->code.size(); // allocate instruction pointers+ code->instr = new Chuck_Instr *[code->num_instr]; // set the stack depth code->stack_depth = in->stack_depth; // set whether code need this base pointer code->need_this = in->need_this; // set whether static inside class | 1.4.1.0 (ge) added code->is_static = in->is_static; // set name code->name = in->name; // set filename for me.sourceDir() (added 1.3.0.0) code->filename = in->filename; // copy for( t_CKUINT i = 0; i < code->num_instr; i++ ) code->instr[i] = in->code[i]; // dump if( dump ) { // name of what we are dumping EM_error2( 0, "dumping %s:", in->name.c_str() ); // uh EM_error2( 0, "-------" ); for( t_CKUINT i = 0; i < code->num_instr; i++ ) { // check code str | 1.5.0.0 (ge) added if( code->instr[i]->m_codestr ) { // print the reconstructed code str EM_error2( 0, "%s", code->instr[i]->m_codestr->c_str() ); } // print the instruction EM_error2( 0, "[%i] %s( %s )", i, code->instr[i]->name(), code->instr[i]->params() ); } EM_error2( 0, "-------\n" ); } return code;} //-----------------------------------------------------------------------------// name:// desc: ...//-----------------------------------------------------------------------------// t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred ); //-----------------------------------------------------------------------------// name:// desc: ...//-----------------------------------------------------------------------------// t_CKBOOL emit_engine_resolve( ); //-----------------------------------------------------------------------------// name: emit_engine_emit_stmt_list()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ){ t_CKBOOL ret = TRUE; // emit->push(); while( list && ret ) { ret = emit_engine_emit_stmt( emit, list->stmt ); list = list->next; } // emit->pop(); return ret;} //-----------------------------------------------------------------------------// name: emit_engine_emit_stmt()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop ){ // empty stmt list if( !stmt ) return TRUE; // return t_CKBOOL ret = TRUE; // next index t_CKUINT nextIndex = 0; // expression string string codestr; // loop over statements switch( stmt->s_type ) { case ae_stmt_exp: // expression statement // get str codestr = absyn2str( stmt->stmt_exp ); // get next index | 1.5.0.0 (ge) added nextIndex = emit->next_index(); // emit it ret = emit_engine_emit_exp( emit, stmt->stmt_exp ); if( !ret ) return FALSE; // need to pop the final value from stack if( ret && pop && stmt->stmt_exp->type->size > 0 ) { // sanity assert( stmt->stmt_exp->cast_to == NULL ); // exp a_Exp exp = stmt->stmt_exp; // hack if( exp->s_type == ae_exp_primary && exp->primary.s_type == ae_primary_hack ) exp = exp->primary.exp; // need to pop in reverse order vector<a_Exp> pxe; // go while( exp ) { pxe.push_back( exp ); exp = exp->next; } // loop over the expression that is the statement (prior to 1.5.0.0 comment: "HACK" hmmm...) for( t_CKINT i = pxe.size()-1; i >= 0; i-- ) // for( t_CKINT i = 0; i < pxe.size(); i++ ) { exp = pxe[i]; // if decl, then expect only one word per var // added 1.3.1.0: iskindofint -- since on some 64-bit systems sz_INT == sz_FLOAT if( exp->s_type == ae_exp_decl ) { // (added 1.3.1.0 -- multiply by type size; #64-bit) // (fixed 1.3.1.2 -- uh... decl should also be int-sized, so changed to INT/WORD) emit->append( new Chuck_Instr_Reg_Pop_Word4( exp->decl.num_var_decls * sz_INT / sz_WORD ) ); } else if( exp->type->size == sz_INT && iskindofint(emit->env, exp->type) ) // ISSUE: 64-bit (fixed 1.3.1.0) { // is an object left on the stack for the stmt if( exp->s_type == ae_exp_func_call && isobj(emit->env, exp->type) ) { emit->append( new Chuck_Instr_Release_Object3_Pop_Word ); } else // not an object { emit->append( new Chuck_Instr_Reg_Pop_Word ); } } else if( exp->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) emit->append( new Chuck_Instr_Reg_Pop_Word2 ); else if( exp->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) emit->append( new Chuck_Instr_Reg_Pop_Word3 ); else if( exp->type->size == sz_VEC3 ) // ge: added 1.3.5.3 emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC3/sz_WORD) ); else if( exp->type->size == sz_VEC4 ) // ge: added 1.3.5.3 emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC4/sz_WORD) ); else { EM_error2( exp->linepos, "(emit): internal error: %i byte stack item unhandled...", exp->type->size ); return FALSE; } } } // see if we added at least one instruction if( nextIndex < emit->next_index() ) { // set codestr (for instruction dump) emit->code->code[nextIndex]->set_codestr( codestr ); } break; case ae_stmt_if: // if statement ret = emit_engine_emit_if( emit, &stmt->stmt_if ); break; case ae_stmt_for: // for statement ret = emit_engine_emit_for( emit, &stmt->stmt_for ); break; case ae_stmt_while: // while statement if( stmt->stmt_while.is_do ) ret = emit_engine_emit_do_while( emit, &stmt->stmt_while ); else ret = emit_engine_emit_while( emit, &stmt->stmt_while ); break; case ae_stmt_until: // until statement if( stmt->stmt_until.is_do ) ret = emit_engine_emit_do_until( emit, &stmt->stmt_until ); else ret = emit_engine_emit_until( emit, &stmt->stmt_until ); break; case ae_stmt_loop: // loop statement ret = emit_engine_emit_loop( emit, &stmt->stmt_loop );Lines 1–500 of 5331. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_emit.cpp // desc: chuck instruction emitter // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // date: Autumn 2002 - first version // Autumn 2004 - redesign //----------------------------------------------------------------------------- #include "chuck_emit.h" #include "chuck_vm.h" #include "chuck_errmsg.h" #include "chuck_instr.h" #include "chuck_globals.h" // added 1.4.1.0 #include "chuck_parse.h" // added 1.5.0.0 #include <sstream> #include <iostream> using namespace std; //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ); t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop = TRUE ); t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt ); t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt ); t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt ); t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt ); t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt ); t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt ); t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt ); t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br ); t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont ); t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt ); t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt ); t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef = FALSE ); t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary ); t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary ); t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp ); t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast ); t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix ); t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur ); t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array ); t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func, Chuck_Type * type, int linepos, t_CKBOOL spork = FALSE ); t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call, t_CKBOOL spork = FALSE ); t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call ); t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member ); t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if ); t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp ); t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array ); t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val ); t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val ); t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val ); t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def ); t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def ); t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type ); t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, a_Array_Sub array, t_CKBOOL is_ref ); t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ); t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from ); t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, Chuck_Value * v, t_CKBOOL emit_var, int linepos ); // disabled until further notice (added 1.3.0.0) // t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Stmt stmt ); //----------------------------------------------------------------------------- // name: emit_engine_init() // desc: ... //----------------------------------------------------------------------------- Chuck_Emitter * emit_engine_init( Chuck_Env * env ) { // log EM_log( CK_LOG_SEVERE, "initializing emitter..." ); // TODO: ensure this in a better way assert( sizeof(t_CKUINT) == sizeof(void *) ); // allocate new emit Chuck_Emitter * emit = new Chuck_Emitter; // set the reference emit->env = env; return emit; } //----------------------------------------------------------------------------- // name: emit_engine_shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ) { if( !emit ) return FALSE; // log EM_log( CK_LOG_SYSTEM, "shutting down emitter..." ); // delete delete emit; emit = NULL; return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_prog() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, te_HowMuch how_much ) { // make sure the code is NULL assert( emit->code == NULL ); // make sure the stack is empty assert( emit->stack.size() == 0 ); // make sure there is a context to emit assert( emit->env->context != NULL ); // make sure no code assert( emit->env->context->nspc->pre_ctor == NULL ); // log EM_log( CK_LOG_FINER, "(pass 4) emitting VM code '%s'...", emit->env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // return t_CKBOOL ret = TRUE; // allocate the code emit->code = new Chuck_Code; // set the current context emit->context = emit->env->context; // set the namespace emit->nspc = emit->context->nspc; // reset the func emit->func = NULL; // clear the code stack emit->stack.clear(); // name the code // emit->code->name = "(main)"; // whether code need this emit->code->need_this = TRUE; // keep track of full path (added 1.3.0.0) emit->code->filename = emit->context->full_path; // push global scope (added 1.3.0.0) emit->push_scope(); // loop over the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // code section // if only classes, then skip if( how_much == te_do_classes_only ) break; // emit statement list ret = emit_engine_emit_stmt_list( emit, prog->section->stmt_list ); break; case ae_section_func: // function definition // if only classes, then skip if( how_much == te_do_classes_only ) break; // check function definition ret = emit_engine_emit_func_def( emit, prog->section->func_def ); break; case ae_section_class: // class definition // if no classes, then skip if( how_much == te_do_no_classes ) break; // check class definition ret = emit_engine_emit_class_def( emit, prog->section->class_def ); break; default: // bad EM_error2( 0, "internal compiler error: unrecognized program section..." ); ret = FALSE; break; } // the next prog = prog->next; } // 1.4.1.0 (jack): error-checking: was dac-replacement initted? // (see chuck_compile.h for an explanation on replacement dacs) if( emit->should_replace_dac ) { if( !emit->env->vm()->globals_manager()->is_global_ugen_init( emit->dac_replacement ) ) { EM_error2( 0, "compiler error: dac replacement '%s' was never initialized...", emit->dac_replacement.c_str() ); EM_error2( 0, " ... (hint: need to declare this variable as a global UGen)" ); ret = FALSE; } // (also need to make sure it was constructed; see runtime error in // Chuck_Instr_Reg_Push_Global) } if( ret ) { // pop global scope (added 1.3.0.0) emit->pop_scope(); // append end of code emit->append( new Chuck_Instr_EOC ); // make sure assert( emit->context->nspc->pre_ctor == NULL ); // converted to virtual machine code emit->context->nspc->pre_ctor = emit_to_code( emit->code, NULL, emit->dump ); // add reference emit->context->nspc->pre_ctor->add_ref(); } // clear the code delete emit->code; emit->code = NULL; // pop indent EM_poplog(); // return the code return emit->context->nspc->pre_ctor; } //----------------------------------------------------------------------------- // name: emit_to_code() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Code * emit_to_code( Chuck_Code * in, Chuck_VM_Code * out, t_CKBOOL dump ) { // log EM_log( CK_LOG_FINER, "emitting code: %d VM instructions...", in->code.size() ); // allocate the vm code Chuck_VM_Code * code = out ? out : new Chuck_VM_Code; // make sure assert( code->num_instr == 0 ); // size code->num_instr = in->code.size(); // allocate instruction pointers+ code->instr = new Chuck_Instr *[code->num_instr]; // set the stack depth code->stack_depth = in->stack_depth; // set whether code need this base pointer code->need_this = in->need_this; // set whether static inside class | 1.4.1.0 (ge) added code->is_static = in->is_static; // set name code->name = in->name; // set filename for me.sourceDir() (added 1.3.0.0) code->filename = in->filename; // copy for( t_CKUINT i = 0; i < code->num_instr; i++ ) code->instr[i] = in->code[i]; // dump if( dump ) { // name of what we are dumping EM_error2( 0, "dumping %s:", in->name.c_str() ); // uh EM_error2( 0, "-------" ); for( t_CKUINT i = 0; i < code->num_instr; i++ ) { // check code str | 1.5.0.0 (ge) added if( code->instr[i]->m_codestr ) { // print the reconstructed code str EM_error2( 0, "%s", code->instr[i]->m_codestr->c_str() ); } // print the instruction EM_error2( 0, "[%i] %s( %s )", i, code->instr[i]->name(), code->instr[i]->params() ); } EM_error2( 0, "-------\n" ); } return code; } //----------------------------------------------------------------------------- // name: // desc: ... //----------------------------------------------------------------------------- // t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred ); //----------------------------------------------------------------------------- // name: // desc: ... //----------------------------------------------------------------------------- // t_CKBOOL emit_engine_resolve( ); //----------------------------------------------------------------------------- // name: emit_engine_emit_stmt_list() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ) { t_CKBOOL ret = TRUE; // emit->push(); while( list && ret ) { ret = emit_engine_emit_stmt( emit, list->stmt ); list = list->next; } // emit->pop(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_stmt() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop ) { // empty stmt list if( !stmt ) return TRUE; // return t_CKBOOL ret = TRUE; // next index t_CKUINT nextIndex = 0; // expression string string codestr; // loop over statements switch( stmt->s_type ) { case ae_stmt_exp: // expression statement // get str codestr = absyn2str( stmt->stmt_exp ); // get next index | 1.5.0.0 (ge) added nextIndex = emit->next_index(); // emit it ret = emit_engine_emit_exp( emit, stmt->stmt_exp ); if( !ret ) return FALSE; // need to pop the final value from stack if( ret && pop && stmt->stmt_exp->type->size > 0 ) { // sanity assert( stmt->stmt_exp->cast_to == NULL ); // exp a_Exp exp = stmt->stmt_exp; // hack if( exp->s_type == ae_exp_primary && exp->primary.s_type == ae_primary_hack ) exp = exp->primary.exp; // need to pop in reverse order vector<a_Exp> pxe; // go while( exp ) { pxe.push_back( exp ); exp = exp->next; } // loop over the expression that is the statement (prior to 1.5.0.0 comment: "HACK" hmmm...) for( t_CKINT i = pxe.size()-1; i >= 0; i-- ) // for( t_CKINT i = 0; i < pxe.size(); i++ ) { exp = pxe[i]; // if decl, then expect only one word per var // added 1.3.1.0: iskindofint -- since on some 64-bit systems sz_INT == sz_FLOAT if( exp->s_type == ae_exp_decl ) { // (added 1.3.1.0 -- multiply by type size; #64-bit) // (fixed 1.3.1.2 -- uh... decl should also be int-sized, so changed to INT/WORD) emit->append( new Chuck_Instr_Reg_Pop_Word4( exp->decl.num_var_decls * sz_INT / sz_WORD ) ); } else if( exp->type->size == sz_INT && iskindofint(emit->env, exp->type) ) // ISSUE: 64-bit (fixed 1.3.1.0) { // is an object left on the stack for the stmt if( exp->s_type == ae_exp_func_call && isobj(emit->env, exp->type) ) { emit->append( new Chuck_Instr_Release_Object3_Pop_Word ); } else // not an object { emit->append( new Chuck_Instr_Reg_Pop_Word ); } } else if( exp->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) emit->append( new Chuck_Instr_Reg_Pop_Word2 ); else if( exp->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) emit->append( new Chuck_Instr_Reg_Pop_Word3 ); else if( exp->type->size == sz_VEC3 ) // ge: added 1.3.5.3 emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC3/sz_WORD) ); else if( exp->type->size == sz_VEC4 ) // ge: added 1.3.5.3 emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC4/sz_WORD) ); else { EM_error2( exp->linepos, "(emit): internal error: %i byte stack item unhandled...", exp->type->size ); return FALSE; } } } // see if we added at least one instruction if( nextIndex < emit->next_index() ) { // set codestr (for instruction dump) emit->code->code[nextIndex]->set_codestr( codestr ); } break; case ae_stmt_if: // if statement ret = emit_engine_emit_if( emit, &stmt->stmt_if ); break; case ae_stmt_for: // for statement ret = emit_engine_emit_for( emit, &stmt->stmt_for ); break; case ae_stmt_while: // while statement if( stmt->stmt_while.is_do ) ret = emit_engine_emit_do_while( emit, &stmt->stmt_while ); else ret = emit_engine_emit_while( emit, &stmt->stmt_while ); break; case ae_stmt_until: // until statement if( stmt->stmt_until.is_do ) ret = emit_engine_emit_do_until( emit, &stmt->stmt_until ); else ret = emit_engine_emit_until( emit, &stmt->stmt_until ); break; case ae_stmt_loop: // loop statement ret = emit_engine_emit_loop( emit, &stmt->stmt_loop );