static void genfun_dwarf(compile_t* c, gentype_t* g, const char *name, ast_t* typeargs, ast_t* fun) { if(!codegen_hassource(c)) return; // Get the function. const char* funname = genname_fun(g->type_name, name, typeargs); LLVMValueRef func = LLVMGetNamedFunction(c->module, funname); assert(func != NULL); // Count the parameters, including the receiver. ast_t* params = ast_childidx(fun, 3); size_t count = ast_childcount(params) + 1; size_t buf_size = (count + 1) * sizeof(const char*); const char** pnames = (const char**)pool_alloc_size(buf_size); count = 0; // Return value type name and receiver type name. pnames[count++] = genname_type(ast_childidx(fun, 4)); pnames[count++] = g->type_name; // Get a type name for each parameter. ast_t* param = ast_child(params); while(param != NULL) { ast_t* ptype = ast_childidx(param, 1); pnames[count++] = genname_type(ptype); param = ast_sibling(param); } // Dwarf the method type dwarf_method(&c->dwarf, fun, name, funname, pnames, count, func); // Dwarf the receiver pointer. LLVMBasicBlockRef entry = LLVMGetEntryBasicBlock(codegen_fun(c)); LLVMValueRef argument = codegen_getlocal(c, stringtab("this")); dwarf_this(&c->dwarf, fun, g->type_name, entry, argument); // Dwarf locals for parameters param = ast_child(params); size_t index = 1; while(param != NULL) { argument = codegen_getlocal(c, ast_name(ast_child(param))); dwarf_parameter(&c->dwarf, param, pnames[index + 1], entry, argument, index); param = ast_sibling(param); index++; } pool_free_size(buf_size, pnames); }
LLVMValueRef gen_expr(compile_t* c, ast_t* ast) { LLVMValueRef ret; bool has_scope = ast_has_scope(ast); bool has_source = codegen_hassource(c); if(has_scope) { codegen_pushscope(c); // Dwarf a new lexical scope, if necessary. if(has_source) dwarf_lexicalscope(&c->dwarf, ast); } switch(ast_id(ast)) { case TK_SEQ: ret = gen_seq(c, ast); break; case TK_FVARREF: case TK_FLETREF: ret = gen_fieldload(c, ast); break; case TK_PARAMREF: ret = gen_param(c, ast); break; case TK_VAR: case TK_LET: ret = gen_localdecl(c, ast); break; case TK_VARREF: case TK_LETREF: ret = gen_localload(c, ast); break; case TK_IF: ret = gen_if(c, ast); break; case TK_WHILE: ret = gen_while(c, ast); break; case TK_REPEAT: ret = gen_repeat(c, ast); break; case TK_TRY: case TK_TRY_NO_CHECK: ret = gen_try(c, ast); break; case TK_MATCH: ret = gen_match(c, ast); break; case TK_CALL: ret = gen_call(c, ast); break; case TK_CONSUME: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_RECOVER: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_BREAK: ret = gen_break(c, ast); break; case TK_CONTINUE: ret = gen_continue(c, ast); break; case TK_RETURN: ret = gen_return(c, ast); break; case TK_ERROR: ret = gen_error(c, ast); break; case TK_IS: ret = gen_is(c, ast); break; case TK_ISNT: ret = gen_isnt(c, ast); break; case TK_ASSIGN: ret = gen_assign(c, ast); break; case TK_THIS: ret = gen_this(c, ast); break; case TK_TRUE: ret = LLVMConstInt(c->i1, 1, false); break; case TK_FALSE: ret = LLVMConstInt(c->i1, 0, false); break; case TK_INT: ret = gen_int(c, ast); break; case TK_FLOAT: ret = gen_float(c, ast); break; case TK_STRING: ret = gen_string(c, ast); break; case TK_TUPLE: ret = gen_tuple(c, ast); break; case TK_FFICALL: ret = gen_ffi(c, ast); break; case TK_AMP: ret = gen_addressof(c, ast); break; case TK_IDENTITY: ret = gen_identity(c, ast); break; case TK_DONTCARE: ret = GEN_NOVALUE; break; case TK_COMPILER_INTRINSIC: ast_error(ast, "unimplemented compiler intrinsic"); LLVMBuildUnreachable(c->builder); ret = GEN_NOVALUE; break; default: ast_error(ast, "not implemented (codegen unknown)"); return NULL; } if(has_scope) { codegen_popscope(c); if(has_source) dwarf_finish(&c->dwarf); } return ret; }