LLVMValueRef gen_localdecl(compile_t* c, ast_t* ast) { ast_t* id = ast_child(ast); ast_t* type = ast_type(id); gentype_t g; if(!gentype(c, type, &g)) return NULL; // 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); const char* name = ast_name(id); LLVMValueRef l_value = LLVMBuildAlloca(c->builder, g.use_type, name); // Store the alloca to use when we reference this local. codegen_setlocal(c, name, l_value); // Emit debug info for local variable declaration. dwarf_local(&c->dwarf, ast, g.type_name, entry_block, inst, l_value); // Put the builder back where it was. LLVMPositionBuilderAtEnd(c->builder, this_block); return GEN_NOVALUE; }
unsigned ac_count_scratch_private_memory(LLVMValueRef function) { unsigned private_mem_vgprs = 0; /* Process all LLVM instructions. */ LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(function); while (bb) { LLVMValueRef next = LLVMGetFirstInstruction(bb); while (next) { LLVMValueRef inst = next; next = LLVMGetNextInstruction(next); if (LLVMGetInstructionOpcode(inst) != LLVMAlloca) continue; LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(inst)); /* No idea why LLVM aligns allocas to 4 elements. */ unsigned alignment = LLVMGetAlignment(inst); unsigned dw_size = align(ac_get_type_size(type) / 4, alignment); private_mem_vgprs += dw_size; } bb = LLVMGetNextBasicBlock(bb); } return private_mem_vgprs; }
int llvm_test_callsite_attributes(void) { LLVMEnablePrettyStackTrace(); LLVMModuleRef M = llvm_load_module(false, true); LLVMValueRef F = LLVMGetFirstFunction(M); while (F) { LLVMBasicBlockRef BB; for (BB = LLVMGetFirstBasicBlock(F); BB; BB = LLVMGetNextBasicBlock(BB)) { LLVMValueRef I; for (I = LLVMGetFirstInstruction(BB); I; I = LLVMGetNextInstruction(I)) { if (LLVMIsACallInst(I)) { // Read attributes int Idx, ParamCount; for (Idx = LLVMAttributeFunctionIndex, ParamCount = LLVMCountParams(F); Idx <= ParamCount; ++Idx) { int AttrCount = LLVMGetCallSiteAttributeCount(I, Idx); LLVMAttributeRef *Attrs = (LLVMAttributeRef *)malloc( AttrCount * sizeof(LLVMAttributeRef)); assert(Attrs); LLVMGetCallSiteAttributes(I, Idx, Attrs); free(Attrs); } } } } F = LLVMGetNextFunction(F); } LLVMDisposeModule(M); return 0; }
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; }
LLVMValueRef gen_break(compile_t* c, ast_t* ast) { ast_t* body = ast_child(ast); LLVMBasicBlockRef target; if(ast_id(body) == TK_NONE) { target = c->frame->break_novalue_target; } else { ast_t* body_type = ast_type(body); // Get the break target. target = c->frame->break_target; // Get the phi node. LLVMValueRef post_phi = LLVMGetFirstInstruction(target); bool needed = (post_phi != NULL) && LLVMIsAPHINode(post_phi); // Build the break expression. LLVMValueRef value = gen_expr(c, body); if(needed) { // Cast it to the phi type if we need to. LLVMTypeRef phi_type = LLVMTypeOf(post_phi); value = gen_assign_cast(c, phi_type, value, body_type); } if(value == NULL) return NULL; // Add break value to the post block phi node. if(needed) { LLVMBasicBlockRef insert_block = LLVMGetInsertBlock(c->builder); LLVMAddIncoming(post_phi, &value, &insert_block, 1); } } // Jump to the break target. codegen_scope_lifetime_end(c); codegen_debugloc(c, ast); LLVMBuildBr(c->builder, target); codegen_debugloc(c, NULL); return GEN_NOVALUE; }
LLVMValueRef gen_localdecl(compile_t* c, ast_t* ast) { ast_t* id = ast_child(ast); ast_t* type = ast_type(id); 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; reach_type_t* t = reach_type(c->reach, 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, t->use_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); LLVMMetadataRef info = LLVMDIBuilderCreateAutoVariable(c->di, scope, name, file, (unsigned)ast_line(ast), t->di_type); 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_NOVALUE; }
static LLVMBuilderRef create_builder_at_entry(struct gallivm_state *gallivm) { LLVMBuilderRef builder = gallivm->builder; LLVMBasicBlockRef current_block = LLVMGetInsertBlock(builder); LLVMValueRef function = LLVMGetBasicBlockParent(current_block); LLVMBasicBlockRef first_block = LLVMGetEntryBasicBlock(function); LLVMValueRef first_instr = LLVMGetFirstInstruction(first_block); LLVMBuilderRef first_builder = LLVMCreateBuilderInContext(gallivm->context); if (first_instr) { LLVMPositionBuilderBefore(first_builder, first_instr); } else { LLVMPositionBuilderAtEnd(first_builder, first_block); } return first_builder; }
/** * Count the number of instructions in a function. */ unsigned lp_build_count_instructions(LLVMValueRef function) { unsigned num_instrs = 0; LLVMBasicBlockRef block; block = LLVMGetFirstBasicBlock(function); while (block) { LLVMValueRef instr; instr = LLVMGetFirstInstruction(block); while (instr) { ++num_instrs; instr = LLVMGetNextInstruction(instr); } block = LLVMGetNextBasicBlock(block); } return num_instrs; }
int module_list_functions(void) { LLVMModuleRef M = load_module(false, false); LLVMValueRef f; f = LLVMGetFirstFunction(M); while (f) { if (LLVMIsDeclaration(f)) { printf("FunctionDeclaration: %s\n", LLVMGetValueName(f)); } else { LLVMBasicBlockRef bb; LLVMValueRef isn; unsigned nisn = 0; unsigned nbb = 0; printf("FunctionDefinition: %s [#bb=%u]\n", LLVMGetValueName(f), LLVMCountBasicBlocks(f)); for (bb = LLVMGetFirstBasicBlock(f); bb; bb = LLVMGetNextBasicBlock(bb)) { nbb++; for (isn = LLVMGetFirstInstruction(bb); isn; isn = LLVMGetNextInstruction(isn)) { nisn++; if (LLVMIsACallInst(isn)) { LLVMValueRef callee = LLVMGetOperand(isn, LLVMGetNumOperands(isn) - 1); printf(" calls: %s\n", LLVMGetValueName(callee)); } } } printf(" #isn: %u\n", nisn); printf(" #bb: %u\n\n", nbb); } f = LLVMGetNextFunction(f); } LLVMDisposeModule(M); return 0; }
LLVMValueRef codegen_ctx(compile_t* c) { compile_frame_t* frame = c->frame; while(!frame->is_function) frame = frame->prev; if(frame->ctx == NULL) { LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder); LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(frame->fun); LLVMValueRef inst = LLVMGetFirstInstruction(entry_block); if(inst != NULL) LLVMPositionBuilderBefore(c->builder, inst); else LLVMPositionBuilderAtEnd(c->builder, entry_block); frame->ctx = gencall_runtime(c, "pony_ctx", NULL, 0, ""); LLVMPositionBuilderAtEnd(c->builder, this_block); } return frame->ctx; }
void ac_optimize_vs_outputs(struct ac_llvm_context *ctx, LLVMValueRef main_fn, uint8_t *vs_output_param_offset, uint32_t num_outputs, uint8_t *num_param_exports) { LLVMBasicBlockRef bb; bool removed_any = false; struct ac_vs_exports exports; exports.num = 0; /* Process all LLVM instructions. */ bb = LLVMGetFirstBasicBlock(main_fn); while (bb) { LLVMValueRef inst = LLVMGetFirstInstruction(bb); while (inst) { LLVMValueRef cur = inst; inst = LLVMGetNextInstruction(inst); struct ac_vs_exp_inst exp; if (LLVMGetInstructionOpcode(cur) != LLVMCall) continue; LLVMValueRef callee = ac_llvm_get_called_value(cur); if (!ac_llvm_is_function(callee)) continue; const char *name = LLVMGetValueName(callee); unsigned num_args = LLVMCountParams(callee); /* Check if this is an export instruction. */ if ((num_args != 9 && num_args != 8) || (strcmp(name, "llvm.SI.export") && strcmp(name, "llvm.amdgcn.exp.f32"))) continue; LLVMValueRef arg = LLVMGetOperand(cur, AC_EXP_TARGET); unsigned target = LLVMConstIntGetZExtValue(arg); if (target < V_008DFC_SQ_EXP_PARAM) continue; target -= V_008DFC_SQ_EXP_PARAM; /* Parse the instruction. */ memset(&exp, 0, sizeof(exp)); exp.offset = target; exp.inst = cur; for (unsigned i = 0; i < 4; i++) { LLVMValueRef v = LLVMGetOperand(cur, AC_EXP_OUT0 + i); exp.chan[i].value = v; if (LLVMIsUndef(v)) { exp.chan[i].type = AC_IR_UNDEF; } else if (LLVMIsAConstantFP(v)) { LLVMBool loses_info; exp.chan[i].type = AC_IR_CONST; exp.chan[i].const_float = LLVMConstRealGetDouble(v, &loses_info); } else { exp.chan[i].type = AC_IR_VALUE; } } /* Eliminate constant and duplicated PARAM exports. */ if (ac_eliminate_const_output(vs_output_param_offset, num_outputs, &exp) || ac_eliminate_duplicated_output(vs_output_param_offset, num_outputs, &exports, &exp)) { removed_any = true; } else { exports.exp[exports.num++] = exp; } } bb = LLVMGetNextBasicBlock(bb); } /* Remove holes in export memory due to removed PARAM exports. * This is done by renumbering all PARAM exports. */ if (removed_any) { uint8_t old_offset[VARYING_SLOT_MAX]; unsigned out, i; /* Make a copy of the offsets. We need the old version while * we are modifying some of them. */ memcpy(old_offset, vs_output_param_offset, sizeof(old_offset)); for (i = 0; i < exports.num; i++) { unsigned offset = exports.exp[i].offset; /* Update vs_output_param_offset. Multiple outputs can * have the same offset. */ for (out = 0; out < num_outputs; out++) { if (old_offset[out] == offset) vs_output_param_offset[out] = i; } /* Change the PARAM offset in the instruction. */ LLVMSetOperand(exports.exp[i].inst, AC_EXP_TARGET, LLVMConstInt(ctx->i32, V_008DFC_SQ_EXP_PARAM + i, 0)); } *num_param_exports = exports.num; } }