record by aliasing group, unit tests for record/replay genext, add PtrToInt#44
Conversation
Coverage
Diff CoverageDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
genext.hppLines 22-32 22 struct Config {
23 std::set<AliasingGroup> groups;
24 size_t min_align = 1;
25
! 26 bool has(AliasingGroup group) const {
! 27 return groups.find(group) != groups.end();
! 28 }
29 };
30 private:
31 Section* _section;
32 Builder _builder;Lines 38-49 38
39 for (Block* block : *_section) {
40 for (Inst* inst : *block) {
41 if (dynmatch(LoadInst, load, inst)) {
! 42 if (_config.has(load->aliasing())) {
43 _builder.move_after(block, inst);
44
! 45 Value* aligned_ptr = build_tape_advance(_builder, tape_ptr, _config.min_align, load->type());
46 _builder.build_store(aligned_ptr, load, AliasingGroup(0), 0);
47 }
48 }
49 }Lines 53-61 53 AddRecord(Section* section, Config config):
54 Pass(section),
55 _section(section),
56 _builder(section),
! 57 _config(config) {
58
59 apply();
60 }Lines 62-71 62 AddRecord(Section* section, size_t& max_write_size, Config config):
63 Pass(section),
64 _section(section),
65 _builder(section),
! 66 _config(config) {
! 67
68 apply();
69
70 max_write_size = this->max_write_size();
71 }Lines 98-107 98 for (Block* block : *_section) {
99 size_t size = max_entry_sizes[block];
100 for (Inst* inst : *block) {
101 if (dynmatch(LoadInst, load, inst)) {
! 102 if (_config.has(load->aliasing())) {
! 103 size_t load_size = std::max(_config.min_align, type_size(load->type()));
104 if (size % load_size != 0) {
105 size += load_size - (size % load_size);
106 }
107 size += load_size;Lines 901-916 901
902 Value* emit_inst(Inst* inst) {
903 if (_config.record.has_value()) {
904 if (dynmatch(LoadInst, load, inst)) {
! 905 if (_config.record->has(load->aliasing())) {
! 906 Value* aligned_ptr = AddRecord::build_tape_advance(_builder, _tape_ptr, _config.record->min_align, load->type());
907 return _builder.build_load(aligned_ptr, load->type(), LoadFlags::None, AliasingGroup(0), 0);
908 }
! 909 } else if (dynmatch(StoreInst, store, inst)) {
! 910 if (_config.record->has(store->aliasing())) {
! 911 return nullptr;
! 912 }
913 }
914 }
915 return Clone::clone(inst, _builder, _blocks, _values);
916 }Lines 1408-1426 1408 for (Arg* arg : section->entry()->args()) {
1409 entry_arg_types.push_back(arg->type());
1410 }
1411 entry_arg_types.push_back(Type::Ptr);
! 1412 if (_config.record.has_value()) {
1413 entry_arg_types.push_back(Type::Ptr);
1414 }
1415 _builder.move_to_end(_builder.build_block(entry_arg_types));
1416
! 1417 size_t builder_index = _section->entry()->args().size();
! 1418 _jitir_builder = _genext_section->entry()->arg(builder_index);
! 1419 if (_config.record.has_value()) {
! 1420 _tape_ptr = _genext_section->entry()->arg(builder_index + 1);
! 1421 }
! 1422
1423 for (Block* block : *section) {
1424 std::vector<Type> arg_types;
1425 for (Arg* arg : block->args()) {
1426 arg_types.push_back(arg->type()); // values |
Coverage
Diff CoverageDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
genext.hppLines 22-32 22 struct Config {
23 std::set<AliasingGroup> groups;
24 size_t min_align = 1;
25
! 26 bool has(AliasingGroup group) const {
! 27 return groups.find(group) != groups.end();
! 28 }
29 };
30 private:
31 Section* _section;
32 Builder _builder;Lines 36-50 36 Arg* tape_ptr = _builder.alloc_arg(Type::Ptr, _section->entry()->args().size());
37 _builder.add_args_to_block(_section->entry(), {tape_ptr});
38
39 for (Block* block : *_section) {
! 40 for (Inst* inst = *block->begin(); inst; inst = inst->next()) {
41 if (dynmatch(LoadInst, load, inst)) {
! 42 if (_config.has(load->aliasing())) {
43 _builder.move_after(block, inst);
! 44
! 45 Value* aligned_ptr = build_tape_advance(_builder, tape_ptr, _config.min_align, load->type());
! 46 inst = _builder.build_store(aligned_ptr, load, AliasingGroup(0), 0);
47 }
48 }
49 }
50 }Lines 53-61 53 AddRecord(Section* section, Config config):
54 Pass(section),
55 _section(section),
56 _builder(section),
! 57 _config(config) {
58
59 apply();
60 }Lines 62-71 62 AddRecord(Section* section, size_t& max_write_size, Config config):
63 Pass(section),
64 _section(section),
65 _builder(section),
! 66 _config(config) {
! 67
68 apply();
69
70 max_write_size = this->max_write_size();
71 }Lines 98-107 98 for (Block* block : *_section) {
99 size_t size = max_entry_sizes[block];
100 for (Inst* inst : *block) {
101 if (dynmatch(LoadInst, load, inst)) {
! 102 if (_config.has(load->aliasing())) {
! 103 size_t load_size = std::max(_config.min_align, type_size(load->type()));
104 if (size % load_size != 0) {
105 size += load_size - (size % load_size);
106 }
107 size += load_size;Lines 115-123 115
116 max_size = std::max(max_size, size);
117 }
118
! 119 assert(max_size % _config.min_align == 0);
120 return max_size;
121 }
122 };Lines 902-917 902
903 Value* emit_inst(Inst* inst) {
904 if (_config.record.has_value()) {
905 if (dynmatch(LoadInst, load, inst)) {
! 906 if (_config.record->has(load->aliasing())) {
! 907 Value* aligned_ptr = AddRecord::build_tape_advance(_builder, _tape_ptr, _config.record->min_align, load->type());
908 return _builder.build_load(aligned_ptr, load->type(), LoadFlags::None, AliasingGroup(0), 0);
909 }
! 910 } else if (dynmatch(StoreInst, store, inst)) {
! 911 if (_config.record->has(store->aliasing())) {
! 912 return nullptr;
! 913 }
914 }
915 }
916 return Clone::clone(inst, _builder, _blocks, _values);
917 }Lines 1409-1427 1409 for (Arg* arg : section->entry()->args()) {
1410 entry_arg_types.push_back(arg->type());
1411 }
1412 entry_arg_types.push_back(Type::Ptr);
! 1413 if (_config.record.has_value()) {
1414 entry_arg_types.push_back(Type::Ptr);
1415 }
1416 _builder.move_to_end(_builder.build_block(entry_arg_types));
1417
! 1418 size_t builder_index = _section->entry()->args().size();
! 1419 _jitir_builder = _genext_section->entry()->arg(builder_index);
! 1420 if (_config.record.has_value()) {
! 1421 _tape_ptr = _genext_section->entry()->arg(builder_index + 1);
! 1422 }
! 1423
1424 for (Block* block : *section) {
1425 std::vector<Type> arg_types;
1426 for (Arg* arg : block->args()) {
1427 arg_types.push_back(arg->type()); // values |
Coverage
Diff CoverageDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
genext.hppLines 53-61 53 AddRecord(Section* section, Config config):
54 Pass(section),
55 _section(section),
56 _builder(section),
! 57 _config(config) {
58
59 apply();
60 }Lines 558-573 558 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
559 Value* built = builder.build_call(syms.build_float_to_int_s, Type::Ptr, build_args);
560 return built;
561 }
! 562 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 563 std::vector<Value*> build_args;
! 564 build_args.push_back(jitir_builder);
! 565 build_args.push_back(args[0]);
! 566 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
! 567 Value* built = builder.build_call(syms.build_ptr_to_int, Type::Ptr, build_args);
! 568 return built;
! 569 }
570 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
571 std::vector<Value*> build_args;
572 build_args.push_back(jitir_builder);
573 build_args.push_back(args[0]);Lines 1419-1437 1419 for (Arg* arg : section->entry()->args()) {
1420 entry_arg_types.push_back(arg->type());
1421 }
1422 entry_arg_types.push_back(Type::Ptr);
! 1423 if (_config.record.has_value()) {
1424 entry_arg_types.push_back(Type::Ptr);
1425 }
1426 _builder.move_to_end(_builder.build_block(entry_arg_types));
1427
! 1428 size_t builder_index = _section->entry()->args().size();
! 1429 _jitir_builder = _genext_section->entry()->arg(builder_index);
! 1430 if (_config.record.has_value()) {
! 1431 _tape_ptr = _genext_section->entry()->arg(builder_index + 1);
! 1432 }
! 1433
1434 for (Block* block : *section) {
1435 std::vector<Type> arg_types;
1436 for (Arg* arg : block->args()) {
1437 arg_types.push_back(arg->type()); // valuesjitir.hppLines 1415-1448 1415 write_args(stream, is_first);
1416 if (!is_first) { stream << ", "; } else { is_first = false; }
1417 stream << Highlight::ArgName << "type=" << Highlight::None; stream << Highlight::Type << _type << Highlight::None;;
1418 }
! 1419 void write_json(std::ostream& stream) const override {
! 1420 stream << "{";
! 1421 stream << "\"kind\": ";
! 1422 stream << "\"PtrToInt\"";
! 1423 stream << ", ";
! 1424 stream << "\"args\": ";
! 1425 write_args_json(stream);
! 1426 stream << ", ";
! 1427 stream << "\"name\": ";
! 1428 stream << name();
! 1429 stream << ", ";
! 1430 stream << "\"type\": ";
! 1431 stream << "\"" << _type << "\"";
! 1432 stream << "}";
! 1433 } bool equals(const Value* other) const override {
! 1434 if (this == other) { return true; }
! 1435 if (other == nullptr) { return false; }
! 1436 if (typeid(*this) != typeid(*other)) { return false; }
! 1437 const PtrToIntInst* other_inst = (const PtrToIntInst*) other;
! 1438 if (arg_count() != other_inst->arg_count()) { return false; }
! 1439 for (size_t it = 0; it < arg_count(); it++) {
! 1440 if (arg(it) != other_inst->arg(it)) { return false; }
! 1441 }
! 1442 if (_type != other_inst->_type) { return false; }
! 1443 return true;
! 1444 }
1445 size_t hash() const override {
1446 size_t hash = 1926102241188748124ULL;
1447 hash ^= std::hash<size_t>()(arg_count());
1448 for (size_t it = 0; it < arg_count(); it++) {Lines 4778-4788 4778 }
4779 void* jitir_build_float_to_int_s(void* builder, void* a, uint32_t type) {
4780 return (void*)((::metajit::TraceBuilder*)builder)->build_float_to_int_s((Value*) a, (Type) type);
4781 }
! 4782 void* jitir_build_ptr_to_int(void* builder, void* a, uint32_t type) {
! 4783 return (void*)((::metajit::TraceBuilder*)builder)->build_ptr_to_int((Value*) a, (Type) type);
! 4784 }
4785 void* jitir_build_load(void* builder, void* ptr, uint32_t type, uint32_t flags, uint32_t aliasing, uint64_t offset) {
4786 return (void*)((::metajit::TraceBuilder*)builder)->build_load((Value*) ptr, (Type) type, (LoadFlags) flags, (AliasingGroup) aliasing, (uint64_t) offset);
4787 }
4788 void* jitir_build_store(void* builder, void* ptr, void* value, uint32_t aliasing, uint64_t offset) {Lines 5234-5248 5234 Type type = read_type();
5235 return _builder.build_float_to_int_s(a, type)
5236 ;
5237 } else if (opcode == "PtrToInt") {
! 5238 Value* a = read_value_arg();
! 5239 expect_char(','); skip_whitespace();
! 5240 expect_word("type");
! 5241 expect_char('=');
! 5242 Type type = read_type();
! 5243 return _builder.build_ptr_to_int(a, type)
! 5244 ;
5245 } else if (opcode == "Load") {
5246 Value* ptr = read_value_arg();
5247 expect_char(','); skip_whitespace();
5248 expect_word("type");Lines 6346-6357 6346 return b;
6347 }
6348 }
6349
! 6350 Bits ptr_to_int(Type to) const {
! 6351 assert(type == Type::Ptr);
! 6352 return Bits::constant(to, value);
! 6353 }
6354
6355 void store(uint8_t* ptr) {
6356 assert(!is_poison);
6357 switch (type_size(type)) {Lines 6517-6526 6517 } else if (dynmatch(ResizeXInst, resize_x, _inst)) {
6518 Bits a = at(resize_x->arg(0));
6519 _values[_inst] = a.resize_x(resize_x->type());
6520 } else if (dynmatch(PtrToIntInst, ptr_to_int, _inst)) {
! 6521 Bits a = at(ptr_to_int->arg(0));
! 6522 _values[_inst] = a.ptr_to_int(ptr_to_int->type());
6523 } else if (dynmatch(FreezeInst, freeze, _inst)) {
6524 Bits a = at(freeze->arg(0));
6525 // Poison is refined to a non-poison value, we choose zero in this case
6526 if (a.is_poison) {Lines 8540-8551 8540 if (dynamic_cast<FloatToIntSInst*>(inst)) {
8541 FloatToIntSInst* clone = builder.build_float_to_int_s(clone_arg(inst->arg(0), builder, values), ((FloatToIntSInst*) inst)->type());
8542 return clone;
8543 }
! 8544 if (dynamic_cast<PtrToIntInst*>(inst)) {
! 8545 PtrToIntInst* clone = builder.build_ptr_to_int(clone_arg(inst->arg(0), builder, values), ((PtrToIntInst*) inst)->type());
! 8546 return clone;
! 8547 }
8548 if (dynamic_cast<LoadInst*>(inst)) {
8549 LoadInst* clone = builder.build_load(clone_arg(inst->arg(0), builder, values), ((LoadInst*) inst)->type(), ((LoadInst*) inst)->flags(), ((LoadInst*) inst)->aliasing(), ((LoadInst*) inst)->offset());
8550 return clone;
8551 }jitir_llvmapi.hppLines 632-648 632 assert(build_args.size() == 3);
633 llvm::Value* built = builder.CreateCall(api.build_float_to_int_s, build_args);
634 return built;
635 }
! 636 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 637 std::vector<llvm::Value*> build_args;
! 638 build_args.push_back(jitir_builder);
! 639 build_args.push_back(args[0]);
! 640 build_args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), (uint64_t)i->type(), false));
! 641 assert(build_args.size() == 3);
! 642 llvm::Value* built = builder.CreateCall(api.build_ptr_to_int, build_args);
! 643 return built;
! 644 }
645 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
646 std::vector<llvm::Value*> build_args;
647 build_args.push_back(jitir_builder);
648 build_args.push_back(args[0]); |
Coverage
Diff CoverageDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
genext.hppLines 45-54 45 if (dynmatch(LoadInst, load, inst)) {
46 if (_config.has(load->aliasing())) {
47 size_t load_size = std::max(_config.min_align, type_size(load->type()));
48 if (size % load_size != 0) {
! 49 size += load_size - (size % load_size);
! 50 }
51 size += load_size;
52 }
53 }
54 }Lines 53-62 53 }
54 }
55
56 for (Block* succ : block->successors()) {
! 57 max_entry_sizes[succ] = std::max(max_entry_sizes[succ], size);
! 58 }
59
60 _max_write_size = std::max(_max_write_size, size);
61 }Lines 84-94 84 AddRecord(Section* section, Config config):
85 Pass(section),
86 _section(section),
87 _builder(section),
! 88 _config(config) {
89
! 90 find_max_write_size();
91 apply();
92 }
93
94 AddRecord(Section* section, size_t* max_write_size, Config config):Lines 122-130 122
123 return aligned_ptr;
124 }
125
! 126 size_t max_write_size() const { return _max_write_size; }
127 };
128
129 // Codegen for the generating extension uses topological sorting.
130 // Cycles are broken by selecting an overapproximation.Lines 563-578 563 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
564 Value* built = builder.build_call(syms.build_float_to_int_s, Type::Ptr, build_args);
565 return built;
566 }
! 567 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 568 std::vector<Value*> build_args;
! 569 build_args.push_back(jitir_builder);
! 570 build_args.push_back(args[0]);
! 571 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
! 572 Value* built = builder.build_call(syms.build_ptr_to_int, Type::Ptr, build_args);
! 573 return built;
! 574 }
575 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
576 std::vector<Value*> build_args;
577 build_args.push_back(jitir_builder);
578 build_args.push_back(args[0]);Lines 1424-1442 1424 for (Arg* arg : section->entry()->args()) {
1425 entry_arg_types.push_back(arg->type());
1426 }
1427 entry_arg_types.push_back(Type::Ptr);
! 1428 if (_config.record.has_value()) {
1429 entry_arg_types.push_back(Type::Ptr);
1430 }
1431 _builder.move_to_end(_builder.build_block(entry_arg_types));
1432
! 1433 size_t builder_index = _section->entry()->args().size();
! 1434 _jitir_builder = _genext_section->entry()->arg(builder_index);
! 1435 if (_config.record.has_value()) {
! 1436 _tape_ptr = _genext_section->entry()->arg(builder_index + 1);
! 1437 }
! 1438
1439 for (Block* block : *section) {
1440 std::vector<Type> arg_types;
1441 for (Arg* arg : block->args()) {
1442 arg_types.push_back(arg->type()); // valuesjitir.hppLines 1415-1448 1415 write_args(stream, is_first);
1416 if (!is_first) { stream << ", "; } else { is_first = false; }
1417 stream << Highlight::ArgName << "type=" << Highlight::None; stream << Highlight::Type << _type << Highlight::None;;
1418 }
! 1419 void write_json(std::ostream& stream) const override {
! 1420 stream << "{";
! 1421 stream << "\"kind\": ";
! 1422 stream << "\"PtrToInt\"";
! 1423 stream << ", ";
! 1424 stream << "\"args\": ";
! 1425 write_args_json(stream);
! 1426 stream << ", ";
! 1427 stream << "\"name\": ";
! 1428 stream << name();
! 1429 stream << ", ";
! 1430 stream << "\"type\": ";
! 1431 stream << "\"" << _type << "\"";
! 1432 stream << "}";
! 1433 } bool equals(const Value* other) const override {
! 1434 if (this == other) { return true; }
! 1435 if (other == nullptr) { return false; }
! 1436 if (typeid(*this) != typeid(*other)) { return false; }
! 1437 const PtrToIntInst* other_inst = (const PtrToIntInst*) other;
! 1438 if (arg_count() != other_inst->arg_count()) { return false; }
! 1439 for (size_t it = 0; it < arg_count(); it++) {
! 1440 if (arg(it) != other_inst->arg(it)) { return false; }
! 1441 }
! 1442 if (_type != other_inst->_type) { return false; }
! 1443 return true;
! 1444 }
1445 size_t hash() const override {
1446 size_t hash = 1926102241188748124ULL;
1447 hash ^= std::hash<size_t>()(arg_count());
1448 for (size_t it = 0; it < arg_count(); it++) {Lines 4778-4788 4778 }
4779 void* jitir_build_float_to_int_s(void* builder, void* a, uint32_t type) {
4780 return (void*)((::metajit::TraceBuilder*)builder)->build_float_to_int_s((Value*) a, (Type) type);
4781 }
! 4782 void* jitir_build_ptr_to_int(void* builder, void* a, uint32_t type) {
! 4783 return (void*)((::metajit::TraceBuilder*)builder)->build_ptr_to_int((Value*) a, (Type) type);
! 4784 }
4785 void* jitir_build_load(void* builder, void* ptr, uint32_t type, uint32_t flags, uint32_t aliasing, uint64_t offset) {
4786 return (void*)((::metajit::TraceBuilder*)builder)->build_load((Value*) ptr, (Type) type, (LoadFlags) flags, (AliasingGroup) aliasing, (uint64_t) offset);
4787 }
4788 void* jitir_build_store(void* builder, void* ptr, void* value, uint32_t aliasing, uint64_t offset) {Lines 5234-5248 5234 Type type = read_type();
5235 return _builder.build_float_to_int_s(a, type)
5236 ;
5237 } else if (opcode == "PtrToInt") {
! 5238 Value* a = read_value_arg();
! 5239 expect_char(','); skip_whitespace();
! 5240 expect_word("type");
! 5241 expect_char('=');
! 5242 Type type = read_type();
! 5243 return _builder.build_ptr_to_int(a, type)
! 5244 ;
5245 } else if (opcode == "Load") {
5246 Value* ptr = read_value_arg();
5247 expect_char(','); skip_whitespace();
5248 expect_word("type");Lines 6346-6357 6346 return b;
6347 }
6348 }
6349
! 6350 Bits ptr_to_int(Type to) const {
! 6351 assert(type == Type::Ptr);
! 6352 return Bits::constant(to, value);
! 6353 }
6354
6355 void store(uint8_t* ptr) {
6356 assert(!is_poison);
6357 switch (type_size(type)) {Lines 6517-6526 6517 } else if (dynmatch(ResizeXInst, resize_x, _inst)) {
6518 Bits a = at(resize_x->arg(0));
6519 _values[_inst] = a.resize_x(resize_x->type());
6520 } else if (dynmatch(PtrToIntInst, ptr_to_int, _inst)) {
! 6521 Bits a = at(ptr_to_int->arg(0));
! 6522 _values[_inst] = a.ptr_to_int(ptr_to_int->type());
6523 } else if (dynmatch(FreezeInst, freeze, _inst)) {
6524 Bits a = at(freeze->arg(0));
6525 // Poison is refined to a non-poison value, we choose zero in this case
6526 if (a.is_poison) {Lines 8540-8551 8540 if (dynamic_cast<FloatToIntSInst*>(inst)) {
8541 FloatToIntSInst* clone = builder.build_float_to_int_s(clone_arg(inst->arg(0), builder, values), ((FloatToIntSInst*) inst)->type());
8542 return clone;
8543 }
! 8544 if (dynamic_cast<PtrToIntInst*>(inst)) {
! 8545 PtrToIntInst* clone = builder.build_ptr_to_int(clone_arg(inst->arg(0), builder, values), ((PtrToIntInst*) inst)->type());
! 8546 return clone;
! 8547 }
8548 if (dynamic_cast<LoadInst*>(inst)) {
8549 LoadInst* clone = builder.build_load(clone_arg(inst->arg(0), builder, values), ((LoadInst*) inst)->type(), ((LoadInst*) inst)->flags(), ((LoadInst*) inst)->aliasing(), ((LoadInst*) inst)->offset());
8550 return clone;
8551 }jitir_llvmapi.hppLines 632-648 632 assert(build_args.size() == 3);
633 llvm::Value* built = builder.CreateCall(api.build_float_to_int_s, build_args);
634 return built;
635 }
! 636 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 637 std::vector<llvm::Value*> build_args;
! 638 build_args.push_back(jitir_builder);
! 639 build_args.push_back(args[0]);
! 640 build_args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), (uint64_t)i->type(), false));
! 641 assert(build_args.size() == 3);
! 642 llvm::Value* built = builder.CreateCall(api.build_ptr_to_int, build_args);
! 643 return built;
! 644 }
645 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
646 std::vector<llvm::Value*> build_args;
647 build_args.push_back(jitir_builder);
648 build_args.push_back(args[0]); |
Coverage
Diff CoverageDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
genext.hppLines 46-55 46 if (dynmatch(LoadInst, load, inst)) {
47 if (_config.has(load->aliasing())) {
48 size_t load_size = std::max(_config.min_align, type_size(load->type()));
49 if (size % load_size != 0) {
! 50 size += load_size - (size % load_size);
! 51 }
52 size += load_size;
53 max_load_size = std::max(max_load_size, load_size);
54 }
55 }Lines 55-64 55 }
56 }
57
58 for (Block* succ : block->successors()) {
! 59 max_entry_sizes[succ] = std::max(max_entry_sizes[succ], size);
! 60 }
61
62 _max_write_size = std::max(_max_write_size, size);
63 }Lines 87-97 87 AddRecord(Section* section, Config config):
88 Pass(section),
89 _section(section),
90 _builder(section),
! 91 _config(config) {
92
! 93 find_max_write_size();
94 apply();
95 }
96
97 AddRecord(Section* section, size_t* max_write_size, Config config):Lines 125-133 125
126 return aligned_ptr;
127 }
128
! 129 size_t max_write_size() const { return _max_write_size; }
130 };
131
132 // Codegen for the generating extension uses topological sorting.
133 // Cycles are broken by selecting an overapproximation.Lines 566-581 566 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
567 Value* built = builder.build_call(syms.build_float_to_int_s, Type::Ptr, build_args);
568 return built;
569 }
! 570 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 571 std::vector<Value*> build_args;
! 572 build_args.push_back(jitir_builder);
! 573 build_args.push_back(args[0]);
! 574 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
! 575 Value* built = builder.build_call(syms.build_ptr_to_int, Type::Ptr, build_args);
! 576 return built;
! 577 }
578 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
579 std::vector<Value*> build_args;
580 build_args.push_back(jitir_builder);
581 build_args.push_back(args[0]);Lines 1427-1445 1427 for (Arg* arg : section->entry()->args()) {
1428 entry_arg_types.push_back(arg->type());
1429 }
1430 entry_arg_types.push_back(Type::Ptr);
! 1431 if (_config.record.has_value()) {
1432 entry_arg_types.push_back(Type::Ptr);
1433 }
1434 _builder.move_to_end(_builder.build_block(entry_arg_types));
1435
! 1436 size_t builder_index = _section->entry()->args().size();
! 1437 _jitir_builder = _genext_section->entry()->arg(builder_index);
! 1438 if (_config.record.has_value()) {
! 1439 _tape_ptr = _genext_section->entry()->arg(builder_index + 1);
! 1440 }
! 1441
1442 for (Block* block : *section) {
1443 std::vector<Type> arg_types;
1444 for (Arg* arg : block->args()) {
1445 arg_types.push_back(arg->type()); // valuesjitir.hppLines 1415-1448 1415 write_args(stream, is_first);
1416 if (!is_first) { stream << ", "; } else { is_first = false; }
1417 stream << Highlight::ArgName << "type=" << Highlight::None; stream << Highlight::Type << _type << Highlight::None;;
1418 }
! 1419 void write_json(std::ostream& stream) const override {
! 1420 stream << "{";
! 1421 stream << "\"kind\": ";
! 1422 stream << "\"PtrToInt\"";
! 1423 stream << ", ";
! 1424 stream << "\"args\": ";
! 1425 write_args_json(stream);
! 1426 stream << ", ";
! 1427 stream << "\"name\": ";
! 1428 stream << name();
! 1429 stream << ", ";
! 1430 stream << "\"type\": ";
! 1431 stream << "\"" << _type << "\"";
! 1432 stream << "}";
! 1433 } bool equals(const Value* other) const override {
! 1434 if (this == other) { return true; }
! 1435 if (other == nullptr) { return false; }
! 1436 if (typeid(*this) != typeid(*other)) { return false; }
! 1437 const PtrToIntInst* other_inst = (const PtrToIntInst*) other;
! 1438 if (arg_count() != other_inst->arg_count()) { return false; }
! 1439 for (size_t it = 0; it < arg_count(); it++) {
! 1440 if (arg(it) != other_inst->arg(it)) { return false; }
! 1441 }
! 1442 if (_type != other_inst->_type) { return false; }
! 1443 return true;
! 1444 }
1445 size_t hash() const override {
1446 size_t hash = 1926102241188748124ULL;
1447 hash ^= std::hash<size_t>()(arg_count());
1448 for (size_t it = 0; it < arg_count(); it++) {Lines 4778-4788 4778 }
4779 void* jitir_build_float_to_int_s(void* builder, void* a, uint32_t type) {
4780 return (void*)((::metajit::TraceBuilder*)builder)->build_float_to_int_s((Value*) a, (Type) type);
4781 }
! 4782 void* jitir_build_ptr_to_int(void* builder, void* a, uint32_t type) {
! 4783 return (void*)((::metajit::TraceBuilder*)builder)->build_ptr_to_int((Value*) a, (Type) type);
! 4784 }
4785 void* jitir_build_load(void* builder, void* ptr, uint32_t type, uint32_t flags, uint32_t aliasing, uint64_t offset) {
4786 return (void*)((::metajit::TraceBuilder*)builder)->build_load((Value*) ptr, (Type) type, (LoadFlags) flags, (AliasingGroup) aliasing, (uint64_t) offset);
4787 }
4788 void* jitir_build_store(void* builder, void* ptr, void* value, uint32_t aliasing, uint64_t offset) {Lines 5234-5248 5234 Type type = read_type();
5235 return _builder.build_float_to_int_s(a, type)
5236 ;
5237 } else if (opcode == "PtrToInt") {
! 5238 Value* a = read_value_arg();
! 5239 expect_char(','); skip_whitespace();
! 5240 expect_word("type");
! 5241 expect_char('=');
! 5242 Type type = read_type();
! 5243 return _builder.build_ptr_to_int(a, type)
! 5244 ;
5245 } else if (opcode == "Load") {
5246 Value* ptr = read_value_arg();
5247 expect_char(','); skip_whitespace();
5248 expect_word("type");Lines 6346-6357 6346 return b;
6347 }
6348 }
6349
! 6350 Bits ptr_to_int(Type to) const {
! 6351 assert(type == Type::Ptr);
! 6352 return Bits::constant(to, value);
! 6353 }
6354
6355 void store(uint8_t* ptr) {
6356 assert(!is_poison);
6357 switch (type_size(type)) {Lines 6517-6526 6517 } else if (dynmatch(ResizeXInst, resize_x, _inst)) {
6518 Bits a = at(resize_x->arg(0));
6519 _values[_inst] = a.resize_x(resize_x->type());
6520 } else if (dynmatch(PtrToIntInst, ptr_to_int, _inst)) {
! 6521 Bits a = at(ptr_to_int->arg(0));
! 6522 _values[_inst] = a.ptr_to_int(ptr_to_int->type());
6523 } else if (dynmatch(FreezeInst, freeze, _inst)) {
6524 Bits a = at(freeze->arg(0));
6525 // Poison is refined to a non-poison value, we choose zero in this case
6526 if (a.is_poison) {Lines 8540-8551 8540 if (dynamic_cast<FloatToIntSInst*>(inst)) {
8541 FloatToIntSInst* clone = builder.build_float_to_int_s(clone_arg(inst->arg(0), builder, values), ((FloatToIntSInst*) inst)->type());
8542 return clone;
8543 }
! 8544 if (dynamic_cast<PtrToIntInst*>(inst)) {
! 8545 PtrToIntInst* clone = builder.build_ptr_to_int(clone_arg(inst->arg(0), builder, values), ((PtrToIntInst*) inst)->type());
! 8546 return clone;
! 8547 }
8548 if (dynamic_cast<LoadInst*>(inst)) {
8549 LoadInst* clone = builder.build_load(clone_arg(inst->arg(0), builder, values), ((LoadInst*) inst)->type(), ((LoadInst*) inst)->flags(), ((LoadInst*) inst)->aliasing(), ((LoadInst*) inst)->offset());
8550 return clone;
8551 }jitir_llvmapi.hppLines 632-648 632 assert(build_args.size() == 3);
633 llvm::Value* built = builder.CreateCall(api.build_float_to_int_s, build_args);
634 return built;
635 }
! 636 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 637 std::vector<llvm::Value*> build_args;
! 638 build_args.push_back(jitir_builder);
! 639 build_args.push_back(args[0]);
! 640 build_args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), (uint64_t)i->type(), false));
! 641 assert(build_args.size() == 3);
! 642 llvm::Value* built = builder.CreateCall(api.build_ptr_to_int, build_args);
! 643 return built;
! 644 }
645 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
646 std::vector<llvm::Value*> build_args;
647 build_args.push_back(jitir_builder);
648 build_args.push_back(args[0]); |
Coverage
Diff CoverageDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
genext.hppLines 46-55 46 if (dynmatch(LoadInst, load, inst)) {
47 if (_config.has(load->aliasing())) {
48 size_t load_size = std::max(_config.min_align, type_size(load->type()));
49 if (size % load_size != 0) {
! 50 size += load_size - (size % load_size);
! 51 }
52 size += load_size;
53 max_load_size = std::max(max_load_size, load_size);
54 }
55 }Lines 55-64 55 }
56 }
57
58 for (Block* succ : block->successors()) {
! 59 max_entry_sizes[succ] = std::max(max_entry_sizes[succ], size);
! 60 }
61
62 _max_write_size = std::max(_max_write_size, size);
63 }Lines 87-97 87 AddRecord(Section* section, Config config):
88 Pass(section),
89 _section(section),
90 _builder(section),
! 91 _config(config) {
92
! 93 find_max_write_size();
94 apply();
95 }
96
97 AddRecord(Section* section, size_t* max_write_size, Config config):Lines 125-133 125
126 return aligned_ptr;
127 }
128
! 129 size_t max_write_size() const { return _max_write_size; }
130 };
131
132 // Codegen for the generating extension uses topological sorting.
133 // Cycles are broken by selecting an overapproximation.Lines 566-581 566 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
567 Value* built = builder.build_call(syms.build_float_to_int_s, Type::Ptr, build_args);
568 return built;
569 }
! 570 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 571 std::vector<Value*> build_args;
! 572 build_args.push_back(jitir_builder);
! 573 build_args.push_back(args[0]);
! 574 build_args.push_back(builder.build_const(Type::Int32, (uint64_t)i->type()));
! 575 Value* built = builder.build_call(syms.build_ptr_to_int, Type::Ptr, build_args);
! 576 return built;
! 577 }
578 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
579 std::vector<Value*> build_args;
580 build_args.push_back(jitir_builder);
581 build_args.push_back(args[0]);Lines 1427-1445 1427 for (Arg* arg : section->entry()->args()) {
1428 entry_arg_types.push_back(arg->type());
1429 }
1430 entry_arg_types.push_back(Type::Ptr);
! 1431 if (_config.record.has_value()) {
1432 entry_arg_types.push_back(Type::Ptr);
1433 }
1434 _builder.move_to_end(_builder.build_block(entry_arg_types));
1435
! 1436 size_t builder_index = _section->entry()->args().size();
! 1437 _jitir_builder = _genext_section->entry()->arg(builder_index);
! 1438 if (_config.record.has_value()) {
! 1439 _tape_ptr = _genext_section->entry()->arg(builder_index + 1);
! 1440 }
! 1441
1442 for (Block* block : *section) {
1443 std::vector<Type> arg_types;
1444 for (Arg* arg : block->args()) {
1445 arg_types.push_back(arg->type()); // valuesjitir.hppLines 1415-1448 1415 write_args(stream, is_first);
1416 if (!is_first) { stream << ", "; } else { is_first = false; }
1417 stream << Highlight::ArgName << "type=" << Highlight::None; stream << Highlight::Type << _type << Highlight::None;;
1418 }
! 1419 void write_json(std::ostream& stream) const override {
! 1420 stream << "{";
! 1421 stream << "\"kind\": ";
! 1422 stream << "\"PtrToInt\"";
! 1423 stream << ", ";
! 1424 stream << "\"args\": ";
! 1425 write_args_json(stream);
! 1426 stream << ", ";
! 1427 stream << "\"name\": ";
! 1428 stream << name();
! 1429 stream << ", ";
! 1430 stream << "\"type\": ";
! 1431 stream << "\"" << _type << "\"";
! 1432 stream << "}";
! 1433 } bool equals(const Value* other) const override {
! 1434 if (this == other) { return true; }
! 1435 if (other == nullptr) { return false; }
! 1436 if (typeid(*this) != typeid(*other)) { return false; }
! 1437 const PtrToIntInst* other_inst = (const PtrToIntInst*) other;
! 1438 if (arg_count() != other_inst->arg_count()) { return false; }
! 1439 for (size_t it = 0; it < arg_count(); it++) {
! 1440 if (arg(it) != other_inst->arg(it)) { return false; }
! 1441 }
! 1442 if (_type != other_inst->_type) { return false; }
! 1443 return true;
! 1444 }
1445 size_t hash() const override {
1446 size_t hash = 1926102241188748124ULL;
1447 hash ^= std::hash<size_t>()(arg_count());
1448 for (size_t it = 0; it < arg_count(); it++) {Lines 4778-4788 4778 }
4779 void* jitir_build_float_to_int_s(void* builder, void* a, uint32_t type) {
4780 return (void*)((::metajit::TraceBuilder*)builder)->build_float_to_int_s((Value*) a, (Type) type);
4781 }
! 4782 void* jitir_build_ptr_to_int(void* builder, void* a, uint32_t type) {
! 4783 return (void*)((::metajit::TraceBuilder*)builder)->build_ptr_to_int((Value*) a, (Type) type);
! 4784 }
4785 void* jitir_build_load(void* builder, void* ptr, uint32_t type, uint32_t flags, uint32_t aliasing, uint64_t offset) {
4786 return (void*)((::metajit::TraceBuilder*)builder)->build_load((Value*) ptr, (Type) type, (LoadFlags) flags, (AliasingGroup) aliasing, (uint64_t) offset);
4787 }
4788 void* jitir_build_store(void* builder, void* ptr, void* value, uint32_t aliasing, uint64_t offset) {Lines 5234-5248 5234 Type type = read_type();
5235 return _builder.build_float_to_int_s(a, type)
5236 ;
5237 } else if (opcode == "PtrToInt") {
! 5238 Value* a = read_value_arg();
! 5239 expect_char(','); skip_whitespace();
! 5240 expect_word("type");
! 5241 expect_char('=');
! 5242 Type type = read_type();
! 5243 return _builder.build_ptr_to_int(a, type)
! 5244 ;
5245 } else if (opcode == "Load") {
5246 Value* ptr = read_value_arg();
5247 expect_char(','); skip_whitespace();
5248 expect_word("type");Lines 6346-6357 6346 return b;
6347 }
6348 }
6349
! 6350 Bits ptr_to_int(Type to) const {
! 6351 assert(type == Type::Ptr);
! 6352 return Bits::constant(to, value);
! 6353 }
6354
6355 void store(uint8_t* ptr) {
6356 assert(!is_poison);
6357 switch (type_size(type)) {Lines 6517-6526 6517 } else if (dynmatch(ResizeXInst, resize_x, _inst)) {
6518 Bits a = at(resize_x->arg(0));
6519 _values[_inst] = a.resize_x(resize_x->type());
6520 } else if (dynmatch(PtrToIntInst, ptr_to_int, _inst)) {
! 6521 Bits a = at(ptr_to_int->arg(0));
! 6522 _values[_inst] = a.ptr_to_int(ptr_to_int->type());
6523 } else if (dynmatch(FreezeInst, freeze, _inst)) {
6524 Bits a = at(freeze->arg(0));
6525 // Poison is refined to a non-poison value, we choose zero in this case
6526 if (a.is_poison) {Lines 6562-6570 6562
6563 #undef binop
6564
6565 else {
! 6566 assert(false && "Unsupported instruction in interpreter");
6567 }
6568
6569 _inst = _inst->next();
6570 return Event::None;Lines 8542-8553 8542 if (dynamic_cast<FloatToIntSInst*>(inst)) {
8543 FloatToIntSInst* clone = builder.build_float_to_int_s(clone_arg(inst->arg(0), builder, values), ((FloatToIntSInst*) inst)->type());
8544 return clone;
8545 }
! 8546 if (dynamic_cast<PtrToIntInst*>(inst)) {
! 8547 PtrToIntInst* clone = builder.build_ptr_to_int(clone_arg(inst->arg(0), builder, values), ((PtrToIntInst*) inst)->type());
! 8548 return clone;
! 8549 }
8550 if (dynamic_cast<LoadInst*>(inst)) {
8551 LoadInst* clone = builder.build_load(clone_arg(inst->arg(0), builder, values), ((LoadInst*) inst)->type(), ((LoadInst*) inst)->flags(), ((LoadInst*) inst)->aliasing(), ((LoadInst*) inst)->offset());
8552 return clone;
8553 }jitir_llvmapi.hppLines 632-648 632 assert(build_args.size() == 3);
633 llvm::Value* built = builder.CreateCall(api.build_float_to_int_s, build_args);
634 return built;
635 }
! 636 if (PtrToIntInst* i = dynamic_cast<PtrToIntInst*>(inst)) {
! 637 std::vector<llvm::Value*> build_args;
! 638 build_args.push_back(jitir_builder);
! 639 build_args.push_back(args[0]);
! 640 build_args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), (uint64_t)i->type(), false));
! 641 assert(build_args.size() == 3);
! 642 llvm::Value* built = builder.CreateCall(api.build_ptr_to_int, build_args);
! 643 return built;
! 644 }
645 if (LoadInst* i = dynamic_cast<LoadInst*>(inst)) {
646 std::vector<llvm::Value*> build_args;
647 build_args.push_back(jitir_builder);
648 build_args.push_back(args[0]); |
No description provided.