static LLVMValueRef assign_rvalue(compile_t* c, ast_t* left, ast_t* r_type, LLVMValueRef r_value) { switch(ast_id(left)) { case TK_VAR: case TK_LET: { // Generate the locals. if(gen_localdecl(c, left) == NULL) return NULL; return assign_rvalue(c, ast_child(left), r_type, r_value); } case TK_FVARREF: case TK_FLETREF: { // The result is the previous value of the field. LLVMValueRef l_value = gen_fieldptr(c, left); return assign_one(c, l_value, r_value, r_type); } case TK_VARREF: { // The result is the previous value of the local. LLVMValueRef l_value = gen_localptr(c, left); return assign_one(c, l_value, r_value, r_type); } case TK_TUPLE: { // If the l_value is a tuple, assemble it as the result. LLVMValueRef result = gen_expr(c, left); if(result == NULL) return NULL; if(!assign_tuple(c, left, r_type, r_value)) return NULL; // Return the original tuple. return result; } case TK_ID: { // We may have recursed here from a VAR or LET or arrived directly. const char* name = ast_name(left); LLVMValueRef l_value = codegen_getlocal(c, name); return assign_one(c, l_value, r_value, r_type); } default: {} } assert(0); return NULL; }
LLVMValueRef gen_localload(compile_t* c, ast_t* ast) { LLVMValueRef local_ptr = gen_localptr(c, ast); if(local_ptr == NULL) return NULL; return LLVMBuildLoad(c->builder, local_ptr, ""); }
LLVMValueRef gen_localload(compile_t* c, ast_t* ast) { LLVMValueRef local_ptr = gen_localptr(c, ast); if(local_ptr == NULL) return NULL; ast_t* type = deferred_reify(c->frame->reify, ast_type(ast), c->opt); reach_type_t* t = reach_type(c->reach, type); ast_free_unattached(type); compile_type_t* c_t = (compile_type_t*)t->c_type; LLVMValueRef value = LLVMBuildLoad(c->builder, local_ptr, ""); return gen_assign_cast(c, c_t->use_type, value, t->ast_cap); }
LLVMValueRef gen_addressof(compile_t* c, ast_t* ast) { ast_t* expr = ast_child(ast); switch(ast_id(expr)) { case TK_VARREF: case TK_LETREF: return gen_localptr(c, expr); case TK_FVARREF: case TK_FLETREF: return gen_fieldptr(c, expr); default: {} } assert(0); return NULL; }
static LLVMValueRef assign_rvalue(compile_t* c, ast_t* left, ast_t* r_type, LLVMValueRef r_value) { switch(ast_id(left)) { case TK_SEQ: // The actual expression is inside a sequence node. while(ast_id(left) == TK_SEQ) { assert(ast_childcount(left) == 1); left = ast_child(left); } return assign_rvalue(c, left, r_type, r_value); case TK_VAR: case TK_LET: { // Generate the locals. if(gen_localdecl(c, left) == NULL) return NULL; return assign_rvalue(c, ast_child(left), r_type, r_value); } case TK_FVARREF: case TK_FLETREF: { // The result is the previous value of the field. LLVMValueRef l_value = gen_fieldptr(c, left); return assign_one(c, l_value, r_value, r_type); } case TK_EMBEDREF: { // Do nothing. The embed field was already passed as the receiver. return GEN_NOVALUE; } case TK_VARREF: { // The result is the previous value of the local. LLVMValueRef l_value = gen_localptr(c, left); return assign_one(c, l_value, r_value, r_type); } case TK_TUPLE: { // If the l_value is a tuple, assemble it as the result. LLVMValueRef result = gen_expr(c, left); if(result == NULL) return NULL; if(!assign_tuple(c, left, r_type, r_value)) return NULL; // Return the original tuple. return result; } case TK_ID: { // We may have recursed here from a VAR or LET or arrived directly. const char* name = ast_name(left); LLVMValueRef l_value = codegen_getlocal(c, name); return assign_one(c, l_value, r_value, r_type); } default: {} } assert(0); return NULL; }