LLVMTypeRef gendesc_type(compile_t* c, gentype_t* g) { const char* desc_name; uint32_t traits = 0; uint32_t fields = 0; uint32_t vtable_size = 0; if(g != NULL) { // TODO: wrong trait count desc_name = g->desc_name; traits = trait_count(c, g, NULL, NULL); if(g->underlying == TK_TUPLETYPE) { fields = g->field_count; } else { vtable_size = genfun_vtable_size(c, g); } } else { desc_name = genname_descriptor(NULL); } LLVMTypeRef type = LLVMGetTypeByName(c->module, desc_name); if(type == NULL) { type = LLVMStructCreateNamed(c->context, desc_name); } else if(!LLVMIsOpaqueStruct(type)) { return type; } LLVMTypeRef params[DESC_LENGTH]; params[DESC_ID] = c->i32; params[DESC_SIZE] = c->i32; params[DESC_TRAIT_COUNT] = c->i32; params[DESC_FIELD_COUNT] = c->i32; params[DESC_FIELD_OFFSET] = c->i32; params[DESC_TRACE] = c->trace_fn; params[DESC_SERIALISE] = c->trace_fn; params[DESC_DESERIALISE] = c->trace_fn; params[DESC_DISPATCH] = c->dispatch_fn; params[DESC_FINALISE] = c->final_fn; params[DESC_EVENT_NOTIFY] = c->i32; params[DESC_TRAITS] = LLVMPointerType(LLVMArrayType(c->i32, traits), 0); params[DESC_FIELDS] = LLVMPointerType( LLVMArrayType(c->field_descriptor, fields), 0); params[DESC_VTABLE] = LLVMArrayType(c->void_ptr, vtable_size); LLVMStructSetBody(type, params, DESC_LENGTH, false); return type; }
static void make_box_type(compile_t* c, gentype_t* g) { if(g->primitive == NULL) return; if(g->structure == NULL) { const char* box_name = genname_box(g->type_name); g->structure = LLVMGetTypeByName(c->module, box_name); if(g->structure == NULL) g->structure = LLVMStructCreateNamed(c->context, box_name); } if(LLVMIsOpaqueStruct(g->structure)) { LLVMTypeRef elements[2]; elements[0] = LLVMPointerType(g->desc_type, 0); elements[1] = g->primitive; LLVMStructSetBody(g->structure, elements, 2, false); } g->structure_ptr = LLVMPointerType(g->structure, 0); }
/** * Return true if the type already exists or if we are only being asked to * generate a preliminary type, false otherwise. */ static bool setup_name(compile_t* c, ast_t* ast, gentype_t* g, bool prelim) { if(ast_id(ast) == TK_NOMINAL) { ast_t* def = (ast_t*)ast_data(ast); g->underlying = ast_id(def); // Find the primitive type, if there is one. AST_GET_CHILDREN(ast, pkg, id); const char* package = ast_name(pkg); const char* name = ast_name(id); if(package == c->str_builtin) { if(name == c->str_Bool) g->primitive = c->i1; else if(name == c->str_I8) g->primitive = c->i8; else if(name == c->str_U8) g->primitive = c->i8; else if(name == c->str_I16) g->primitive = c->i16; else if(name == c->str_U16) g->primitive = c->i16; else if(name == c->str_I32) g->primitive = c->i32; else if(name == c->str_U32) g->primitive = c->i32; else if(name == c->str_I64) g->primitive = c->i64; else if(name == c->str_U64) g->primitive = c->i64; else if(name == c->str_I128) g->primitive = c->i128; else if(name == c->str_U128) g->primitive = c->i128; #if defined(PLATFORM_IS_ILP32) else if(name == c->str_ILong) g->primitive = c->i32; else if(name == c->str_ULong) g->primitive = c->i32; else if(name == c->str_ISize) g->primitive = c->i32; else if(name == c->str_USize) g->primitive = c->i32; #elif defined(PLATFORM_IS_LP64) else if(name == c->str_ILong) g->primitive = c->i64; else if(name == c->str_ULong) g->primitive = c->i64; else if(name == c->str_ISize) g->primitive = c->i64; else if(name == c->str_USize) g->primitive = c->i64; #elif defined(PLATFORM_IS_LLP64) else if(name == c->str_ILong) g->primitive = c->i32; else if(name == c->str_ULong) g->primitive = c->i32; else if(name == c->str_ISize) g->primitive = c->i64; else if(name == c->str_USize) g->primitive = c->i64; #endif else if(name == c->str_F32) g->primitive = c->f32; else if(name == c->str_F64) g->primitive = c->f64; else if(name == c->str_Pointer) return genprim_pointer(c, g, prelim); else if(name == c->str_Maybe) return genprim_maybe(c, g, prelim); else if(name == c->str_Platform) return true; } } else { g->underlying = TK_TUPLETYPE; } // Find or create the structure type. g->structure = LLVMGetTypeByName(c->module, g->type_name); if(g->structure == NULL) g->structure = LLVMStructCreateNamed(c->context, g->type_name); bool opaque = LLVMIsOpaqueStruct(g->structure) != 0; if(g->underlying == TK_TUPLETYPE) { // This is actually our primitive type. g->primitive = g->structure; g->structure = NULL; } else { g->structure_ptr = LLVMPointerType(g->structure, 0); } // Fill in our global descriptor. make_global_descriptor(c, g); if(g->primitive != NULL) { // We're primitive, so use the primitive type. g->use_type = g->primitive; } else { // We're not primitive, so use a pointer to our structure. g->use_type = g->structure_ptr; } if(!opaque) { // Fill in our global instance if the type is not opaque. make_global_instance(c, g); // Fill in a box type if we need one. make_box_type(c, g); return true; } return prelim; }
static bool make_struct(compile_t* c, gentype_t* g) { LLVMTypeRef type; int extra = 0; if(g->underlying != TK_TUPLETYPE) { type = g->structure; if(g->underlying != TK_STRUCT) extra++; } else { type = g->primitive; } if(g->underlying == TK_ACTOR) extra++; size_t buf_size = (g->field_count + extra) * sizeof(LLVMTypeRef); LLVMTypeRef* elements = (LLVMTypeRef*)pool_alloc_size(buf_size); // Create the type descriptor as element 0. if(extra > 0) elements[0] = LLVMPointerType(g->desc_type, 0); // Create the actor pad as element 1. if(g->underlying == TK_ACTOR) elements[1] = c->actor_pad; // Get a preliminary type for each field and set the struct body. This is // needed in case a struct for the type being generated here is required when // generating a field. for(int i = 0; i < g->field_count; i++) { gentype_t field_g; bool ok; if((g->field_keys != NULL) && (g->field_keys[i] == TK_EMBED)) { ok = gentype(c, g->fields[i], &field_g); elements[i + extra] = field_g.structure; } else { ok = gentype_prelim(c, g->fields[i], &field_g); elements[i + extra] = field_g.use_type; } if(!ok) { pool_free_size(buf_size, elements); return false; } } // An embedded field may have caused the current type to be fully generated // at this point. If so, finish gracefully. if(!LLVMIsOpaqueStruct(type)) { g->done = true; return true; } LLVMStructSetBody(type, elements, g->field_count + extra, false); // Create a box type for tuples. if(g->underlying == TK_TUPLETYPE) make_box_type(c, g); pool_free_size(buf_size, elements); return true; }