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_assign_value(compile_t* c, ast_t* left, LLVMValueRef right, ast_t* right_type) { // Must generate the right hand side before the left hand side. if(right == NULL) return NULL; // This is from pattern matching and we should not generate the alloca again. return assign_rvalue(c, ast_child(left), right_type, right); }
static bool assign_tuple(compile_t* c, ast_t* left, ast_t* r_type, LLVMValueRef r_value) { // Handle assignment for each component. ast_t* child = ast_child(left); ast_t* rtype_child = ast_child(r_type); int i = 0; while(child != NULL) { ast_t* expr = NULL; switch(ast_id(child)) { case TK_SEQ: // The actual tuple expression is inside a sequence node. expr = ast_child(child); break; case TK_LET: case TK_VAR: case TK_TUPLE: expr = child; break; case TK_DONTCARE: // Ignore this element. break; default: assert(0); } if(expr != NULL) { // Extract the tuple value. LLVMValueRef rvalue_child = LLVMBuildExtractValue(c->builder, r_value, i, ""); // Recurse, assigning pairwise. if(assign_rvalue(c, expr, rtype_child, rvalue_child) == NULL) return false; } i++; child = ast_sibling(child); rtype_child = ast_sibling(rtype_child); } assert(rtype_child == NULL); return true; }
LLVMValueRef gen_assign(compile_t* c, ast_t* ast) { // Must generate the right hand side before the left hand side. Left and // right are swapped for type checking, so we fetch them in reverse order. AST_GET_CHILDREN(ast, right, left); LLVMValueRef r_value = gen_expr(c, right); // Emit debug location of assignment expression dwarf_location(&c->dwarf, ast); if(r_value == NULL) return NULL; return assign_rvalue(c, left, ast_type(right), r_value); }
LLVMValueRef gen_assign(compile_t* c, ast_t* ast) { // Must generate the right hand side before the left hand side. Left and // right are swapped for type checking, so we fetch them in reverse order. AST_GET_CHILDREN(ast, right, left); LLVMValueRef r_value = gen_expr(c, right); if(r_value == NULL) return NULL; codegen_debugloc(c, ast); LLVMValueRef result = assign_rvalue(c, left, ast_type(right), r_value); codegen_debugloc(c, NULL); return result; }
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; }