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(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { switch(ast_id(type)) { case TK_UNIONTYPE: case TK_ISECTTYPE: trace_dynamic_union_or_isect(c, ctx, object, type, orig, tuple, next_block); break; case TK_TUPLETYPE: { // This is a boxed tuple. Trace the box, then handle the elements. trace_unknown(c, ctx, object, PONY_TRACE_OPAQUE); LLVMValueRef desc = gendesc_fetch(c, object); LLVMValueRef ptr = gendesc_ptr_to_fields(c, object, desc); trace_dynamic_tuple(c, ctx, ptr, desc, type, orig, tuple); break; } case TK_NOMINAL: trace_dynamic_nominal(c, ctx, object, type, orig, tuple, next_block); break; default: {} } }
static void trace_static(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* src_type, ast_t* dst_type) { pony_assert(ast_id(src_type) == TK_NOMINAL); int mutability = trace_cap_nominal(c->opt, src_type, dst_type, NULL); pony_assert(mutability != -1); if(is_known(src_type)) trace_known(c, ctx, object, src_type, mutability); else trace_unknown(c, ctx, object, mutability); }
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_tuple(compile_t* c, LLVMValueRef ctx, LLVMValueRef src_value, LLVMValueRef dst_value, ast_t* src_type, ast_t* dst_type) { int i = 0; // We're a tuple, determined statically. if(ast_id(dst_type) == TK_TUPLETYPE) { ast_t* src_child = ast_child(src_type); ast_t* dst_child = ast_child(dst_type); while((src_child != NULL) && (dst_child != NULL)) { // Extract each element and trace it. LLVMValueRef elem = LLVMBuildExtractValue(c->builder, dst_value, i, ""); gentrace(c, ctx, elem, elem, src_child, dst_child); i++; src_child = ast_sibling(src_child); dst_child = ast_sibling(dst_child); } pony_assert(src_child == NULL && dst_child == NULL); } else { // This is a boxed tuple. Trace the box, then handle the elements. trace_unknown(c, ctx, dst_value, PONY_TRACE_OPAQUE); // Extract the elements from the original unboxed tuple. pony_assert(LLVMGetTypeKind(LLVMTypeOf(src_value)) == LLVMStructTypeKind); ast_t* src_child = ast_child(src_type); while(src_child != NULL) { LLVMValueRef elem = LLVMBuildExtractValue(c->builder, src_value, i, ""); gentrace(c, ctx, elem, elem, src_child, src_child); i++; src_child = ast_sibling(src_child); } } }
bool gentrace(compile_t* c, LLVMValueRef ctx, LLVMValueRef value, ast_t* type) { bool tag = trace_as_tag(c, value, type); switch(ast_id(type)) { case TK_UNIONTYPE: case TK_ISECTTYPE: { if(tag) trace_tag_or_actor(c, ctx, value); else trace_unknown(c, ctx, value); return true; } case TK_TUPLETYPE: return trace_tuple(c, ctx, value, type); case TK_NOMINAL: { switch(ast_id((ast_t*)ast_data(type))) { case TK_INTERFACE: case TK_TRAIT: if(tag) trace_tag_or_actor(c, ctx, value); else trace_unknown(c, ctx, value); return true; case TK_PRIMITIVE: // Do nothing. return false; case TK_STRUCT: case TK_CLASS: if(tag) { if(is_maybe(type)) trace_maybe(c, ctx, value, type, true); else trace_tag(c, ctx, value); return true; } if(is_maybe(type)) { trace_maybe(c, ctx, value, type, false); return true; } return trace_known(c, ctx, value, type); case TK_ACTOR: trace_actor(c, ctx, value); return true; default: {} } break; } default: {} } assert(0); return 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; } }