authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-14 17:04:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-14 17:04:35-07:00
log0c9afede9e6216aa59cd69dd9ed1ca544e24df30
treead59785a0c4c2d7d0a4c53cc48d5bf98a1498352
parent68c4f617edc2afd4f9b201b6b67248d6cb80e69d

overflow intrinsics take type as first argument


6 files changed, 182 insertions(+), 198 deletions(-)

src/all_types.hpp+7-1
......@@ -630,6 +630,9 @@ struct TypeTableEntryPointer {
630630
631631struct TypeTableEntryInt {
632632 bool is_signed;
633 LLVMValueRef add_with_overflow_fn;
634 LLVMValueRef sub_with_overflow_fn;
635 LLVMValueRef mul_with_overflow_fn;
633636};
634637
635638struct TypeTableEntryArray {
......@@ -791,7 +794,6 @@ struct FnTableEntry {
791794
792795enum BuiltinFnId {
793796 BuiltinFnIdInvalid,
794 BuiltinFnIdArithmeticWithOverflow,
795797 BuiltinFnIdMemcpy,
796798 BuiltinFnIdMemset,
797799 BuiltinFnIdSizeof,
......@@ -799,6 +801,9 @@ enum BuiltinFnId {
799801 BuiltinFnIdMinValue,
800802 BuiltinFnIdValueCount,
801803 BuiltinFnIdTypeof,
804 BuiltinFnIdAddWithOverflow,
805 BuiltinFnIdSubWithOverflow,
806 BuiltinFnIdMulWithOverflow,
802807};
803808
804809struct BuiltinFnEntry {
......@@ -831,6 +836,7 @@ struct CodeGen {
831836
832837 struct {
833838 TypeTableEntry *entry_bool;
839 TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]
834840 TypeTableEntry *entry_u8;
835841 TypeTableEntry *entry_u16;
836842 TypeTableEntry *entry_u32;
src/analyze.cpp+49-20
......@@ -155,18 +155,7 @@ static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x)
155155}
156156
157157static TypeTableEntry *get_int_type_unsigned(CodeGen *g, uint64_t x) {
158 switch (get_number_literal_kind_unsigned(x)) {
159 case NumLitU8:
160 return g->builtin_types.entry_u8;
161 case NumLitU16:
162 return g->builtin_types.entry_u16;
163 case NumLitU32:
164 return g->builtin_types.entry_u32;
165 case NumLitU64:
166 return g->builtin_types.entry_u64;
167 default:
168 zig_unreachable();
169 }
158 return get_int_type(g, false, num_lit_bit_count(get_number_literal_kind_unsigned(x)));
170159}
171160
172161static TypeTableEntry *get_meta_type(CodeGen *g, TypeTableEntry *child_type) {
......@@ -464,7 +453,9 @@ static void eval_const_expr_builtin(CodeGen *g, BlockContext *context, AstNode *
464453 switch (node->data.fn_call_expr.builtin_fn->id) {
465454 case BuiltinFnIdInvalid:
466455 zig_unreachable();
467 case BuiltinFnIdArithmeticWithOverflow:
456 case BuiltinFnIdAddWithOverflow:
457 case BuiltinFnIdSubWithOverflow:
458 case BuiltinFnIdMulWithOverflow:
468459 case BuiltinFnIdMemcpy:
469460 case BuiltinFnIdMemset:
470461 break;
......@@ -2476,18 +2467,36 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
24762467 add_node_error(g, node,
24772468 buf_sprintf("expected %d arguments, got %d",
24782469 builtin_fn->param_count, actual_param_count));
2470 return g->builtin_types.entry_invalid;
24792471 }
24802472
24812473 switch (builtin_fn->id) {
24822474 case BuiltinFnIdInvalid:
24832475 zig_unreachable();
2484 case BuiltinFnIdArithmeticWithOverflow:
2485 for (int i = 0; i < actual_param_count; i += 1) {
2486 AstNode *child = node->data.fn_call_expr.params.at(i);
2487 TypeTableEntry *expected_param_type = builtin_fn->param_types[i];
2488 analyze_expression(g, import, context, expected_param_type, child);
2476 case BuiltinFnIdAddWithOverflow:
2477 case BuiltinFnIdSubWithOverflow:
2478 case BuiltinFnIdMulWithOverflow:
2479 {
2480 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2481 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
2482 if (int_type->id == TypeTableEntryIdInvalid) {
2483 return g->builtin_types.entry_bool;
2484 } else if (int_type->id == TypeTableEntryIdInt) {
2485 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
2486 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
2487 AstNode *result_node = node->data.fn_call_expr.params.at(3);
2488
2489 analyze_expression(g, import, context, int_type, op1_node);
2490 analyze_expression(g, import, context, int_type, op2_node);
2491 analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
2492 result_node);
2493 } else {
2494 add_node_error(g, type_node,
2495 buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
2496 }
2497
2498 return g->builtin_types.entry_bool;
24892499 }
2490 return builtin_fn->return_type;
24912500 case BuiltinFnIdMemcpy:
24922501 {
24932502 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
......@@ -2796,7 +2805,8 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
27962805 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {
27972806 return expr_type;
27982807 } else {
2799 add_node_error(g, operand_node, buf_sprintf("invalid negation type: '%s'",
2808 BREAKPOINT;
2809 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",
28002810 buf_ptr(&expr_type->name)));
28012811 return g->builtin_types.entry_invalid;
28022812 }
......@@ -3842,3 +3852,22 @@ bool is_node_void_expr(AstNode *node) {
38423852 return false;
38433853}
38443854
3855TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits) {
3856 int index;
3857 if (size_in_bits == 8) {
3858 index = 0;
3859 } else if (size_in_bits == 16) {
3860 index = 1;
3861 } else if (size_in_bits == 32) {
3862 index = 2;
3863 } else if (size_in_bits == 64) {
3864 index = 3;
3865 } else {
3866 zig_unreachable();
3867 }
3868 return &g->builtin_types.entry_int[is_signed ? 0 : 1][index];
3869}
3870
3871TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {
3872 return *get_int_type_ptr(g, is_signed, size_in_bits);
3873}
src/analyze.hpp+2
......@@ -21,5 +21,7 @@ Expr *get_resolved_expr(AstNode *node);
2121NumLitCodeGen *get_resolved_num_lit(AstNode *node);
2222TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
2323bool is_node_void_expr(AstNode *node);
24TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
25TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
2426
2527#endif
src/codegen.cpp+120-173
......@@ -184,14 +184,28 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
184184 case BuiltinFnIdInvalid:
185185 case BuiltinFnIdTypeof:
186186 zig_unreachable();
187 case BuiltinFnIdArithmeticWithOverflow:
187 case BuiltinFnIdAddWithOverflow:
188 case BuiltinFnIdSubWithOverflow:
189 case BuiltinFnIdMulWithOverflow:
188190 {
189191 int fn_call_param_count = node->data.fn_call_expr.params.length;
190 assert(fn_call_param_count == 3);
192 assert(fn_call_param_count == 4);
193
194 TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
195 LLVMValueRef fn_val;
196 if (builtin_fn->id == BuiltinFnIdAddWithOverflow) {
197 fn_val = int_type->data.integral.add_with_overflow_fn;
198 } else if (builtin_fn->id == BuiltinFnIdSubWithOverflow) {
199 fn_val = int_type->data.integral.sub_with_overflow_fn;
200 } else if (builtin_fn->id == BuiltinFnIdMulWithOverflow) {
201 fn_val = int_type->data.integral.mul_with_overflow_fn;
202 } else {
203 zig_unreachable();
204 }
191205
192 LLVMValueRef op1 = gen_expr(g, node->data.fn_call_expr.params.at(0));
193 LLVMValueRef op2 = gen_expr(g, node->data.fn_call_expr.params.at(1));
194 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(2));
206 LLVMValueRef op1 = gen_expr(g, node->data.fn_call_expr.params.at(1));
207 LLVMValueRef op2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
208 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
195209
196210 LLVMValueRef params[] = {
197211 op1,
......@@ -199,7 +213,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
199213 };
200214
201215 add_debug_source_node(g, node);
202 LLVMValueRef result_struct = LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 2, "");
216 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
203217 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
204218 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
205219 LLVMBuildStore(g->builder, result, ptr_result);
......@@ -2184,6 +2198,35 @@ static void do_code_gen(CodeGen *g) {
21842198#endif
21852199}
21862200
2201static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
2202 const char *signed_name, const char *unsigned_name)
2203{
2204 const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name;
2205 Buf *llvm_name = buf_sprintf("llvm.%s.with.overflow.i%" PRIu64, signed_str, type_entry->size_in_bits);
2206
2207 LLVMTypeRef return_elem_types[] = {
2208 type_entry->type_ref,
2209 LLVMInt1Type(),
2210 };
2211 LLVMTypeRef param_types[] = {
2212 type_entry->type_ref,
2213 type_entry->type_ref,
2214 };
2215 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
2216 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
2217 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
2218 assert(LLVMGetIntrinsicID(fn_val));
2219 return fn_val;
2220}
2221
2222static void add_int_overflow_fns(CodeGen *g, TypeTableEntry *type_entry) {
2223 assert(type_entry->id == TypeTableEntryIdInt);
2224
2225 type_entry->data.integral.add_with_overflow_fn = get_arithmetic_overflow_fn(g, type_entry, "sadd", "uadd");
2226 type_entry->data.integral.sub_with_overflow_fn = get_arithmetic_overflow_fn(g, type_entry, "ssub", "usub");
2227 type_entry->data.integral.mul_with_overflow_fn = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul");
2228}
2229
21872230static const NumLit num_lit_kinds[] = {
21882231 NumLitF32,
21892232 NumLitF64,
......@@ -2198,6 +2241,13 @@ static const NumLit num_lit_kinds[] = {
21982241 NumLitI64,
21992242};
22002243
2244static const int int_sizes_in_bits[] = {
2245 8,
2246 16,
2247 32,
2248 64,
2249};
2250
22012251static void define_builtin_types(CodeGen *g) {
22022252 {
22032253 // if this type is anywhere in the AST, we should never hit codegen.
......@@ -2219,6 +2269,37 @@ static void define_builtin_types(CodeGen *g) {
22192269 g->num_lit_types[i] = entry;
22202270 }
22212271
2272 for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {
2273 int size_in_bits = int_sizes_in_bits[i];
2274 bool is_signed = true;
2275 for (;;) {
2276 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2277 entry->type_ref = LLVMIntType(size_in_bits);
2278
2279 const char u_or_i = is_signed ? 'i' : 'u';
2280 buf_resize(&entry->name, 0);
2281 buf_appendf(&entry->name, "%c%d", u_or_i, size_in_bits);
2282
2283 entry->size_in_bits = size_in_bits;
2284 entry->align_in_bits = size_in_bits;
2285 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2286 entry->size_in_bits, entry->align_in_bits,
2287 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
2288 entry->data.integral.is_signed = is_signed;
2289 g->primitive_type_table.put(&entry->name, entry);
2290
2291 get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;
2292
2293 add_int_overflow_fns(g, entry);
2294
2295 if (!is_signed) {
2296 break;
2297 } else {
2298 is_signed = false;
2299 }
2300 }
2301 }
2302
22222303 {
22232304 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool);
22242305 entry->type_ref = LLVMInt1Type();
......@@ -2231,110 +2312,6 @@ static void define_builtin_types(CodeGen *g) {
22312312 g->builtin_types.entry_bool = entry;
22322313 g->primitive_type_table.put(&entry->name, entry);
22332314 }
2234 {
2235 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2236 entry->type_ref = LLVMInt8Type();
2237 buf_init_from_str(&entry->name, "u8");
2238 entry->size_in_bits = 8;
2239 entry->align_in_bits = 8;
2240 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2241 entry->size_in_bits, entry->align_in_bits,
2242 LLVMZigEncoding_DW_ATE_unsigned());
2243 g->builtin_types.entry_u8 = entry;
2244 g->primitive_type_table.put(&entry->name, entry);
2245 }
2246 {
2247 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2248 entry->type_ref = LLVMInt16Type();
2249 buf_init_from_str(&entry->name, "u16");
2250 entry->size_in_bits = 16;
2251 entry->align_in_bits = 16;
2252 entry->data.integral.is_signed = false;
2253 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2254 entry->size_in_bits, entry->align_in_bits,
2255 LLVMZigEncoding_DW_ATE_unsigned());
2256 g->builtin_types.entry_u16 = entry;
2257 g->primitive_type_table.put(&entry->name, entry);
2258 }
2259 {
2260 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2261 entry->type_ref = LLVMInt32Type();
2262 buf_init_from_str(&entry->name, "u32");
2263 entry->size_in_bits = 32;
2264 entry->align_in_bits = 32;
2265 entry->data.integral.is_signed = false;
2266 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2267 entry->size_in_bits, entry->align_in_bits,
2268 LLVMZigEncoding_DW_ATE_unsigned());
2269 g->builtin_types.entry_u32 = entry;
2270 g->primitive_type_table.put(&entry->name, entry);
2271 }
2272 {
2273 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2274 entry->type_ref = LLVMInt64Type();
2275 buf_init_from_str(&entry->name, "u64");
2276 entry->size_in_bits = 64;
2277 entry->align_in_bits = 64;
2278 entry->data.integral.is_signed = false;
2279 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2280 entry->size_in_bits, entry->align_in_bits,
2281 LLVMZigEncoding_DW_ATE_unsigned());
2282 g->builtin_types.entry_u64 = entry;
2283 g->primitive_type_table.put(&entry->name, entry);
2284 }
2285 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
2286 {
2287 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2288 entry->type_ref = LLVMInt8Type();
2289 buf_init_from_str(&entry->name, "i8");
2290 entry->size_in_bits = 8;
2291 entry->align_in_bits = 8;
2292 entry->data.integral.is_signed = true;
2293 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2294 entry->size_in_bits, entry->align_in_bits,
2295 LLVMZigEncoding_DW_ATE_signed());
2296 g->builtin_types.entry_i8 = entry;
2297 g->primitive_type_table.put(&entry->name, entry);
2298 }
2299 {
2300 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2301 entry->type_ref = LLVMInt16Type();
2302 buf_init_from_str(&entry->name, "i16");
2303 entry->size_in_bits = 16;
2304 entry->align_in_bits = 16;
2305 entry->data.integral.is_signed = true;
2306 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2307 entry->size_in_bits, entry->align_in_bits,
2308 LLVMZigEncoding_DW_ATE_signed());
2309 g->builtin_types.entry_i16 = entry;
2310 g->primitive_type_table.put(&entry->name, entry);
2311 }
2312 {
2313 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2314 entry->type_ref = LLVMInt32Type();
2315 buf_init_from_str(&entry->name, "i32");
2316 entry->size_in_bits = 32;
2317 entry->align_in_bits = 32;
2318 entry->data.integral.is_signed = true;
2319 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2320 entry->size_in_bits, entry->align_in_bits,
2321 LLVMZigEncoding_DW_ATE_signed());
2322 g->builtin_types.entry_i32 = entry;
2323 g->primitive_type_table.put(&entry->name, entry);
2324 }
2325 {
2326 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2327 entry->type_ref = LLVMInt64Type();
2328 buf_init_from_str(&entry->name, "i64");
2329 entry->size_in_bits = 64;
2330 entry->align_in_bits = 64;
2331 entry->data.integral.is_signed = true;
2332 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
2333 entry->size_in_bits, entry->align_in_bits,
2334 LLVMZigEncoding_DW_ATE_signed());
2335 g->builtin_types.entry_i64 = entry;
2336 g->primitive_type_table.put(&entry->name, entry);
2337 }
23382315 {
23392316 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
23402317 entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
......@@ -2342,6 +2319,12 @@ static void define_builtin_types(CodeGen *g) {
23422319 entry->size_in_bits = g->pointer_size_bytes * 8;
23432320 entry->align_in_bits = g->pointer_size_bytes * 8;
23442321 entry->data.integral.is_signed = true;
2322
2323 TypeTableEntry *fixed_width_entry = get_int_type(g, entry->data.integral.is_signed, entry->size_in_bits);
2324 entry->data.integral.add_with_overflow_fn = fixed_width_entry->data.integral.add_with_overflow_fn;
2325 entry->data.integral.sub_with_overflow_fn = fixed_width_entry->data.integral.sub_with_overflow_fn;
2326 entry->data.integral.mul_with_overflow_fn = fixed_width_entry->data.integral.mul_with_overflow_fn;
2327
23452328 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
23462329 entry->size_in_bits, entry->align_in_bits,
23472330 LLVMZigEncoding_DW_ATE_signed());
......@@ -2355,6 +2338,12 @@ static void define_builtin_types(CodeGen *g) {
23552338 entry->size_in_bits = g->pointer_size_bytes * 8;
23562339 entry->align_in_bits = g->pointer_size_bytes * 8;
23572340 entry->data.integral.is_signed = false;
2341
2342 TypeTableEntry *fixed_width_entry = get_int_type(g, entry->data.integral.is_signed, entry->size_in_bits);
2343 entry->data.integral.add_with_overflow_fn = fixed_width_entry->data.integral.add_with_overflow_fn;
2344 entry->data.integral.sub_with_overflow_fn = fixed_width_entry->data.integral.sub_with_overflow_fn;
2345 entry->data.integral.mul_with_overflow_fn = fixed_width_entry->data.integral.mul_with_overflow_fn;
2346
23582347 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
23592348 entry->size_in_bits, entry->align_in_bits,
23602349 LLVMZigEncoding_DW_ATE_unsigned());
......@@ -2403,55 +2392,20 @@ static void define_builtin_types(CodeGen *g) {
24032392 g->builtin_types.entry_unreachable = entry;
24042393 g->primitive_type_table.put(&entry->name, entry);
24052394 }
2406}
2407
2408static void define_builtin_fns_int(CodeGen *g, TypeTableEntry *type_entry) {
2409 assert(type_entry->id == TypeTableEntryIdInt);
2410 struct OverflowFn {
2411 const char *bare_name;
2412 const char *signed_name;
2413 const char *unsigned_name;
2414 };
2415 OverflowFn overflow_fns[] = {
2416 {"add", "sadd", "uadd"},
2417 {"sub", "ssub", "usub"},
2418 {"mul", "smul", "umul"},
2419 };
2420 for (size_t i = 0; i < sizeof(overflow_fns)/sizeof(overflow_fns[0]); i += 1) {
2421 OverflowFn *overflow_fn = &overflow_fns[i];
2422 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
2423 buf_resize(&builtin_fn->name, 0);
2424 buf_appendf(&builtin_fn->name, "%s_with_overflow_%s", overflow_fn->bare_name, buf_ptr(&type_entry->name));
2425 builtin_fn->id = BuiltinFnIdArithmeticWithOverflow;
2426 builtin_fn->return_type = g->builtin_types.entry_bool;
2427 builtin_fn->param_count = 3;
2428 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
2429 builtin_fn->param_types[0] = type_entry;
2430 builtin_fn->param_types[1] = type_entry;
2431 builtin_fn->param_types[2] = get_pointer_to_type(g, type_entry, false);
24322395
2396 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, get_int_type(g, false, 8), true);
24332397
2434 const char *signed_str = type_entry->data.integral.is_signed ?
2435 overflow_fn->signed_name : overflow_fn->unsigned_name;
2436 Buf *llvm_name = buf_sprintf("llvm.%s.with.overflow.i%" PRIu64, signed_str, type_entry->size_in_bits);
2437
2438 LLVMTypeRef return_elem_types[] = {
2439 type_entry->type_ref,
2440 LLVMInt1Type(),
2441 };
2442 LLVMTypeRef param_types[] = {
2443 type_entry->type_ref,
2444 type_entry->type_ref,
2445 };
2446 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
2447 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
2448 builtin_fn->fn_val = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
2449 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
2450
2451 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
2452 }
2398 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
2399 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
2400 g->builtin_types.entry_u32 = get_int_type(g, false, 32);
2401 g->builtin_types.entry_u64 = get_int_type(g, false, 64);
2402 g->builtin_types.entry_i8 = get_int_type(g, true, 8);
2403 g->builtin_types.entry_i16 = get_int_type(g, true, 16);
2404 g->builtin_types.entry_i32 = get_int_type(g, true, 32);
2405 g->builtin_types.entry_i64 = get_int_type(g, true, 64);
24532406}
24542407
2408
24552409static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name) {
24562410 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
24572411 buf_init_from_str(&builtin_fn->name, name);
......@@ -2460,24 +2414,14 @@ static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char
24602414 return builtin_fn;
24612415}
24622416
2463static BuiltinFnEntry *create_one_arg_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name) {
2417static BuiltinFnEntry *create_builtin_fn_with_arg_count(CodeGen *g, BuiltinFnId id, const char *name, int count) {
24642418 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, id, name);
2465 builtin_fn->return_type = nullptr; // manually determined later
2466 builtin_fn->param_count = 1;
2467 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
2468 builtin_fn->param_types[0] = nullptr; // manually checked later
2419 builtin_fn->param_count = count;
2420 builtin_fn->param_types = allocate<TypeTableEntry *>(count);
24692421 return builtin_fn;
24702422}
24712423
24722424static void define_builtin_fns(CodeGen *g) {
2473 define_builtin_fns_int(g, g->builtin_types.entry_u8);
2474 define_builtin_fns_int(g, g->builtin_types.entry_u16);
2475 define_builtin_fns_int(g, g->builtin_types.entry_u32);
2476 define_builtin_fns_int(g, g->builtin_types.entry_u64);
2477 define_builtin_fns_int(g, g->builtin_types.entry_i8);
2478 define_builtin_fns_int(g, g->builtin_types.entry_i16);
2479 define_builtin_fns_int(g, g->builtin_types.entry_i32);
2480 define_builtin_fns_int(g, g->builtin_types.entry_i64);
24812425 {
24822426 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
24832427 builtin_fn->return_type = g->builtin_types.entry_void;
......@@ -2524,11 +2468,14 @@ static void define_builtin_fns(CodeGen *g) {
25242468
25252469 g->memset_fn_val = builtin_fn->fn_val;
25262470 }
2527 create_one_arg_builtin_fn(g, BuiltinFnIdSizeof, "sizeof");
2528 create_one_arg_builtin_fn(g, BuiltinFnIdMaxValue, "max_value");
2529 create_one_arg_builtin_fn(g, BuiltinFnIdMinValue, "min_value");
2530 create_one_arg_builtin_fn(g, BuiltinFnIdValueCount, "value_count");
2531 create_one_arg_builtin_fn(g, BuiltinFnIdTypeof, "typeof");
2471 create_builtin_fn_with_arg_count(g, BuiltinFnIdSizeof, "sizeof", 1);
2472 create_builtin_fn_with_arg_count(g, BuiltinFnIdMaxValue, "max_value", 1);
2473 create_builtin_fn_with_arg_count(g, BuiltinFnIdMinValue, "min_value", 1);
2474 create_builtin_fn_with_arg_count(g, BuiltinFnIdValueCount, "value_count", 1);
2475 create_builtin_fn_with_arg_count(g, BuiltinFnIdTypeof, "typeof", 1);
2476 create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4);
2477 create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4);
2478 create_builtin_fn_with_arg_count(g, BuiltinFnIdMulWithOverflow, "mul_with_overflow", 4);
25322479}
25332480
25342481
std/std.zig+2-2
......@@ -61,12 +61,12 @@ pub fn parse_u64(buf: []u8, radix: u8, result: &u64) bool => {
6161 }
6262
6363 // x *= radix
64 if (@mul_with_overflow_u64(x, radix, &x)) {
64 if (@mul_with_overflow(u64, x, radix, &x)) {
6565 return true;
6666 }
6767
6868 // x += digit
69 if (@add_with_overflow_u64(x, digit, &x)) {
69 if (@add_with_overflow(u64, x, digit, &x)) {
7070 return true;
7171 }
7272
test/run_tests.cpp+2-2
......@@ -986,10 +986,10 @@ fn f(c: u8) u8 => {
986986use "std.zig";
987987pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
988988 var result: u8;
989 if (!@add_with_overflow_u8(250, 100, &result)) {
989 if (!@add_with_overflow(u8, 250, 100, &result)) {
990990 print_str("BAD\n");
991991 }
992 if (@add_with_overflow_u8(100, 150, &result)) {
992 if (@add_with_overflow(u8, 100, 150, &result)) {
993993 print_str("BAD\n");
994994 }
995995 if (result != 250) {