LLVMValueRef gen_int(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); gentype_t g; if(!gentype(c, type, &g)) return NULL; __uint128_t value = ast_int(ast); uint64_t low, high; #if !defined(HAVE_STRUCT_INT128) low = (uint64_t)value; high = (uint64_t)(value >> 64); #else low = value.low; high = value.high; #endif LLVMValueRef vlow = LLVMConstInt(c->i128, low, false); LLVMValueRef vhigh = LLVMConstInt(c->i128, high, false); LLVMValueRef shift = LLVMConstInt(c->i128, 64, false); vhigh = LLVMConstShl(vhigh, shift); vhigh = LLVMConstAdd(vhigh, vlow); if(g.primitive == c->i128) return vhigh; if((g.primitive == c->f32) || (g.primitive == c->f64)) return LLVMConstUIToFP(vhigh, g.primitive); return LLVMConstTrunc(vhigh, g.primitive); }
static bool tuple_access(ast_t* ast) { // Left is a postfix expression, right is a lookup name. ast_t* left = ast_child(ast); ast_t* right = ast_sibling(left); ast_t* type = ast_type(left); if(is_typecheck_error(type)) return false; // Change the lookup name to an integer index. if(!make_tuple_index(&right)) { ast_error(right, "lookup on a tuple must take the form _X, where X is an integer"); return false; } // Make sure our index is in bounds. type = ast_childidx(type, (size_t)ast_int(right)); if(type == NULL) { ast_error(right, "tuple index is out of bounds"); return false; } ast_setid(ast, TK_FLETREF); ast_settype(ast, type); ast_inheritflags(ast); return true; }
static LLVMValueRef make_tupleelemptr(compile_t* c, LLVMValueRef l_value, ast_t* l_type, ast_t* right) { pony_assert(ast_id(l_type) == TK_TUPLETYPE); int index = (int)ast_int(right)->low; return LLVMBuildExtractValue(c->builder, l_value, index, ""); }
static bool tuple_access(pass_opt_t* opt, ast_t* ast) { // Left is a postfix expression, right is a lookup name. ast_t* left = ast_child(ast); ast_t* right = ast_sibling(left); ast_t* type = ast_type(left); if(is_typecheck_error(type)) return false; // Change the lookup name to an integer index. if(!make_tuple_index(&right)) { ast_error(opt->check.errors, right, "lookup on a tuple must take the form _X, where X is an integer"); return false; } // Make sure our index is in bounds. make_tuple_index automatically shifts // from one indexed to zero, so we have to use -1 and >= for our comparisons. size_t right_idx = (size_t)ast_int(right)->low; size_t tuple_size = ast_childcount(type); if (right_idx == (size_t)-1) { ast_error(opt->check.errors, right, "tuples are one indexed not zero indexed. Did you mean _1?"); return false; } else if (right_idx >= tuple_size) { ast_error(opt->check.errors, right, "tuple index " __zu " is out of " "valid range. Valid range is [1, " __zu "]", right_idx, tuple_size); return false; } type = ast_childidx(type, right_idx); assert(type != NULL); ast_setid(ast, TK_FLETREF); ast_settype(ast, type); ast_inheritflags(ast); return true; }
LLVMValueRef gen_int(compile_t* c, ast_t* ast) { ast_t* type = ast_type(ast); reach_type_t* t = reach_type(c->reach, type); lexint_t* value = ast_int(ast); LLVMValueRef vlow = LLVMConstInt(c->i128, value->low, false); LLVMValueRef vhigh = LLVMConstInt(c->i128, value->high, false); LLVMValueRef shift = LLVMConstInt(c->i128, 64, false); vhigh = LLVMConstShl(vhigh, shift); vhigh = LLVMConstAdd(vhigh, vlow); if(t->primitive == c->i128) return vhigh; if((t->primitive == c->f32) || (t->primitive == c->f64)) return LLVMConstUIToFP(vhigh, t->primitive); return LLVMConstTrunc(vhigh, t->primitive); }
LLVMValueRef gen_int(compile_t* c, ast_t* ast) { ast_t* type = deferred_reify(c->frame->reify, ast_type(ast), 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; lexint_t* value = ast_int(ast); LLVMValueRef vlow = LLVMConstInt(c->i128, value->low, false); LLVMValueRef vhigh = LLVMConstInt(c->i128, value->high, false); LLVMValueRef shift = LLVMConstInt(c->i128, 64, false); vhigh = LLVMConstShl(vhigh, shift); vhigh = LLVMConstAdd(vhigh, vlow); if(c_t->primitive == c->i128) return vhigh; if((c_t->primitive == c->f32) || (c_t->primitive == c->f64)) return LLVMConstUIToFP(vhigh, c_t->primitive); return LLVMConstTrunc(vhigh, c_t->primitive); }
static LLVMValueRef make_fieldptr(compile_t* c, LLVMValueRef l_value, ast_t* l_type, ast_t* right) { switch(ast_id(l_type)) { case TK_NOMINAL: { assert(ast_id(right) == TK_ID); ast_t* def = (ast_t*)ast_data(l_type); ast_t* field = ast_get(def, ast_name(right), NULL); int index = (int)ast_index(field); if(ast_id(def) != TK_STRUCT) index++; if(ast_id(def) == TK_ACTOR) index++; return LLVMBuildStructGEP(c->builder, l_value, index, ""); } case TK_TUPLETYPE: { assert(ast_id(right) == TK_INT); int index = (int)ast_int(right)->low; return LLVMBuildExtractValue(c->builder, l_value, index, ""); } case TK_ARROW: return make_fieldptr(c, l_value, ast_childidx(l_type, 1), right); default: {} } assert(0); return NULL; }
// Assign a UIF type from the given target type to the given AST static bool uif_type_from_chain(pass_opt_t* opt, ast_t* literal, ast_t* target_type, lit_chain_t* chain, bool require_float, bool report_errors) { assert(literal != NULL); assert(chain != NULL); lit_chain_t* chain_head = chain; while(chain_head->cardinality != CHAIN_CARD_BASE) chain_head = chain_head->next; if(chain_head->cached_type == NULL) { // This is the first time we've needed this type, find it if(!uif_type(opt, literal, target_type, chain_head, report_errors)) return false; } if(require_float && !chain_head->valid_for_float) { if(report_errors) ast_error(literal, "Inferred possibly integer type %s for float literal", chain_head->name); return false; } if(ast_id(literal) == TK_INT && chain_head->cached_uif_index >= 0) { // Check for literals that are outside the range of their type. // Note we don't check for types bound to type parameters. int i = chain_head->cached_uif_index; if(_str_uif_types[i].limit_low != 0 || _str_uif_types[i].limit_high != 0) { #ifdef PLATFORM_IS_VISUAL_STUDIO UnsignedInt128 limit(_str_uif_types[i].limit_high, _str_uif_types[i].limit_low); #else __uint128_t limit = (((__uint128_t)_str_uif_types[i].limit_high) << 64) | _str_uif_types[i].limit_low; #endif // There is a limit specified for this type, the literal must be smaller // than that. bool neg_plus_one = false; if(_str_uif_types[i].neg_plus_one) { // If the literal is immediately negated it can be equal to the given // limit. This is because of how the world chooses to encode negative // integers. // For example, the maximum value in an I8 is 127. But the minimum // value is -128. // We don't actually calculate the negative value here, but we have a // looser test if the literal is immediately negated. // We do not do this if the negation is not immediate, eg "-(128)". ast_t* parent = ast_parent(literal); assert(parent != NULL); ast_t* parent_type = ast_type(parent); if(parent_type != NULL && ast_id(parent_type) == TK_OPERATORLITERAL && ast_child(parent) == literal && ((lit_op_info_t*)ast_data(parent_type))->neg_plus_one) neg_plus_one = true; } __uint128_t actual = ast_int(literal); if((actual > limit) || (!neg_plus_one && actual == limit)) { // Illegal value. Note that we report an error, but don't return an // error, so other errors may be found. ast_error(literal, "Literal value is out of range for type (%s)", chain_head->name); } } } ast_settype(literal, chain_head->cached_type); return true; }
// 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; }