| 2928 | } // anonymous namespace |
| 2929 | |
| 2930 | spv_result_t Diff(opt::IRContext* src, opt::IRContext* dst, std::ostream& out, |
| 2931 | Options options) { |
| 2932 | // High level algorithm: |
| 2933 | // |
| 2934 | // - Some sections of SPIR-V don't deal with ids; instructions in those |
| 2935 | // sections are matched identically. For example OpCapability instructions. |
| 2936 | // - Some sections produce ids, and they can be trivially matched by their |
| 2937 | // parameters. For example OpExtInstImport instructions. |
| 2938 | // - Some sections annotate ids. These are matched at the end, after the ids |
| 2939 | // themselves are matched. For example OpName or OpDecorate instructions. |
| 2940 | // - Some sections produce ids that depend on other ids and they can be |
| 2941 | // recursively matched. For example OpType* instructions. |
| 2942 | // - Some sections produce ids that are not trivially matched. For these ids, |
| 2943 | // the debug info is used when possible, or a best guess (such as through |
| 2944 | // decorations) is used. For example OpVariable instructions. |
| 2945 | // - Matching functions is done with multiple attempts: |
| 2946 | // * Functions with identical debug names are matched if there are no |
| 2947 | // overloads. |
| 2948 | // * Otherwise, functions with identical debug names and types are matched. |
| 2949 | // * The rest of the functions are best-effort matched, first in groups of |
| 2950 | // identical type, then any with any. |
| 2951 | // * The best-effort matching takes the diff of every pair of functions in |
| 2952 | // a group and selects the top matches that also meet a similarity |
| 2953 | // index. |
| 2954 | // * Once a pair of functions are matched, the fuzzy diff of the |
| 2955 | // instructions is used to match the instructions in the function body. |
| 2956 | // The fuzzy diff makes sure that sufficiently similar instructions are |
| 2957 | // matched and that yet-to-be-matched result ids don't result in a larger |
| 2958 | // diff. |
| 2959 | // |
| 2960 | // Once the instructions are matched between the src and dst SPIR-V, the src |
| 2961 | // is traversed and its disassembly is output. In the process, any unmatched |
| 2962 | // instruction is prefixed with -, and any unmatched instruction in dst in the |
| 2963 | // same section is output prefixed with +. To avoid confusion, the |
| 2964 | // instructions in dst are output with matching ids in src so the output |
| 2965 | // assembly is consistent. |
| 2966 | |
| 2967 | Differ differ(src, dst, out, options); |
| 2968 | |
| 2969 | // First, match instructions between the different non-annotation sections of |
| 2970 | // the SPIR-V. |
| 2971 | differ.MatchCapabilities(); |
| 2972 | differ.MatchExtensions(); |
| 2973 | differ.MatchExtInstImportIds(); |
| 2974 | differ.MatchMemoryModel(); |
| 2975 | differ.MatchEntryPointIds(); |
| 2976 | differ.MatchExecutionModes(); |
| 2977 | differ.MatchTypeForwardPointers(); |
| 2978 | differ.MatchTypeIds(); |
| 2979 | differ.MatchConstants(); |
| 2980 | differ.MatchVariableIds(); |
| 2981 | differ.MatchFunctions(); |
| 2982 | |
| 2983 | // Match instructions that annotate previously-matched ids. |
| 2984 | differ.MatchDebugs1(); |
| 2985 | differ.MatchDebugs2(); |
| 2986 | differ.MatchDebugs3(); |
| 2987 | differ.MatchExtInstDebugInfo(); |