void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return; case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, value, type); return; case TRACE_ACTOR: trace_actor(c, ctx, value); return; case TRACE_KNOWN_VAL: trace_known(c, ctx, value, type, true); return; case TRACE_UNKNOWN_VAL: trace_unknown(c, ctx, value, true); return; case TRACE_KNOWN: trace_known(c, ctx, value, type, false); return; case TRACE_UNKNOWN: trace_unknown(c, ctx, value, false); return; case TRACE_TAG: trace_tag(c, ctx, value); return; case TRACE_TAG_OR_ACTOR: trace_tag_or_actor(c, ctx, value); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, value, type, type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, value, type); return; } }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { switch(trace_type(type)) { case TRACE_NONE: assert(0); return; case TRACE_MACHINE_WORD: case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, value, type); return; case TRACE_VAL_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_IMMUTABLE); return; case TRACE_VAL_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_IMMUTABLE); return; case TRACE_MUT_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_MUTABLE); return; case TRACE_MUT_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_MUTABLE); return; case TRACE_TAG_KNOWN: trace_known(c, ctx, value, type, PONY_TRACE_OPAQUE); return; case TRACE_TAG_UNKNOWN: trace_unknown(c, ctx, value, PONY_TRACE_OPAQUE); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, value, type, type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, value, type); return; } }
static void trace_dynamic_union_or_isect(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { // Trace as every type. This results in maximal tracing. It also results in // all tuple elements eventually being maximally traced. for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { trace_dynamic(c, ctx, object, child, orig, tuple, next_block); } }
static void trace_dynamic_union_or_isect(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { // Trace as every type. This results in maximal tracing. It also results in // all tuple elements eventually being maximally traced. for(ast_t* child = ast_child(type); child != NULL; child = ast_sibling(child)) { trace_dynamic(c, ctx, object, child, orig, tuple, next_block); } // No type matched. This may be a boxed primitive: trace it here. trace_unknown(c, ctx, object, PONY_TRACE_OPAQUE); }
static void trace_dynamic_tuple(compile_t* c, LLVMValueRef ctx, LLVMValueRef ptr, LLVMValueRef desc, ast_t* type, ast_t* orig, ast_t* tuple) { // Build a "don't care" type of our cardinality. size_t cardinality = ast_childcount(type); ast_t* dontcare = ast_from(type, TK_TUPLETYPE); for(size_t i = 0; i < cardinality; i++) ast_append(dontcare, ast_from(type, TK_DONTCARE)); // Replace our type in the tuple type with the "don't care" type. bool in_tuple = (tuple != NULL); if(in_tuple) ast_swap(type, dontcare); else tuple = dontcare; // If the original type is a subtype of the test type, then we are always // the correct cardinality. Otherwise, we need to dynamically check // cardinality. LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); if(!is_subtype(orig, tuple, NULL)) { LLVMValueRef dynamic_count = gendesc_fieldcount(c, desc); LLVMValueRef static_count = LLVMConstInt(c->i32, cardinality, false); LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntEQ, static_count, dynamic_count, ""); // Skip if not the right cardinality. LLVMBuildCondBr(c->builder, test, is_true, is_false); } else { LLVMBuildBr(c->builder, is_true); } LLVMPositionBuilderAtEnd(c->builder, is_true); size_t index = 0; ast_t* child = ast_child(type); ast_t* dc_child = ast_child(dontcare); while(child != NULL) { switch(trace_type(child)) { case TRACE_PRIMITIVE: // Skip this element. break; case TRACE_ACTOR: case TRACE_KNOWN: case TRACE_UNKNOWN: case TRACE_KNOWN_VAL: case TRACE_UNKNOWN_VAL: case TRACE_TAG: case TRACE_TAG_OR_ACTOR: case TRACE_DYNAMIC: { // If we are (A, B), turn (_, _) into (A, _). ast_t* swap = ast_dup(child); ast_swap(dc_child, swap); // Create a next block. LLVMBasicBlockRef next_block = codegen_block(c, ""); // Load the object from the tuple field. LLVMValueRef field_info = gendesc_fieldinfo(c, desc, index); LLVMValueRef object = gendesc_fieldload(c, ptr, field_info); // Trace dynamic, even if the tuple thinks the field isn't dynamic. trace_dynamic(c, ctx, object, swap, orig, tuple, next_block); // Continue into the next block. LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); // Restore (A, _) to (_, _). ast_swap(swap, dc_child); ast_free_unattached(swap); break; } case TRACE_TUPLE: { // If we are (A, B), turn (_, _) into (A, _). ast_t* swap = ast_dup(child); ast_swap(dc_child, swap); // Get a pointer to the unboxed tuple and it's descriptor. LLVMValueRef field_info = gendesc_fieldinfo(c, desc, index); LLVMValueRef field_ptr = gendesc_fieldptr(c, ptr, field_info); LLVMValueRef field_desc = gendesc_fielddesc(c, field_info); // Trace the tuple dynamically. trace_dynamic_tuple(c, ctx, field_ptr, field_desc, swap, orig, tuple); // Restore (A, _) to (_, _). ast_swap(swap, dc_child); ast_free_unattached(swap); break; } default: {} } index++; child = ast_sibling(child); dc_child = ast_sibling(dc_child); } // Restore the tuple type. if(in_tuple) ast_swap(dontcare, type); ast_free_unattached(dontcare); // Continue with other possible tracings. LLVMBuildBr(c->builder, is_false); LLVMPositionBuilderAtEnd(c->builder, is_false); }
void gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef src_value, LLVMValueRef dst_value, ast_t* src_type, ast_t* dst_type) { trace_t trace_method = trace_type(src_type); if(src_type != dst_type) { trace_method = trace_type_dst_cap(trace_method, trace_type(dst_type), src_type); } switch(trace_method) { case TRACE_NONE: pony_assert(0); return; case TRACE_MACHINE_WORD: { bool boxed = true; if(ast_id(dst_type) == TK_NOMINAL) { ast_t* def = (ast_t*)ast_data(dst_type); if(ast_id(def) == TK_PRIMITIVE) boxed = false; } if(boxed) trace_known(c, ctx, dst_value, src_type, PONY_TRACE_IMMUTABLE); return; } case TRACE_PRIMITIVE: return; case TRACE_MAYBE: trace_maybe(c, ctx, dst_value, src_type); return; case TRACE_VAL_KNOWN: trace_known(c, ctx, dst_value, src_type, PONY_TRACE_IMMUTABLE); return; case TRACE_VAL_UNKNOWN: trace_unknown(c, ctx, dst_value, PONY_TRACE_IMMUTABLE); return; case TRACE_MUT_KNOWN: trace_known(c, ctx, dst_value, src_type, PONY_TRACE_MUTABLE); return; case TRACE_MUT_UNKNOWN: trace_unknown(c, ctx, dst_value, PONY_TRACE_MUTABLE); return; case TRACE_TAG_KNOWN: trace_known(c, ctx, dst_value, src_type, PONY_TRACE_OPAQUE); return; case TRACE_TAG_UNKNOWN: trace_unknown(c, ctx, dst_value, PONY_TRACE_OPAQUE); return; case TRACE_STATIC: trace_static(c, ctx, dst_value, src_type, dst_type); return; case TRACE_DYNAMIC: { LLVMBasicBlockRef next_block = codegen_block(c, ""); trace_dynamic(c, ctx, dst_value, src_type, dst_type, NULL, next_block); LLVMBuildBr(c->builder, next_block); LLVMPositionBuilderAtEnd(c->builder, next_block); return; } case TRACE_TUPLE: trace_tuple(c, ctx, src_value, dst_value, src_type, dst_type); return; } }