- Notifications
You must be signed in to change notification settings - Fork 818
Closed
Description
Below is a simple(ish) sudoku solver.
emcc a.cpp -o a.html
produces a working program. If I then add wasm-opt a.wasm --spill-pointers -o a.wasm
I get Uncaught RuntimeError: indirect call to null
.
I started trying to reduce the program, but found many changes would fix the program, as (I think) the compiler is clever enough to optimise away the need for spilling pointers.
I could try to reduce the example further if that would be useful -- hopefully someone who knows more about wasm-opt
might be able to figure out what's going on? --spill-pointers was re-added recently in #4570
I'm finding --spill-pointers fails on most large programs, this was one I found that was (I hope) small enough to be easily looked at, but big enough to fail.
// In this code we represent sudokus as a vector<vector<int> >, // where the value 0 means 'not yet known'. #include <vector> #include <iostream> #include <ostream> using namespace std; vector<int> check_sudoku_vector(vector<int> v); vector<vector<int> > check_sudoku(vector<vector<int> > sudoku); vector<vector<int> > read_sudoku(); void print_sudoku(vector<vector<int> > sudoku); void solve_sudoku(vector<vector<int> > sudoku); int main(void) { vector<vector<int> > v = read_sudoku(); solve_sudoku(v); } // Checks a vector does not contain any value twice // Attempts to fill in values where possible. // As a hack, we return the empty vector if there are // any repeated values. // This tries to fill in the blank value if it can. vector<int> check_sudoku_vector(vector<int> v) { // We need 10 because we want 1..9, and 0 for empty. vector<int> count(10); // Count up the occurrences of each value for(int i = 0; i < 9; ++i) count[v[i]]++; // Check if any value occurs twice for(int i = 1; i <= 9; ++i) { if(count[i] > 1) { // Some value occurs twice! vector<int> empty; return empty; } } if(count[0] == 1) { // There is exactly one value to fill in! int empty_place = -1; for(int i = 0; i < 9; ++i) { if(v[i] == 0) empty_place = i; } for(int i = 1; i <= 9; ++i) { if(count[i] == 0) { v[empty_place] = i; return v; } } } return v; } // Tries to fill in the sudoku. // returns the empty vector if a flaw is found. // Takes the return value of check_sudoku_vector and puts it back // in the sudoku. This might be a waste of time, or might fill in a value. // There are obviously other ways check_sudoku_vector could respond back, // this is just one example. vector<vector<int> > check_sudoku(vector<vector<int> > sudoku) { vector<vector<int> > empty_vector; // First check rows for(int i = 0; i < 9; ++i) { vector<int> v = check_sudoku_vector(sudoku[i]); if(v.empty()) { return empty_vector; } sudoku[i] = v; } // then columns for(int i = 0; i < 9; ++i) { vector<int> column; for(int j = 0; j < 9; ++j) column.push_back(sudoku[j][i]); vector<int> v = check_sudoku_vector(column); if(v.empty()) return empty_vector; for(int j = 0; j < 9; ++j) sudoku[j][i] = v[j]; } // then boxes. Notice we do some interesting // loop indexing! for(int i = 0; i < 9; i+=3) { for(int j = 0; j < 9; j+=3) { vector<int> box; for(int a = i; a < i + 3; ++a) for(int b = j; b < j + 3; ++b) box.push_back(sudoku[a][b]); vector<int> v = check_sudoku_vector(box); if(v.empty()) return empty_vector; // Put the values back in! int counter = 0; for(int a = i; a < i + 3; ++a) for(int b = j; b < j + 3; ++b) { sudoku[a][b] = v[counter]; counter++; } } } // The sudoku is fine! return sudoku; } vector<vector<int> > read_sudoku() { vector<vector<int> > v; for(int i = 0; i < 9; ++i) { vector<int> row; for(int j = 0; j < 9; ++j) { int val = 0; row.push_back(val); } v.push_back(row); } return v; } void print_sudoku(vector<vector<int> > sudoku) { for(int i = 0; i < 9; ++i) { for(int j = 0; j < 9; ++j) { cout << sudoku[i][j] << " "; } cout << endl; } cout << endl; exit(0); } int counter = 0; void solve_sudoku(vector<vector<int> > sudoku) { counter++; vector<vector<int> > sudoku_copy = check_sudoku(sudoku); // This means the sudoku is unsolvable if(sudoku_copy.empty()) return; // let's keep looping around until check_sudoku stops filling // in values! while(sudoku_copy != sudoku) { sudoku = sudoku_copy; sudoku_copy = check_sudoku(sudoku); if(sudoku_copy.empty()) return; } for(int i = 0; i < 9; ++i) { for(int j = 0; j < 9; ++j) { if(sudoku[i][j] == 0) { // We have found a value to branch on! for(int k = 1; k <= 9; ++k) { sudoku[i][j] = k; solve_sudoku(sudoku); } // No solution found here! return; } } } // if we get here, then the solution is complete! print_sudoku(sudoku); std::cout << "Search: " << counter << std::endl; }
Metadata
Metadata
Assignees
Labels
No labels