LLVMValueRef gen_string(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); const char* name = ast_name(ast); size_t len = ast_name_len(ast); LLVMValueRef args[4]; args[0] = LLVMConstInt(c->i32, 0, false); args[1] = LLVMConstInt(c->i32, 0, false); LLVMValueRef str = LLVMConstStringInContext(c->context, name, (int)len, false); LLVMValueRef g_str = LLVMAddGlobal(c->module, LLVMTypeOf(str), ""); LLVMSetLinkage(g_str, LLVMPrivateLinkage); LLVMSetInitializer(g_str, str); LLVMSetGlobalConstant(g_str, true); LLVMValueRef str_ptr = LLVMConstInBoundsGEP(g_str, args, 2); reach_type_t* t = reach_type(c->reach, type); args[0] = t->desc; args[1] = LLVMConstInt(c->intptr, len, false); args[2] = LLVMConstInt(c->intptr, len + 1, false); args[3] = str_ptr; LLVMValueRef inst = LLVMConstNamedStruct(t->structure, args, 4); LLVMValueRef g_inst = LLVMAddGlobal(c->module, t->structure, ""); LLVMSetInitializer(g_inst, inst); LLVMSetGlobalConstant(g_inst, true); LLVMSetLinkage(g_inst, LLVMPrivateLinkage); return g_inst; }
static ast_result_t sugar_ffi(ast_t* ast) { AST_GET_CHILDREN(ast, id, typeargs, args, named_args); const char* name = ast_name(id); size_t len = ast_name_len(id); // Check for \0 in ffi name (it may be a string literal) if(memchr(name, '\0', len) != NULL) { ast_error(ast, "FFI function names cannot include nul characters"); return AST_ERROR; } // Prefix '@' to the name char* new_name = (char*)pool_alloc_size(len + 2); new_name[0] = '@'; memcpy(new_name + 1, name, len); new_name[len + 1] = '\0'; ast_t* new_id = ast_from_string(id, stringtab_consume(new_name, len + 2)); ast_replace(&id, new_id); if(ast_id(ast) == TK_FFIDECL) return check_params(args); return AST_OK; }
LLVMValueRef gen_string(compile_t* c, ast_t* ast) { const char* name = ast_name(ast); genned_string_t k; k.string = name; size_t index = HASHMAP_UNKNOWN; genned_string_t* string = genned_strings_get(&c->strings, &k, &index); if(string != NULL) return string->global; ast_t* type = ast_type(ast); pony_assert(is_literal(type, "String")); reach_type_t* t = reach_type(c->reach, type); compile_type_t* c_t = (compile_type_t*)t->c_type; size_t len = ast_name_len(ast); LLVMValueRef args[4]; args[0] = c_t->desc; args[1] = LLVMConstInt(c->intptr, len, false); args[2] = LLVMConstInt(c->intptr, len + 1, false); args[3] = codegen_string(c, name, len); LLVMValueRef inst = LLVMConstNamedStruct(c_t->structure, args, 4); LLVMValueRef g_inst = LLVMAddGlobal(c->module, c_t->structure, ""); LLVMSetInitializer(g_inst, inst); LLVMSetGlobalConstant(g_inst, true); LLVMSetLinkage(g_inst, LLVMPrivateLinkage); LLVMSetUnnamedAddr(g_inst, true); string = POOL_ALLOC(genned_string_t); string->string = name; string->global = g_inst; genned_strings_putindex(&c->strings, string, index); return g_inst; }
// Compare the 2 given signatures to see if they are exactly the same static bool compare_signatures(ast_t* sig_a, ast_t* sig_b) { if(sig_a == NULL && sig_b == NULL) return true; if(sig_a == NULL || sig_b == NULL) return false; token_id a_id = ast_id(sig_a); if(a_id != ast_id(sig_b)) return false; switch(a_id) { case TK_BE: case TK_FUN: case TK_NEW: { // Check everything except body and docstring, ie first 6 children ast_t* a_child = ast_child(sig_a); ast_t* b_child = ast_child(sig_b); for(int i = 0; i < 6; i++) { if(a_child == NULL || b_child == NULL) return false; if(!compare_signatures(a_child, b_child)) return false; a_child = ast_sibling(a_child); b_child = ast_sibling(b_child); } return true; } case TK_STRING: case TK_ID: { // Can't just use strcmp, string literals may contain \0s size_t a_len = ast_name_len(sig_a); size_t b_len = ast_name_len(sig_b); if(a_len != b_len) return false; const char* a_text = ast_name(sig_a); const char* b_text = ast_name(sig_b); for(size_t i = 0; i < a_len; i++) { if(a_text[i] != b_text[i]) return false; } return true; } case TK_INT: return lexint_cmp(ast_int(sig_a), ast_int(sig_b)) == 0; case TK_FLOAT: return ast_float(sig_a) == ast_float(sig_b); case TK_NOMINAL: if(ast_data(sig_a) != ast_data(sig_b)) return false; break; default: break; } ast_t* a_child = ast_child(sig_a); ast_t* b_child = ast_child(sig_b); while(a_child != NULL && b_child != NULL) { if(!compare_signatures(a_child, b_child)) return false; a_child = ast_sibling(a_child); b_child = ast_sibling(b_child); } if(a_child != NULL || b_child != NULL) return false; return true; }