authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-19 00:08:47-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-19 00:08:47-04:00
log1d85b588eab27830409a62e88bd8444db58787a4
treee997fbe7cad2c8c2548a9568b6c59c558ef095a7
parent7f1a550760a7a01d4ae8de51be16fb02d56b5cd2

self-hosted: progress on IR for supporting libc hello world

* add c int types * some more ir stubs

10 files changed, 879 insertions(+), 43 deletions(-)

CMakeLists.txt+1
......@@ -489,6 +489,7 @@ set(ZIG_STD_FILES
489489 "math/atan.zig"
490490 "math/atan2.zig"
491491 "math/atanh.zig"
492 "math/big/index.zig"
492493 "math/big/int.zig"
493494 "math/cbrt.zig"
494495 "math/ceil.zig"
src-self-hosted/c_int.zig created+68
......@@ -0,0 +1,68 @@
1pub const CInt = struct {
2 id: Id,
3 zig_name: []const u8,
4 c_name: []const u8,
5 is_signed: bool,
6
7 pub const Id = enum {
8 Short,
9 UShort,
10 Int,
11 UInt,
12 Long,
13 ULong,
14 LongLong,
15 ULongLong,
16 };
17
18 pub const list = []CInt{
19 CInt{
20 .id = Id.Short,
21 .zig_name = "c_short",
22 .c_name = "short",
23 .is_signed = true,
24 },
25 CInt{
26 .id = Id.UShort,
27 .zig_name = "c_ushort",
28 .c_name = "unsigned short",
29 .is_signed = false,
30 },
31 CInt{
32 .id = Id.Int,
33 .zig_name = "c_int",
34 .c_name = "int",
35 .is_signed = true,
36 },
37 CInt{
38 .id = Id.UInt,
39 .zig_name = "c_uint",
40 .c_name = "unsigned int",
41 .is_signed = false,
42 },
43 CInt{
44 .id = Id.Long,
45 .zig_name = "c_long",
46 .c_name = "long",
47 .is_signed = true,
48 },
49 CInt{
50 .id = Id.ULong,
51 .zig_name = "c_ulong",
52 .c_name = "unsigned long",
53 .is_signed = false,
54 },
55 CInt{
56 .id = Id.LongLong,
57 .zig_name = "c_longlong",
58 .c_name = "long long",
59 .is_signed = true,
60 },
61 CInt{
62 .id = Id.ULongLong,
63 .zig_name = "c_ulonglong",
64 .c_name = "unsigned long long",
65 .is_signed = false,
66 },
67 };
68};
src-self-hosted/compilation.zig+78-29
......@@ -29,6 +29,7 @@ const codegen = @import("codegen.zig");
2929const Package = @import("package.zig").Package;
3030const link = @import("link.zig").link;
3131const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
32const CInt = @import("c_int.zig").CInt;
3233
3334/// Data that is local to the event loop.
3435pub const EventLoopLocal = struct {
......@@ -59,6 +60,7 @@ pub const EventLoopLocal = struct {
5960 };
6061 }
6162
63 /// Must be called only after EventLoop.run completes.
6264 fn deinit(self: *EventLoopLocal) void {
6365 while (self.llvm_handle_pool.pop()) |node| {
6466 c.LLVMContextDispose(node.data);
......@@ -184,6 +186,7 @@ pub const Compilation = struct {
184186 void_type: *Type.Void,
185187 bool_type: *Type.Bool,
186188 noreturn_type: *Type.NoReturn,
189 comptime_int_type: *Type.ComptimeInt,
187190
188191 void_value: *Value.Void,
189192 true_value: *Value.Bool,
......@@ -209,6 +212,16 @@ pub const Compilation = struct {
209212
210213 have_err_ret_tracing: bool,
211214
215 /// not locked because it is read-only
216 primitive_type_table: TypeTable,
217
218 int_type_table: event.Locked(IntTypeTable),
219
220 c_int_types: [CInt.list.len]*Type.Int,
221
222 const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);
223 const TypeTable = std.HashMap([]const u8, *Type, mem.hash_slice_u8, mem.eql_slice_u8);
224
212225 const CompileErrList = std.ArrayList(*errmsg.Msg);
213226
214227 // TODO handle some of these earlier and report them in a way other than error codes
......@@ -362,6 +375,8 @@ pub const Compilation = struct {
362375 .prelink_group = event.Group(BuildError!void).init(loop),
363376 .deinit_group = event.Group(void).init(loop),
364377 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
378 .int_type_table = event.Locked(IntTypeTable).init(loop, IntTypeTable.init(loop.allocator)),
379 .c_int_types = undefined,
365380
366381 .meta_type = undefined,
367382 .void_type = undefined,
......@@ -371,6 +386,7 @@ pub const Compilation = struct {
371386 .false_value = undefined,
372387 .noreturn_type = undefined,
373388 .noreturn_value = undefined,
389 .comptime_int_type = undefined,
374390
375391 .target_machine = undefined,
376392 .target_data_ref = undefined,
......@@ -382,8 +398,10 @@ pub const Compilation = struct {
382398 .override_libc = null,
383399 .destroy_handle = undefined,
384400 .have_err_ret_tracing = false,
401 .primitive_type_table = undefined,
385402 });
386403 errdefer {
404 comp.int_type_table.private_data.deinit();
387405 comp.arena_allocator.deinit();
388406 comp.loop.allocator.destroy(comp);
389407 }
......@@ -393,6 +411,7 @@ pub const Compilation = struct {
393411 comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);
394412 comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());
395413 comp.zig_std_dir = try std.os.path.join(comp.arena(), zig_lib_dir, "std");
414 comp.primitive_type_table = TypeTable.init(comp.arena());
396415
397416 const opt_level = switch (build_mode) {
398417 builtin.Mode.Debug => llvm.CodeGenLevelNone,
......@@ -445,7 +464,6 @@ pub const Compilation = struct {
445464 }
446465
447466 try comp.initTypes();
448 errdefer comp.derefTypes();
449467
450468 comp.destroy_handle = try async<loop.allocator> comp.internalDeinit();
451469
......@@ -453,8 +471,9 @@ pub const Compilation = struct {
453471 }
454472
455473 fn initTypes(comp: *Compilation) !void {
456 comp.meta_type = try comp.gpa().create(Type.MetaType{
474 comp.meta_type = try comp.arena().create(Type.MetaType{
457475 .base = Type{
476 .name = "type",
458477 .base = Value{
459478 .id = Value.Id.Type,
460479 .typeof = undefined,
......@@ -466,10 +485,11 @@ pub const Compilation = struct {
466485 });
467486 comp.meta_type.value = &comp.meta_type.base;
468487 comp.meta_type.base.base.typeof = &comp.meta_type.base;
469 errdefer comp.gpa().destroy(comp.meta_type);
488 assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null);
470489
471 comp.void_type = try comp.gpa().create(Type.Void{
490 comp.void_type = try comp.arena().create(Type.Void{
472491 .base = Type{
492 .name = "void",
473493 .base = Value{
474494 .id = Value.Id.Type,
475495 .typeof = &Type.MetaType.get(comp).base,
......@@ -478,10 +498,11 @@ pub const Compilation = struct {
478498 .id = builtin.TypeId.Void,
479499 },
480500 });
481 errdefer comp.gpa().destroy(comp.void_type);
501 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);
482502
483 comp.noreturn_type = try comp.gpa().create(Type.NoReturn{
503 comp.noreturn_type = try comp.arena().create(Type.NoReturn{
484504 .base = Type{
505 .name = "noreturn",
485506 .base = Value{
486507 .id = Value.Id.Type,
487508 .typeof = &Type.MetaType.get(comp).base,
......@@ -490,10 +511,24 @@ pub const Compilation = struct {
490511 .id = builtin.TypeId.NoReturn,
491512 },
492513 });
493 errdefer comp.gpa().destroy(comp.noreturn_type);
514 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);
494515
495 comp.bool_type = try comp.gpa().create(Type.Bool{
516 comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt{
496517 .base = Type{
518 .name = "comptime_int",
519 .base = Value{
520 .id = Value.Id.Type,
521 .typeof = &Type.MetaType.get(comp).base,
522 .ref_count = std.atomic.Int(usize).init(1),
523 },
524 .id = builtin.TypeId.ComptimeInt,
525 },
526 });
527 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);
528
529 comp.bool_type = try comp.arena().create(Type.Bool{
530 .base = Type{
531 .name = "bool",
497532 .base = Value{
498533 .id = Value.Id.Type,
499534 .typeof = &Type.MetaType.get(comp).base,
......@@ -502,18 +537,17 @@ pub const Compilation = struct {
502537 .id = builtin.TypeId.Bool,
503538 },
504539 });
505 errdefer comp.gpa().destroy(comp.bool_type);
540 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);
506541
507 comp.void_value = try comp.gpa().create(Value.Void{
542 comp.void_value = try comp.arena().create(Value.Void{
508543 .base = Value{
509544 .id = Value.Id.Void,
510545 .typeof = &Type.Void.get(comp).base,
511546 .ref_count = std.atomic.Int(usize).init(1),
512547 },
513548 });
514 errdefer comp.gpa().destroy(comp.void_value);
515549
516 comp.true_value = try comp.gpa().create(Value.Bool{
550 comp.true_value = try comp.arena().create(Value.Bool{
517551 .base = Value{
518552 .id = Value.Id.Bool,
519553 .typeof = &Type.Bool.get(comp).base,
......@@ -521,9 +555,8 @@ pub const Compilation = struct {
521555 },
522556 .x = true,
523557 });
524 errdefer comp.gpa().destroy(comp.true_value);
525558
526 comp.false_value = try comp.gpa().create(Value.Bool{
559 comp.false_value = try comp.arena().create(Value.Bool{
527560 .base = Value{
528561 .id = Value.Id.Bool,
529562 .typeof = &Type.Bool.get(comp).base,
......@@ -531,44 +564,56 @@ pub const Compilation = struct {
531564 },
532565 .x = false,
533566 });
534 errdefer comp.gpa().destroy(comp.false_value);
535567
536 comp.noreturn_value = try comp.gpa().create(Value.NoReturn{
568 comp.noreturn_value = try comp.arena().create(Value.NoReturn{
537569 .base = Value{
538570 .id = Value.Id.NoReturn,
539571 .typeof = &Type.NoReturn.get(comp).base,
540572 .ref_count = std.atomic.Int(usize).init(1),
541573 },
542574 });
543 errdefer comp.gpa().destroy(comp.noreturn_value);
544 }
545575
546 fn derefTypes(self: *Compilation) void {
547 self.noreturn_value.base.deref(self);
548 self.void_value.base.deref(self);
549 self.false_value.base.deref(self);
550 self.true_value.base.deref(self);
551 self.noreturn_type.base.base.deref(self);
552 self.void_type.base.base.deref(self);
553 self.meta_type.base.base.deref(self);
576 for (CInt.list) |cint, i| {
577 const c_int_type = try comp.arena().create(Type.Int{
578 .base = Type{
579 .name = cint.zig_name,
580 .base = Value{
581 .id = Value.Id.Type,
582 .typeof = &Type.MetaType.get(comp).base,
583 .ref_count = std.atomic.Int(usize).init(1),
584 },
585 .id = builtin.TypeId.Int,
586 },
587 .key = Type.Int.Key{
588 .is_signed = cint.is_signed,
589 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),
590 },
591 .garbage_node = undefined,
592 });
593 comp.c_int_types[i] = c_int_type;
594 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);
595 }
554596 }
555597
598 /// This function can safely use async/await, because it manages Compilation's lifetime,
599 /// and EventLoopLocal.deinit will not be called until the event.Loop.run() completes.
556600 async fn internalDeinit(self: *Compilation) void {
557601 suspend;
602
558603 await (async self.deinit_group.wait() catch unreachable);
559604 if (self.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {
560605 // TODO evented I/O?
561606 os.deleteTree(self.arena(), tmp_dir) catch {};
562607 } else |_| {};
563608
564 self.derefTypes();
565
566609 self.events.destroy();
567610
568611 llvm.DisposeMessage(self.target_layout_str);
569612 llvm.DisposeTargetData(self.target_data_ref);
570613 llvm.DisposeTargetMachine(self.target_machine);
571614
615 self.primitive_type_table.deinit();
616
572617 self.arena_allocator.deinit();
573618 self.gpa().destroy(self);
574619 }
......@@ -939,6 +984,10 @@ pub const Compilation = struct {
939984 b64_fs_encoder.encode(result[0..], rand_bytes);
940985 return result;
941986 }
987
988 fn registerGarbage(comp: *Compilation, comptime T: type, node: *std.atomic.Stack(*T).Node) void {
989 // TODO put the garbage somewhere
990 }
942991};
943992
944993fn printError(comptime format: []const u8, args: ...) !void {
......@@ -1005,7 +1054,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
10051054 fn_decl.base.parsed_file,
10061055 &fndef_scope.base,
10071056 body_node,
1008 null,
1057 return_type,
10091058 ) catch unreachable)) orelse return;
10101059 errdefer analyzed_code.destroy(comp.gpa());
10111060
src-self-hosted/ir.zig+473-2
......@@ -705,7 +705,10 @@ pub const Builder = struct {
705705 ast.Node.Id.ErrorType => return error.Unimplemented,
706706 ast.Node.Id.FnProto => return error.Unimplemented,
707707 ast.Node.Id.PromiseType => return error.Unimplemented,
708 ast.Node.Id.IntegerLiteral => return error.Unimplemented,
708 ast.Node.Id.IntegerLiteral => {
709 const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node);
710 return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval);
711 },
709712 ast.Node.Id.FloatLiteral => return error.Unimplemented,
710713 ast.Node.Id.StringLiteral => return error.Unimplemented,
711714 ast.Node.Id.MultilineStringLiteral => return error.Unimplemented,
......@@ -766,6 +769,45 @@ pub const Builder = struct {
766769 }
767770 }
768771
772 pub fn genIntLit(irb: *Builder, int_lit: *ast.Node.IntegerLiteral, scope: *Scope) !*Inst {
773 const int_token = irb.parsed_file.tree.tokenSlice(int_lit.token);
774
775 var base: u8 = undefined;
776 var rest: []const u8 = undefined;
777 if (int_token.len >= 3 and int_token[0] == '0') {
778 base = switch (int_token[1]) {
779 'b' => u8(2),
780 'o' => u8(8),
781 'x' => u8(16),
782 else => unreachable,
783 };
784 rest = int_token[2..];
785 } else {
786 base = 10;
787 rest = int_token;
788 }
789
790 const comptime_int_type = Type.ComptimeInt.get(irb.comp);
791 defer comptime_int_type.base.base.deref(irb.comp);
792
793 const int_val = Value.Int.createFromString(
794 irb.comp,
795 &comptime_int_type.base,
796 base,
797 rest,
798 ) catch |err| switch (err) {
799 error.OutOfMemory => return error.OutOfMemory,
800 error.InvalidBase => unreachable,
801 error.InvalidCharForDigit => unreachable,
802 error.DigitTooLargeForBase => unreachable,
803 };
804 errdefer int_val.base.deref(irb.comp);
805
806 const inst = try irb.build(Inst.Const, scope, Span.token(int_lit.token), Inst.Const.Params{});
807 inst.val = IrVal{ .KnownValue = &int_val.base };
808 return inst;
809 }
810
769811 pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {
770812 const block_scope = try Scope.Block.create(irb.comp, parent_scope);
771813
......@@ -1306,7 +1348,436 @@ const Analyze = struct {
13061348
13071349 fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst {
13081350 const dest_type = optional_dest_type orelse return target;
1309 return error.Unimplemented;
1351 const from_type = target.getKnownType();
1352 if (from_type == dest_type or from_type.id == Type.Id.NoReturn) return target;
1353 return self.analyzeCast(target, target, dest_type);
1354 }
1355
1356 fn analyzeCast(ira: *Analyze, source_instr: *Inst, target: *Inst, dest_type: *Type) !*Inst {
1357 const from_type = target.getKnownType();
1358
1359 //if (type_is_invalid(wanted_type) || type_is_invalid(actual_type)) {
1360 // return ira->codegen->invalid_instruction;
1361 //}
1362
1363 //// perfect match or non-const to const
1364 //ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
1365 // source_node, false);
1366 //if (const_cast_result.id == ConstCastResultIdOk) {
1367 // return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
1368 //}
1369
1370 //// widening conversion
1371 //if (wanted_type->id == TypeTableEntryIdInt &&
1372 // actual_type->id == TypeTableEntryIdInt &&
1373 // wanted_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
1374 // wanted_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
1375 //{
1376 // return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
1377 //}
1378
1379 //// small enough unsigned ints can get casted to large enough signed ints
1380 //if (wanted_type->id == TypeTableEntryIdInt && wanted_type->data.integral.is_signed &&
1381 // actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
1382 // wanted_type->data.integral.bit_count > actual_type->data.integral.bit_count)
1383 //{
1384 // return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
1385 //}
1386
1387 //// float widening conversion
1388 //if (wanted_type->id == TypeTableEntryIdFloat &&
1389 // actual_type->id == TypeTableEntryIdFloat &&
1390 // wanted_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
1391 //{
1392 // return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
1393 //}
1394
1395 //// cast from [N]T to []const T
1396 //if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {
1397 // TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1398 // assert(ptr_type->id == TypeTableEntryIdPointer);
1399 // if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
1400 // types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1401 // source_node, false).id == ConstCastResultIdOk)
1402 // {
1403 // return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);
1404 // }
1405 //}
1406
1407 //// cast from *const [N]T to []const T
1408 //if (is_slice(wanted_type) &&
1409 // actual_type->id == TypeTableEntryIdPointer &&
1410 // actual_type->data.pointer.is_const &&
1411 // actual_type->data.pointer.child_type->id == TypeTableEntryIdArray)
1412 //{
1413 // TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1414 // assert(ptr_type->id == TypeTableEntryIdPointer);
1415
1416 // TypeTableEntry *array_type = actual_type->data.pointer.child_type;
1417
1418 // if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
1419 // types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, array_type->data.array.child_type,
1420 // source_node, false).id == ConstCastResultIdOk)
1421 // {
1422 // return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);
1423 // }
1424 //}
1425
1426 //// cast from [N]T to *const []const T
1427 //if (wanted_type->id == TypeTableEntryIdPointer &&
1428 // wanted_type->data.pointer.is_const &&
1429 // is_slice(wanted_type->data.pointer.child_type) &&
1430 // actual_type->id == TypeTableEntryIdArray)
1431 //{
1432 // TypeTableEntry *ptr_type =
1433 // wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
1434 // assert(ptr_type->id == TypeTableEntryIdPointer);
1435 // if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
1436 // types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1437 // source_node, false).id == ConstCastResultIdOk)
1438 // {
1439 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
1440 // if (type_is_invalid(cast1->value.type))
1441 // return ira->codegen->invalid_instruction;
1442
1443 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1444 // if (type_is_invalid(cast2->value.type))
1445 // return ira->codegen->invalid_instruction;
1446
1447 // return cast2;
1448 // }
1449 //}
1450
1451 //// cast from [N]T to ?[]const T
1452 //if (wanted_type->id == TypeTableEntryIdOptional &&
1453 // is_slice(wanted_type->data.maybe.child_type) &&
1454 // actual_type->id == TypeTableEntryIdArray)
1455 //{
1456 // TypeTableEntry *ptr_type =
1457 // wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
1458 // assert(ptr_type->id == TypeTableEntryIdPointer);
1459 // if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
1460 // types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1461 // source_node, false).id == ConstCastResultIdOk)
1462 // {
1463 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
1464 // if (type_is_invalid(cast1->value.type))
1465 // return ira->codegen->invalid_instruction;
1466
1467 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1468 // if (type_is_invalid(cast2->value.type))
1469 // return ira->codegen->invalid_instruction;
1470
1471 // return cast2;
1472 // }
1473 //}
1474
1475 //// *[N]T to [*]T
1476 //if (wanted_type->id == TypeTableEntryIdPointer &&
1477 // wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
1478 // actual_type->id == TypeTableEntryIdPointer &&
1479 // actual_type->data.pointer.ptr_len == PtrLenSingle &&
1480 // actual_type->data.pointer.child_type->id == TypeTableEntryIdArray &&
1481 // actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment &&
1482 // types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
1483 // actual_type->data.pointer.child_type->data.array.child_type, source_node,
1484 // !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
1485 //{
1486 // return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
1487 //}
1488
1489 //// *[N]T to []T
1490 //if (is_slice(wanted_type) &&
1491 // actual_type->id == TypeTableEntryIdPointer &&
1492 // actual_type->data.pointer.ptr_len == PtrLenSingle &&
1493 // actual_type->data.pointer.child_type->id == TypeTableEntryIdArray)
1494 //{
1495 // TypeTableEntry *slice_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1496 // assert(slice_ptr_type->id == TypeTableEntryIdPointer);
1497 // if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
1498 // actual_type->data.pointer.child_type->data.array.child_type, source_node,
1499 // !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
1500 // {
1501 // return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type);
1502 // }
1503 //}
1504
1505 //// cast from T to ?T
1506 //// note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
1507 //if (wanted_type->id == TypeTableEntryIdOptional) {
1508 // TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type;
1509 // if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
1510 // false).id == ConstCastResultIdOk)
1511 // {
1512 // return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
1513 // } else if (actual_type->id == TypeTableEntryIdComptimeInt ||
1514 // actual_type->id == TypeTableEntryIdComptimeFloat)
1515 // {
1516 // if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
1517 // return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
1518 // } else {
1519 // return ira->codegen->invalid_instruction;
1520 // }
1521 // } else if (wanted_child_type->id == TypeTableEntryIdPointer &&
1522 // wanted_child_type->data.pointer.is_const &&
1523 // (actual_type->id == TypeTableEntryIdPointer || is_container(actual_type)))
1524 // {
1525 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_child_type, value);
1526 // if (type_is_invalid(cast1->value.type))
1527 // return ira->codegen->invalid_instruction;
1528
1529 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1530 // if (type_is_invalid(cast2->value.type))
1531 // return ira->codegen->invalid_instruction;
1532
1533 // return cast2;
1534 // }
1535 //}
1536
1537 //// cast from null literal to maybe type
1538 //if (wanted_type->id == TypeTableEntryIdOptional &&
1539 // actual_type->id == TypeTableEntryIdNull)
1540 //{
1541 // return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
1542 //}
1543
1544 //// cast from child type of error type to error type
1545 //if (wanted_type->id == TypeTableEntryIdErrorUnion) {
1546 // if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
1547 // source_node, false).id == ConstCastResultIdOk)
1548 // {
1549 // return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
1550 // } else if (actual_type->id == TypeTableEntryIdComptimeInt ||
1551 // actual_type->id == TypeTableEntryIdComptimeFloat)
1552 // {
1553 // if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
1554 // return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
1555 // } else {
1556 // return ira->codegen->invalid_instruction;
1557 // }
1558 // }
1559 //}
1560
1561 //// cast from [N]T to E![]const T
1562 //if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1563 // is_slice(wanted_type->data.error_union.payload_type) &&
1564 // actual_type->id == TypeTableEntryIdArray)
1565 //{
1566 // TypeTableEntry *ptr_type =
1567 // wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry;
1568 // assert(ptr_type->id == TypeTableEntryIdPointer);
1569 // if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
1570 // types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1571 // source_node, false).id == ConstCastResultIdOk)
1572 // {
1573 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
1574 // if (type_is_invalid(cast1->value.type))
1575 // return ira->codegen->invalid_instruction;
1576
1577 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1578 // if (type_is_invalid(cast2->value.type))
1579 // return ira->codegen->invalid_instruction;
1580
1581 // return cast2;
1582 // }
1583 //}
1584
1585 //// cast from error set to error union type
1586 //if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1587 // actual_type->id == TypeTableEntryIdErrorSet)
1588 //{
1589 // return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
1590 //}
1591
1592 //// cast from T to E!?T
1593 //if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1594 // wanted_type->data.error_union.payload_type->id == TypeTableEntryIdOptional &&
1595 // actual_type->id != TypeTableEntryIdOptional)
1596 //{
1597 // TypeTableEntry *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
1598 // if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk ||
1599 // actual_type->id == TypeTableEntryIdNull ||
1600 // actual_type->id == TypeTableEntryIdComptimeInt ||
1601 // actual_type->id == TypeTableEntryIdComptimeFloat)
1602 // {
1603 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
1604 // if (type_is_invalid(cast1->value.type))
1605 // return ira->codegen->invalid_instruction;
1606
1607 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1608 // if (type_is_invalid(cast2->value.type))
1609 // return ira->codegen->invalid_instruction;
1610
1611 // return cast2;
1612 // }
1613 //}
1614
1615 // cast from number literal to another type
1616 //// cast from number literal to *const integer
1617 //if (actual_type->id == TypeTableEntryIdComptimeFloat ||
1618 // actual_type->id == TypeTableEntryIdComptimeInt)
1619 //{
1620 // ensure_complete_type(ira->codegen, wanted_type);
1621 // if (type_is_invalid(wanted_type))
1622 // return ira->codegen->invalid_instruction;
1623 // if (wanted_type->id == TypeTableEntryIdEnum) {
1624 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.enumeration.tag_int_type, value);
1625 // if (type_is_invalid(cast1->value.type))
1626 // return ira->codegen->invalid_instruction;
1627
1628 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1629 // if (type_is_invalid(cast2->value.type))
1630 // return ira->codegen->invalid_instruction;
1631
1632 // return cast2;
1633 // } else if (wanted_type->id == TypeTableEntryIdPointer &&
1634 // wanted_type->data.pointer.is_const)
1635 // {
1636 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
1637 // if (type_is_invalid(cast1->value.type))
1638 // return ira->codegen->invalid_instruction;
1639
1640 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1641 // if (type_is_invalid(cast2->value.type))
1642 // return ira->codegen->invalid_instruction;
1643
1644 // return cast2;
1645 // } else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
1646 // CastOp op;
1647 // if ((actual_type->id == TypeTableEntryIdComptimeFloat &&
1648 // wanted_type->id == TypeTableEntryIdFloat) ||
1649 // (actual_type->id == TypeTableEntryIdComptimeInt &&
1650 // wanted_type->id == TypeTableEntryIdInt))
1651 // {
1652 // op = CastOpNumLitToConcrete;
1653 // } else if (wanted_type->id == TypeTableEntryIdInt) {
1654 // op = CastOpFloatToInt;
1655 // } else if (wanted_type->id == TypeTableEntryIdFloat) {
1656 // op = CastOpIntToFloat;
1657 // } else {
1658 // zig_unreachable();
1659 // }
1660 // return ir_resolve_cast(ira, source_instr, value, wanted_type, op, false);
1661 // } else {
1662 // return ira->codegen->invalid_instruction;
1663 // }
1664 //}
1665
1666 //// cast from typed number to integer or float literal.
1667 //// works when the number is known at compile time
1668 //if (instr_is_comptime(value) &&
1669 // ((actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdComptimeInt) ||
1670 // (actual_type->id == TypeTableEntryIdFloat && wanted_type->id == TypeTableEntryIdComptimeFloat)))
1671 //{
1672 // return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
1673 //}
1674
1675 //// cast from union to the enum type of the union
1676 //if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {
1677 // type_ensure_zero_bits_known(ira->codegen, actual_type);
1678 // if (type_is_invalid(actual_type))
1679 // return ira->codegen->invalid_instruction;
1680
1681 // if (actual_type->data.unionation.tag_type == wanted_type) {
1682 // return ir_analyze_union_to_tag(ira, source_instr, value, wanted_type);
1683 // }
1684 //}
1685
1686 //// enum to union which has the enum as the tag type
1687 //if (wanted_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
1688 // (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
1689 // wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
1690 //{
1691 // type_ensure_zero_bits_known(ira->codegen, wanted_type);
1692 // if (wanted_type->data.unionation.tag_type == actual_type) {
1693 // return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
1694 // }
1695 //}
1696
1697 //// enum to &const union which has the enum as the tag type
1698 //if (actual_type->id == TypeTableEntryIdEnum && wanted_type->id == TypeTableEntryIdPointer) {
1699 // TypeTableEntry *union_type = wanted_type->data.pointer.child_type;
1700 // if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
1701 // union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
1702 // {
1703 // type_ensure_zero_bits_known(ira->codegen, union_type);
1704 // if (union_type->data.unionation.tag_type == actual_type) {
1705 // IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, union_type, value);
1706 // if (type_is_invalid(cast1->value.type))
1707 // return ira->codegen->invalid_instruction;
1708
1709 // IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1710 // if (type_is_invalid(cast2->value.type))
1711 // return ira->codegen->invalid_instruction;
1712
1713 // return cast2;
1714 // }
1715 // }
1716 //}
1717
1718 //// cast from *T to *[1]T
1719 //if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
1720 // actual_type->id == TypeTableEntryIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle)
1721 //{
1722 // TypeTableEntry *array_type = wanted_type->data.pointer.child_type;
1723 // if (array_type->id == TypeTableEntryIdArray && array_type->data.array.len == 1 &&
1724 // types_match_const_cast_only(ira, array_type->data.array.child_type,
1725 // actual_type->data.pointer.child_type, source_node,
1726 // !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
1727 // {
1728 // if (wanted_type->data.pointer.alignment > actual_type->data.pointer.alignment) {
1729 // ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
1730 // add_error_note(ira->codegen, msg, value->source_node,
1731 // buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name),
1732 // actual_type->data.pointer.alignment));
1733 // add_error_note(ira->codegen, msg, source_instr->source_node,
1734 // buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name),
1735 // wanted_type->data.pointer.alignment));
1736 // return ira->codegen->invalid_instruction;
1737 // }
1738 // return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);
1739 // }
1740 //}
1741
1742 //// cast from T to *T where T is zero bits
1743 //if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
1744 // types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
1745 // actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
1746 //{
1747 // type_ensure_zero_bits_known(ira->codegen, actual_type);
1748 // if (type_is_invalid(actual_type)) {
1749 // return ira->codegen->invalid_instruction;
1750 // }
1751 // if (!type_has_bits(actual_type)) {
1752 // return ir_get_ref(ira, source_instr, value, false, false);
1753 // }
1754 //}
1755
1756 //// cast from undefined to anything
1757 //if (actual_type->id == TypeTableEntryIdUndefined) {
1758 // return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
1759 //}
1760
1761 //// cast from something to const pointer of it
1762 //if (!type_requires_comptime(actual_type)) {
1763 // TypeTableEntry *const_ptr_actual = get_pointer_to_type(ira->codegen, actual_type, true);
1764 // if (types_match_const_cast_only(ira, wanted_type, const_ptr_actual, source_node, false).id == ConstCastResultIdOk) {
1765 // return ir_analyze_cast_ref(ira, source_instr, value, wanted_type);
1766 // }
1767 //}
1768
1769 try ira.addCompileError(
1770 source_instr.span,
1771 "expected type '{}', found '{}'",
1772 dest_type.name,
1773 from_type.name,
1774 );
1775 //ErrorMsg *parent_msg = ir_add_error_node(ira, source_instr->source_node,
1776 // buf_sprintf("expected type '%s', found '%s'",
1777 // buf_ptr(&wanted_type->name),
1778 // buf_ptr(&actual_type->name)));
1779 //report_recursive_error(ira, source_instr->source_node, &const_cast_result, parent_msg);
1780 return error.SemanticAnalysisFailed;
13101781 }
13111782
13121783 fn getCompTimeValOrNullUndefOk(self: *Analyze, target: *Inst) ?*Value {
src-self-hosted/llvm.zig+2
......@@ -30,6 +30,8 @@ pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
3030pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
3131pub const ConstAllOnes = c.LLVMConstAllOnes;
3232pub const ConstInt = c.LLVMConstInt;
33pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
34pub const ConstNeg = c.LLVMConstNeg;
3335pub const ConstNull = c.LLVMConstNull;
3436pub const ConstStringInContext = c.LLVMConstStringInContext;
3537pub const ConstStructInContext = c.LLVMConstStructInContext;
src-self-hosted/target.zig+98-1
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const llvm = @import("llvm.zig");
4const CInt = @import("c_int.zig").CInt;
45
56pub const FloatAbi = enum {
67 Hard,
......@@ -173,7 +174,7 @@ pub const Target = union(enum) {
173174 return self.getArchPtrBitWidth() == 64;
174175 }
175176
176 pub fn getArchPtrBitWidth(self: Target) u8 {
177 pub fn getArchPtrBitWidth(self: Target) u32 {
177178 switch (self.getArch()) {
178179 builtin.Arch.avr,
179180 builtin.Arch.msp430,
......@@ -429,4 +430,100 @@ pub const Target = union(enum) {
429430 }
430431 return result;
431432 }
433
434 pub fn cIntTypeSizeInBits(self: Target, id: CInt.Id) u32 {
435 const arch = self.getArch();
436 switch (self.getOs()) {
437 builtin.Os.freestanding => switch (self.getArch()) {
438 builtin.Arch.msp430 => switch (id) {
439 CInt.Id.Short,
440 CInt.Id.UShort,
441 CInt.Id.Int,
442 CInt.Id.UInt,
443 => return 16,
444 CInt.Id.Long,
445 CInt.Id.ULong,
446 => return 32,
447 CInt.Id.LongLong,
448 CInt.Id.ULongLong,
449 => return 64,
450 },
451 else => switch (id) {
452 CInt.Id.Short,
453 CInt.Id.UShort,
454 => return 16,
455 CInt.Id.Int,
456 CInt.Id.UInt,
457 => return 32,
458 CInt.Id.Long,
459 CInt.Id.ULong,
460 => return self.getArchPtrBitWidth(),
461 CInt.Id.LongLong,
462 CInt.Id.ULongLong,
463 => return 64,
464 },
465 },
466
467 builtin.Os.linux,
468 builtin.Os.macosx,
469 builtin.Os.openbsd,
470 builtin.Os.zen,
471 => switch (id) {
472 CInt.Id.Short,
473 CInt.Id.UShort,
474 => return 16,
475 CInt.Id.Int,
476 CInt.Id.UInt,
477 => return 32,
478 CInt.Id.Long,
479 CInt.Id.ULong,
480 => return self.getArchPtrBitWidth(),
481 CInt.Id.LongLong,
482 CInt.Id.ULongLong,
483 => return 64,
484 },
485
486 builtin.Os.windows => switch (id) {
487 CInt.Id.Short,
488 CInt.Id.UShort,
489 => return 16,
490 CInt.Id.Int,
491 CInt.Id.UInt,
492 => return 32,
493 CInt.Id.Long,
494 CInt.Id.ULong,
495 CInt.Id.LongLong,
496 CInt.Id.ULongLong,
497 => return 64,
498 },
499
500 builtin.Os.ananas,
501 builtin.Os.cloudabi,
502 builtin.Os.dragonfly,
503 builtin.Os.freebsd,
504 builtin.Os.fuchsia,
505 builtin.Os.ios,
506 builtin.Os.kfreebsd,
507 builtin.Os.lv2,
508 builtin.Os.netbsd,
509 builtin.Os.solaris,
510 builtin.Os.haiku,
511 builtin.Os.minix,
512 builtin.Os.rtems,
513 builtin.Os.nacl,
514 builtin.Os.cnk,
515 builtin.Os.aix,
516 builtin.Os.cuda,
517 builtin.Os.nvcl,
518 builtin.Os.amdhsa,
519 builtin.Os.ps4,
520 builtin.Os.elfiamcu,
521 builtin.Os.tvos,
522 builtin.Os.watchos,
523 builtin.Os.mesa3d,
524 builtin.Os.contiki,
525 builtin.Os.amdpal,
526 => @panic("TODO specify the C integer type sizes for this OS"),
527 }
528 }
432529};
src-self-hosted/type.zig+88-10
......@@ -9,6 +9,7 @@ const ObjectFile = @import("codegen.zig").ObjectFile;
99pub const Type = struct {
1010 base: Value,
1111 id: Id,
12 name: []const u8,
1213
1314 pub const Id = builtin.TypeId;
1415
......@@ -151,6 +152,18 @@ pub const Type = struct {
151152 std.debug.warn("{}", @tagName(base.id));
152153 }
153154
155 fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void {
156 base.* = Type{
157 .base = Value{
158 .id = Value.Id.Type,
159 .typeof = &MetaType.get(comp).base,
160 .ref_count = std.atomic.Int(usize).init(1),
161 },
162 .id = id,
163 .name = name,
164 };
165 }
166
154167 pub fn getAbiAlignment(base: *Type, comp: *Compilation) u32 {
155168 @panic("TODO getAbiAlignment");
156169 }
......@@ -181,20 +194,15 @@ pub const Type = struct {
181194
182195 pub fn create(comp: *Compilation, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
183196 const result = try comp.gpa().create(Fn{
184 .base = Type{
185 .base = Value{
186 .id = Value.Id.Type,
187 .typeof = &MetaType.get(comp).base,
188 .ref_count = std.atomic.Int(usize).init(1),
189 },
190 .id = builtin.TypeId.Fn,
191 },
197 .base = undefined,
192198 .return_type = return_type,
193199 .params = params,
194200 .is_var_args = is_var_args,
195201 });
196202 errdefer comp.gpa().destroy(result);
197203
204 result.base.init(comp, Id.Fn, "TODO fn type name");
205
198206 result.return_type.base.ref();
199207 for (result.params) |param| {
200208 param.typeof.base.ref();
......@@ -293,13 +301,77 @@ pub const Type = struct {
293301
294302 pub const Int = struct {
295303 base: Type,
304 key: Key,
305 garbage_node: std.atomic.Stack(*Int).Node,
306
307 pub const Key = struct {
308 bit_count: u32,
309 is_signed: bool,
310
311 pub fn hash(self: *const Key) u32 {
312 const rands = [2]u32{ 0xa4ba6498, 0x75fc5af7 };
313 return rands[@boolToInt(self.is_signed)] *% self.bit_count;
314 }
315
316 pub fn eql(self: *const Key, other: *const Key) bool {
317 return self.bit_count == other.bit_count and self.is_signed == other.is_signed;
318 }
319 };
320
321 pub async fn get(comp: *Compilation, key: Key) !*Int {
322 {
323 const held = await (async comp.int_type_table.acquire() catch unreachable);
324 defer held.release();
325
326 if (held.value.get(&key)) |entry| {
327 return entry.value;
328 }
329 }
330
331 const self = try comp.gpa().create(Int{
332 .base = undefined,
333 .key = key,
334 .garbage_node = undefined,
335 });
336 errdefer comp.gpa().destroy(self);
337
338 const u_or_i = "ui"[@boolToInt(key.is_signed)];
339 const name = std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count);
340 errdefer comp.gpa().free(name);
341
342 self.base.init(comp, Id.Int, name);
343
344 {
345 const held = await (async comp.int_type_table.acquire() catch unreachable);
346 defer held.release();
347
348 held.value.put(&self.key, self);
349 }
350 return self;
351 }
296352
297353 pub fn destroy(self: *Int, comp: *Compilation) void {
354 self.garbage_node = std.atomic.Stack(*Int).Node{
355 .data = self,
356 .next = undefined,
357 };
358 comp.registerGarbage(Int, &self.garbage_node);
359 }
360
361 pub async fn gcDestroy(self: *Int, comp: *Compilation) void {
362 {
363 const held = await (async comp.int_type_table.acquire() catch unreachable);
364 defer held.release();
365
366 _ = held.value.remove(&self.key).?;
367 }
368 // we allocated the name
369 comp.gpa().free(self.base.name);
298370 comp.gpa().destroy(self);
299371 }
300372
301 pub fn getLlvmType(self: *Int, ofile: *ObjectFile) llvm.TypeRef {
302 @panic("TODO");
373 pub fn getLlvmType(self: *Int, ofile: *ObjectFile) !llvm.TypeRef {
374 return llvm.IntTypeInContext(ofile.context, self.key.bit_count) orelse return error.OutOfMemory;
303375 }
304376 };
305377
......@@ -374,6 +446,12 @@ pub const Type = struct {
374446 pub const ComptimeInt = struct {
375447 base: Type,
376448
449 /// Adds 1 reference to the resulting type
450 pub fn get(comp: *Compilation) *ComptimeInt {
451 comp.comptime_int_type.base.base.ref();
452 return comp.comptime_int_type;
453 }
454
377455 pub fn destroy(self: *ComptimeInt, comp: *Compilation) void {
378456 comp.gpa().destroy(self);
379457 }
src-self-hosted/value.zig+58
......@@ -29,6 +29,7 @@ pub const Value = struct {
2929 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
3030 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
3131 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
32 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
3233 }
3334 }
3435 }
......@@ -50,6 +51,7 @@ pub const Value = struct {
5051 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),
5152 Id.NoReturn => unreachable,
5253 Id.Ptr => @panic("TODO"),
54 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile),
5355 }
5456 }
5557
......@@ -60,6 +62,7 @@ pub const Value = struct {
6062 Bool,
6163 NoReturn,
6264 Ptr,
65 Int,
6366 };
6467
6568 pub const Type = @import("type.zig").Type;
......@@ -198,4 +201,59 @@ pub const Value = struct {
198201 comp.gpa().destroy(self);
199202 }
200203 };
204
205 pub const Int = struct {
206 base: Value,
207 big_int: std.math.big.Int,
208
209 pub fn createFromString(comp: *Compilation, typeof: *Type, base: u8, value: []const u8) !*Int {
210 const self = try comp.gpa().create(Value.Int{
211 .base = Value{
212 .id = Value.Id.Int,
213 .typeof = typeof,
214 .ref_count = std.atomic.Int(usize).init(1),
215 },
216 .big_int = undefined,
217 });
218 typeof.base.ref();
219 errdefer comp.gpa().destroy(self);
220
221 self.big_int = try std.math.big.Int.init(comp.gpa());
222 errdefer self.big_int.deinit();
223
224 try self.big_int.setString(base, value);
225
226 return self;
227 }
228
229 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {
230 switch (self.base.typeof.id) {
231 Type.Id.Int => {
232 const type_ref = try self.base.typeof.getLlvmType(ofile);
233 if (self.big_int.len == 0) {
234 return llvm.ConstNull(type_ref);
235 }
236 const unsigned_val = if (self.big_int.len == 1) blk: {
237 break :blk llvm.ConstInt(type_ref, self.big_int.limbs[0], @boolToInt(false));
238 } else if (@sizeOf(std.math.big.Limb) == @sizeOf(u64)) blk: {
239 break :blk llvm.ConstIntOfArbitraryPrecision(
240 type_ref,
241 @intCast(c_uint, self.big_int.len),
242 @ptrCast([*]u64, self.big_int.limbs.ptr),
243 );
244 } else {
245 @compileError("std.math.Big.Int.Limb size does not match LLVM");
246 };
247 return if (self.big_int.positive) unsigned_val else llvm.ConstNeg(unsigned_val);
248 },
249 Type.Id.ComptimeInt => unreachable,
250 else => unreachable,
251 }
252 }
253
254 pub fn destroy(self: *Int, comp: *Compilation) void {
255 self.big_int.deinit();
256 comp.gpa().destroy(self);
257 }
258 };
201259};
std/event/group.zig+11
......@@ -38,6 +38,15 @@ pub fn Group(comptime ReturnType: type) type {
3838 self.alloc_stack.push(node);
3939 }
4040
41 /// Add a node to the group. Thread-safe. Cannot fail.
42 /// `node.data` should be the promise handle to add to the group.
43 /// The node's memory should be in the coroutine frame of
44 /// the handle that is in the node, or somewhere guaranteed to live
45 /// at least as long.
46 pub fn addNode(self: *Self, node: *Stack.Node) void {
47 self.coro_stack.push(node);
48 }
49
4150 /// This is equivalent to an async call, but the async function is added to the group, instead
4251 /// of returning a promise. func must be async and have return type ReturnType.
4352 /// Thread-safe.
......@@ -98,6 +107,8 @@ pub fn Group(comptime ReturnType: type) type {
98107 }
99108
100109 /// Cancel all the outstanding promises. May only be called if wait was never called.
110 /// TODO These should be `cancelasync` not `cancel`.
111 /// See https://github.com/ziglang/zig/issues/1261
101112 pub fn cancelAll(self: *Self) void {
102113 while (self.coro_stack.pop()) |node| {
103114 cancel node.data;
std/math/big/int.zig+2-1
......@@ -60,8 +60,9 @@ pub const Int = struct {
6060 self.limbs = try self.allocator.realloc(Limb, self.limbs, capacity);
6161 }
6262
63 pub fn deinit(self: Int) void {
63 pub fn deinit(self: *Int) void {
6464 self.allocator.free(self.limbs);
65 self.* = undefined;
6566 }
6667
6768 pub fn clone(other: Int) !Int {