LLVMValueRef gen_localdecl(compile_t* c, ast_t* ast) { ast_t* id = ast_child(ast); const char* name = ast_name(id); // If this local has already been generated, don't create another copy. This // can happen when the same ast node is generated more than once, such as // the condition block of a while expression. LLVMValueRef value = codegen_getlocal(c, name); if(value != NULL) return GEN_NOVALUE; ast_t* type = deferred_reify(c->frame->reify, ast_type(id), c->opt); reach_type_t* t = reach_type(c->reach, type); ast_free_unattached(type); compile_type_t* c_t = (compile_type_t*)t->c_type; // All alloca should happen in the entry block of a function. LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(codegen_fun(c)); LLVMValueRef inst = LLVMGetFirstInstruction(entry_block); if(inst != NULL) LLVMPositionBuilderBefore(c->builder, inst); else LLVMPositionBuilderAtEnd(c->builder, entry_block); LLVMValueRef alloc = LLVMBuildAlloca(c->builder, c_t->mem_type, name); // Store the alloca to use when we reference this local. codegen_setlocal(c, name, alloc); LLVMMetadataRef file = codegen_difile(c); LLVMMetadataRef scope = codegen_discope(c); #if PONY_LLVM >= 700 uint32_t align_bytes = LLVMABIAlignmentOfType(c->target_data, c_t->mem_type); LLVMMetadataRef info = LLVMDIBuilderCreateAutoVariable(c->di, scope, name, strlen(name), file, (unsigned)ast_line(ast), c_t->di_type, true, LLVMDIFlagZero, align_bytes * 8); #else LLVMMetadataRef info = LLVMDIBuilderCreateAutoVariable(c->di, scope, name, file, (unsigned)ast_line(ast), c_t->di_type); #endif LLVMMetadataRef expr = LLVMDIBuilderCreateExpression(c->di, NULL, 0); LLVMDIBuilderInsertDeclare(c->di, alloc, info, expr, (unsigned)ast_line(ast), (unsigned)ast_pos(ast), scope, LLVMGetInsertBlock(c->builder)); // Put the builder back where it was. LLVMPositionBuilderAtEnd(c->builder, this_block); return GEN_NOTNEEDED; }
static LLVMMetadataRef make_debug_field(compile_t* c, reach_type_t* t, uint32_t i) { const char* name; char buf[32]; unsigned flags = 0; uint64_t offset = 0; ast_t* ast; if(t->underlying != TK_TUPLETYPE) { ast_t* def = (ast_t*)ast_data(t->ast); ast_t* members = ast_childidx(def, 4); ast = ast_childidx(members, i); name = ast_name(ast_child(ast)); if(is_name_private(name)) flags |= DW_FLAG_Private; uint32_t extra = 0; if(t->underlying != TK_STRUCT) extra++; if(t->underlying == TK_ACTOR) extra++; offset = LLVMOffsetOfElement(c->target_data, t->structure, i + extra); } else { snprintf(buf, 32, "_%d", i + 1); name = buf; ast = t->ast; offset = LLVMOffsetOfElement(c->target_data, t->primitive, i); } LLVMTypeRef type; LLVMMetadataRef di_type; if(t->fields[i].embed) { type = t->fields[i].type->structure; di_type = t->fields[i].type->di_type_embed; } else { type = t->fields[i].type->use_type; di_type = t->fields[i].type->di_type; } uint64_t size = LLVMABISizeOfType(c->target_data, type); uint64_t align = LLVMABIAlignmentOfType(c->target_data, type); return LLVMDIBuilderCreateMemberType(c->di, c->di_unit, name, t->di_file, (unsigned)ast_line(ast), 8 * size, 8 * align, 8 * offset, flags, di_type); }
static void setup_dwarf(dwarf_t* dwarf, dwarf_meta_t* meta, gentype_t* g, bool opaque, bool field) { memset(meta, 0, sizeof(dwarf_meta_t)); ast_t* ast = g->ast; LLVMTypeRef type = g->primitive; if(is_machine_word(ast)) { if(is_float(ast)) meta->flags |= DWARF_FLOAT; else if(is_signed(dwarf->opt, ast)) meta->flags |= DWARF_SIGNED; else if(is_bool(ast)) meta->flags |= DWARF_BOOLEAN; } else if(is_pointer(ast) || is_maybe(ast) || !is_concrete(ast) || (is_constructable(ast) && field)) { type = g->use_type; } else if(is_constructable(ast)) { type = g->structure; } bool defined_type = g->underlying != TK_TUPLETYPE && g->underlying != TK_UNIONTYPE && g->underlying != TK_ISECTTYPE; source_t* source; if(defined_type) ast = (ast_t*)ast_data(ast); source = ast_source(ast); meta->file = source->file; meta->name = g->type_name; meta->line = ast_line(ast); meta->pos = ast_pos(ast); if(!opaque) { meta->size = LLVMABISizeOfType(dwarf->target_data, type) << 3; meta->align = LLVMABIAlignmentOfType(dwarf->target_data, type) << 3; } }
static void make_debug_fields(compile_t* c, reach_type_t* t) { LLVMMetadataRef fields = NULL; if(t->field_count > 0) { size_t buf_size = t->field_count * sizeof(LLVMMetadataRef); LLVMMetadataRef* data = (LLVMMetadataRef*)ponyint_pool_alloc_size( buf_size); for(uint32_t i = 0; i < t->field_count; i++) data[i] = make_debug_field(c, t, i); fields = LLVMDIBuilderGetOrCreateArray(c->di, data, t->field_count); ponyint_pool_free_size(buf_size, data); } LLVMTypeRef type; if(t->underlying != TK_TUPLETYPE) type = t->structure; else type = t->primitive; uint64_t size = 0; uint64_t align = 0; if(type != NULL) { size = LLVMABISizeOfType(c->target_data, type); align = LLVMABIAlignmentOfType(c->target_data, type); } LLVMMetadataRef di_type = LLVMDIBuilderCreateStructType(c->di, c->di_unit, t->name, t->di_file, (unsigned) ast_line(t->ast), 8 * size, 8 * align, fields); if(t->underlying != TK_TUPLETYPE) { LLVMMetadataReplaceAllUsesWith(t->di_type_embed, di_type); t->di_type_embed = di_type; } else { LLVMMetadataReplaceAllUsesWith(t->di_type, di_type); t->di_type = di_type; } }
static void make_debug_basic(compile_t* c, reach_type_t* t) { uint64_t size = LLVMABISizeOfType(c->target_data, t->primitive); uint64_t align = LLVMABIAlignmentOfType(c->target_data, t->primitive); unsigned encoding; if(is_bool(t->ast)) { encoding = DW_ATE_boolean; } else if(is_float(t->ast)) { encoding = DW_ATE_float; } else if(is_signed(t->ast)) { encoding = DW_ATE_signed; } else { encoding = DW_ATE_unsigned; } t->di_type = LLVMDIBuilderCreateBasicType(c->di, t->name, 8 * size, 8 * align, encoding); }
/* TargetData.t -> Llvm.lltype -> int */ CAMLprim value llvm_abi_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { return Val_int(LLVMABIAlignmentOfType(TD, Ty)); }
/* Llvm.lltype -> DataLayout.t -> int */ CAMLprim value llvm_datalayout_abi_align(LLVMTypeRef Ty, value DL) { return Val_int(LLVMABIAlignmentOfType(DataLayout_val(DL), Ty)); }