LLVMValueRef gendesc_istrait(compile_t* c, LLVMValueRef desc, ast_t* type) { // Get the trait identifier. reach_type_t* t = reach_type(c->reach, type); assert(t != NULL); LLVMValueRef trait_id = LLVMConstInt(c->i32, t->type_id, false); // Read the count and the trait list from the descriptor. LLVMValueRef count = desc_field(c, desc, DESC_TRAIT_COUNT); LLVMValueRef list = desc_field(c, desc, DESC_TRAITS); LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef cond_block = codegen_block(c, "cond"); LLVMBasicBlockRef body_block = codegen_block(c, "body"); LLVMBasicBlockRef post_block = codegen_block(c, "post"); LLVMBuildBr(c->builder, cond_block); // While the index is less than the count, check an ID. LLVMPositionBuilderAtEnd(c->builder, cond_block); LLVMValueRef phi = LLVMBuildPhi(c->builder, c->i32, ""); LLVMValueRef zero = LLVMConstInt(c->i32, 0, false); LLVMAddIncoming(phi, &zero, &entry_block, 1); LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, count, ""); LLVMBuildCondBr(c->builder, test, body_block, post_block); // The phi node is the index. Get ID and compare it. LLVMPositionBuilderAtEnd(c->builder, body_block); LLVMValueRef gep[2]; gep[0] = LLVMConstInt(c->i32, 0, false); gep[1] = phi; LLVMValueRef id_ptr = LLVMBuildInBoundsGEP(c->builder, list, gep, 2, ""); LLVMValueRef id = LLVMBuildLoad(c->builder, id_ptr, ""); LLVMValueRef test_id = LLVMBuildICmp(c->builder, LLVMIntEQ, id, trait_id, ""); // Add one to the phi node. LLVMValueRef one = LLVMConstInt(c->i32, 1, false); LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, ""); LLVMAddIncoming(phi, &inc, &body_block, 1); // Either to the post block or back to the condition. LLVMBuildCondBr(c->builder, test_id, post_block, cond_block); LLVMPositionBuilderAtEnd(c->builder, post_block); LLVMValueRef result = LLVMBuildPhi(c->builder, c->i1, ""); LLVMAddIncoming(result, &test, &cond_block, 1); LLVMAddIncoming(result, &test_id, &body_block, 1); return result; }
LLVMValueRef gendesc_ptr_to_fields(compile_t* c, LLVMValueRef object, LLVMValueRef desc) { // Skip the descriptor. LLVMValueRef offset = desc_field(c, desc, DESC_FIELD_OFFSET); offset = LLVMBuildZExt(c->builder, offset, c->intptr, ""); LLVMValueRef base = LLVMBuildBitCast(c->builder, object, c->void_ptr, ""); return LLVMBuildInBoundsGEP(c->builder, base, &offset, 1, ""); }
LLVMValueRef gendesc_fieldinfo(compile_t* c, LLVMValueRef desc, size_t index) { LLVMValueRef fields = desc_field(c, desc, DESC_FIELDS); LLVMValueRef gep[2]; gep[0] = LLVMConstInt(c->i32, 0, false); gep[1] = LLVMConstInt(c->i32, index, false); LLVMValueRef field_desc = LLVMBuildGEP(c->builder, fields, gep, 2, ""); return LLVMBuildLoad(c->builder, field_desc, ""); }
LLVMValueRef gendesc_ptr_to_fields(compile_t* c, LLVMValueRef object, LLVMValueRef desc) { // Skip the descriptor. LLVMValueRef offset = desc_field(c, desc, DESC_FIELD_OFFSET); offset = LLVMBuildZExt(c->builder, offset, c->intptr, ""); LLVMValueRef base = LLVMBuildPtrToInt(c->builder, object, c->intptr, ""); LLVMValueRef result = LLVMBuildAdd(c->builder, base, offset, ""); // Return as a c->intptr. return result; }
LLVMValueRef gendesc_fieldcount(compile_t* c, LLVMValueRef desc) { return desc_field(c, desc, DESC_FIELD_COUNT); }
LLVMValueRef gendesc_dispatch(compile_t* c, LLVMValueRef object) { return desc_field(c, gendesc_fetch(c, object), DESC_DISPATCH); }
LLVMValueRef gendesc_trace(compile_t* c, LLVMValueRef object) { return desc_field(c, gendesc_fetch(c, object), DESC_TRACE); }