| ... | ... | @@ -140,6 +140,29 @@ pub fn generateFunction( |
| 140 | 140 | } |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void { |
| 144 | if (F == f80) { |
| 145 | switch (target.cpu.arch) { |
| 146 | .i386, .x86_64 => { |
| 147 | const repr = math.break_f80(f); |
| 148 | mem.writeIntLittle(u64, code[0..8], repr.fraction); |
| 149 | mem.writeIntLittle(u16, code[8..10], repr.exp); |
| 150 | // TODO set the rest of the bytes to undefined. should we use 0xaa |
| 151 | // or is there a different way? |
| 152 | return; |
| 153 | }, |
| 154 | else => {}, |
| 155 | } |
| 156 | } else { |
| 157 | const Int = @Type(.{ .Int = .{ |
| 158 | .signedness = .unsigned, |
| 159 | .bits = @typeInfo(F).Float.bits, |
| 160 | } }); |
| 161 | const int = @bitCast(Int, f); |
| 162 | mem.writeInt(Int, code[0..@sizeOf(Int)], int, endian); |
| 163 | } |
| 164 | } |
| 165 | |
| 143 | 166 | pub fn generateSymbol( |
| 144 | 167 | bin_file: *link.File, |
| 145 | 168 | src_loc: Module.SrcLoc, |
| ... | ... | @@ -151,10 +174,12 @@ pub fn generateSymbol( |
| 151 | 174 | const tracy = trace(@src()); |
| 152 | 175 | defer tracy.end(); |
| 153 | 176 | |
| 177 | const target = bin_file.options.target; |
| 178 | const endian = target.cpu.arch.endian(); |
| 179 | |
| 154 | 180 | log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val }); |
| 155 | 181 | |
| 156 | 182 | if (typed_value.val.isUndefDeep()) { |
| 157 | | const target = bin_file.options.target; |
| 158 | 183 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); |
| 159 | 184 | try code.appendNTimes(0xaa, abi_size); |
| 160 | 185 | return Result{ .appended = {} }; |
| ... | ... | @@ -171,6 +196,18 @@ pub fn generateSymbol( |
| 171 | 196 | ), |
| 172 | 197 | }; |
| 173 | 198 | }, |
| 199 | .Float => { |
| 200 | const float_bits = typed_value.ty.floatBits(target); |
| 201 | switch (float_bits) { |
| 202 | 16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)), |
| 203 | 32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)), |
| 204 | 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)), |
| 205 | 80 => writeFloat(f80, typed_value.val.toFloat(f80), target, endian, try code.addManyAsArray(10)), |
| 206 | 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)), |
| 207 | else => unreachable, |
| 208 | } |
| 209 | return Result{ .appended = {} }; |
| 210 | }, |
| 174 | 211 | .Array => switch (typed_value.val.tag()) { |
| 175 | 212 | .bytes => { |
| 176 | 213 | // TODO populate .debug_info for the array |
| ... | ... | @@ -311,7 +348,6 @@ pub fn generateSymbol( |
| 311 | 348 | return Result{ .appended = {} }; |
| 312 | 349 | }, |
| 313 | 350 | .field_ptr => { |
| 314 | | const target = bin_file.options.target; |
| 315 | 351 | const field_ptr = typed_value.val.castTag(.field_ptr).?.data; |
| 316 | 352 | const container_ptr = field_ptr.container_ptr; |
| 317 | 353 | |
| ... | ... | @@ -373,7 +409,6 @@ pub fn generateSymbol( |
| 373 | 409 | }, |
| 374 | 410 | .Int => { |
| 375 | 411 | // TODO populate .debug_info for the integer |
| 376 | | const endian = bin_file.options.target.cpu.arch.endian(); |
| 377 | 412 | const info = typed_value.ty.intInfo(bin_file.options.target); |
| 378 | 413 | if (info.bits <= 8) { |
| 379 | 414 | const x = @intCast(u8, typed_value.val.toUnsignedInt()); |
| ... | ... | @@ -423,7 +458,6 @@ pub fn generateSymbol( |
| 423 | 458 | var int_buffer: Value.Payload.U64 = undefined; |
| 424 | 459 | const int_val = typed_value.enumToInt(&int_buffer); |
| 425 | 460 | |
| 426 | | const target = bin_file.options.target; |
| 427 | 461 | const info = typed_value.ty.intInfo(target); |
| 428 | 462 | if (info.bits <= 8) { |
| 429 | 463 | const x = @intCast(u8, int_val.toUnsignedInt()); |
| ... | ... | @@ -440,7 +474,6 @@ pub fn generateSymbol( |
| 440 | 474 | ), |
| 441 | 475 | }; |
| 442 | 476 | } |
| 443 | | const endian = target.cpu.arch.endian(); |
| 444 | 477 | switch (info.signedness) { |
| 445 | 478 | .unsigned => { |
| 446 | 479 | if (info.bits <= 16) { |
| ... | ... | @@ -506,7 +539,6 @@ pub fn generateSymbol( |
| 506 | 539 | const unpadded_field_end = code.items.len - struct_begin; |
| 507 | 540 | |
| 508 | 541 | // Pad struct members if required |
| 509 | | const target = bin_file.options.target; |
| 510 | 542 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target); |
| 511 | 543 | const padding = try math.cast(usize, padded_field_end - unpadded_field_end); |
| 512 | 544 | |
| ... | ... | @@ -519,7 +551,6 @@ pub fn generateSymbol( |
| 519 | 551 | }, |
| 520 | 552 | .Union => { |
| 521 | 553 | // TODO generate debug info for unions |
| 522 | | const target = bin_file.options.target; |
| 523 | 554 | const union_obj = typed_value.val.castTag(.@"union").?.data; |
| 524 | 555 | const layout = typed_value.ty.unionGetLayout(target); |
| 525 | 556 | |
| ... | ... | @@ -590,19 +621,69 @@ pub fn generateSymbol( |
| 590 | 621 | return Result{ .appended = {} }; |
| 591 | 622 | }, |
| 592 | 623 | .Optional => { |
| 593 | | // TODO generateSymbol for optionals |
| 594 | | const target = bin_file.options.target; |
| 624 | // TODO generate debug info for optionals |
| 625 | var opt_buf: Type.Payload.ElemType = undefined; |
| 626 | const payload_type = typed_value.ty.optionalChild(&opt_buf); |
| 627 | const is_pl = !typed_value.val.isNull(); |
| 595 | 628 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); |
| 596 | | try code.writer().writeByteNTimes(0xaa, abi_size); |
| 629 | const offset = abi_size - try math.cast(usize, payload_type.abiSize(target)); |
| 630 | |
| 631 | if (!payload_type.hasRuntimeBits()) { |
| 632 | try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size); |
| 633 | return Result{ .appended = {} }; |
| 634 | } |
| 635 | |
| 636 | if (typed_value.ty.isPtrLikeOptional()) { |
| 637 | if (typed_value.val.castTag(.opt_payload)) |payload| { |
| 638 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 639 | .ty = payload_type, |
| 640 | .val = payload.data, |
| 641 | }, code, debug_output, reloc_info)) { |
| 642 | .appended => {}, |
| 643 | .externally_managed => |external_slice| { |
| 644 | code.appendSliceAssumeCapacity(external_slice); |
| 645 | }, |
| 646 | .fail => |em| return Result{ .fail = em }, |
| 647 | } |
| 648 | } else if (!typed_value.val.isNull()) { |
| 649 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 650 | .ty = payload_type, |
| 651 | .val = typed_value.val, |
| 652 | }, code, debug_output, reloc_info)) { |
| 653 | .appended => {}, |
| 654 | .externally_managed => |external_slice| { |
| 655 | code.appendSliceAssumeCapacity(external_slice); |
| 656 | }, |
| 657 | .fail => |em| return Result{ .fail = em }, |
| 658 | } |
| 659 | } else { |
| 660 | try code.writer().writeByteNTimes(0, abi_size); |
| 661 | } |
| 662 | |
| 663 | return Result{ .appended = {} }; |
| 664 | } |
| 665 | |
| 666 | const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef); |
| 667 | try code.writer().writeByteNTimes(@boolToInt(is_pl), offset); |
| 668 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 669 | .ty = payload_type, |
| 670 | .val = value, |
| 671 | }, code, debug_output, reloc_info)) { |
| 672 | .appended => {}, |
| 673 | .externally_managed => |external_slice| { |
| 674 | code.appendSliceAssumeCapacity(external_slice); |
| 675 | }, |
| 676 | .fail => |em| return Result{ .fail = em }, |
| 677 | } |
| 597 | 678 | |
| 598 | 679 | return Result{ .appended = {} }; |
| 599 | 680 | }, |
| 600 | 681 | .ErrorUnion => { |
| 682 | // TODO generate debug info for error unions |
| 601 | 683 | const error_ty = typed_value.ty.errorUnionSet(); |
| 602 | 684 | const payload_ty = typed_value.ty.errorUnionPayload(); |
| 603 | 685 | const is_payload = typed_value.val.errorUnionIsPayload(); |
| 604 | 686 | |
| 605 | | const target = bin_file.options.target; |
| 606 | 687 | const abi_align = typed_value.ty.abiAlignment(target); |
| 607 | 688 | |
| 608 | 689 | const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero); |
| ... | ... | @@ -643,12 +724,11 @@ pub fn generateSymbol( |
| 643 | 724 | return Result{ .appended = {} }; |
| 644 | 725 | }, |
| 645 | 726 | .ErrorSet => { |
| 646 | | const target = bin_file.options.target; |
| 727 | // TODO generate debug info for error sets |
| 647 | 728 | switch (typed_value.val.tag()) { |
| 648 | 729 | .@"error" => { |
| 649 | 730 | const name = typed_value.val.getError().?; |
| 650 | 731 | const kv = try bin_file.options.module.?.getErrorValue(name); |
| 651 | | const endian = target.cpu.arch.endian(); |
| 652 | 732 | try code.writer().writeInt(u32, kv.value, endian); |
| 653 | 733 | }, |
| 654 | 734 | else => { |