-
Notifications
You must be signed in to change notification settings - Fork 787
Allows parsing debug information in the .S files #544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -101,6 +101,10 @@ class S2WasmBuilder { | |
abort(); \ | ||
} | ||
|
||
bool peek(const char *pattern) { | ||
return strncmp(s, pattern, strlen(pattern)) == 0; | ||
} | ||
|
||
// match and skip the pattern, if matched | ||
bool match(const char *pattern) { | ||
size_t size = strlen(pattern); | ||
|
@@ -396,17 +400,19 @@ class S2WasmBuilder { | |
else if (match("ident")) {} | ||
else if (match("section")) parseToplevelSection(); | ||
else if (match("align") || match("p2align")) s = strchr(s, '\n'); | ||
else if (match("Lfunc_end")) { | ||
// skip the next line, which has a .size we can ignore | ||
s = strstr(s, ".size"); | ||
s = strchr(s, '\n'); | ||
} else if (match("globl")) parseGlobl(); | ||
else if (match("globl")) parseGlobl(); | ||
else abort_on("process"); | ||
} | ||
} | ||
|
||
void parseToplevelSection() { | ||
auto section = getCommaSeparated(); | ||
// Skipping .debug_ sections | ||
if (!strncmp(section.c_str(), ".debug_", strlen(".debug_"))) { | ||
const char *next = strstr(s, ".section"); | ||
s = !next ? s + strlen(s) : next; | ||
return; | ||
} | ||
// Initializers are anything in a section whose name begins with .init_array | ||
if (!strncmp(section.c_str(), ".init_array", strlen(".init_array") - 1)) { | ||
parseInitializer(); | ||
|
@@ -449,15 +455,24 @@ class S2WasmBuilder { | |
} | ||
|
||
void parseFile() { | ||
assert(*s == '"'); | ||
if (*s != '"') { | ||
// TODO: optimize, see recordFile below | ||
size_t fileId = getInt(); | ||
skipWhitespace(); | ||
auto quoted = getQuoted(); | ||
WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted | ||
s = strchr(s, '\n'); | ||
return; | ||
} | ||
// '.file' without first index argument points to bc-file | ||
s++; | ||
std::string filename; | ||
while (*s != '"') { | ||
filename += *s; | ||
s++; | ||
} | ||
s++; | ||
// TODO: use the filename? | ||
WASM_UNUSED(filename); // TODO: use the filename | ||
} | ||
|
||
void parseGlobl() { | ||
|
@@ -485,11 +500,31 @@ class S2WasmBuilder { | |
|
||
mustMatch(":"); | ||
|
||
if (match(".Lfunc_begin")) { | ||
auto recordFile = [&]() { | ||
if (debug) dump("file"); | ||
size_t fileId = getInt(); | ||
skipWhitespace(); | ||
auto quoted = getQuoted(); | ||
WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted | ||
s = strchr(s, '\n'); | ||
s++; | ||
}; | ||
auto recordLoc = [&]() { | ||
if (debug) dump("loc"); | ||
size_t fileId = getInt(); | ||
skipWhitespace(); | ||
} | ||
size_t row = getInt(); | ||
skipWhitespace(); | ||
size_t column = getInt(); | ||
WASM_UNUSED(fileId); WASM_UNUSED(row); WASM_UNUSED(column); // TODO: use the fileId, row and column | ||
s = strchr(s, '\n'); | ||
}; | ||
auto recordLabel = [&]() { | ||
if (debug) dump("label"); | ||
Name label = getStrToSep(); | ||
// TODO: track and create map of labels and their ranges for our AST | ||
WASM_UNUSED(label); | ||
s = strchr(s, '\n'); | ||
}; | ||
|
||
unsigned nextId = 0; | ||
auto getNextId = [&nextId]() { | ||
|
@@ -523,6 +558,15 @@ class S2WasmBuilder { | |
skipWhitespace(); | ||
if (!match(",")) break; | ||
} | ||
} else if (match(".file")) { | ||
recordFile(); | ||
skipWhitespace(); | ||
} else if (match(".loc")) { | ||
recordLoc(); | ||
skipWhitespace(); | ||
} else if (peek(".Lfunc_begin")) { | ||
recordLabel(); | ||
skipWhitespace(); | ||
} else break; | ||
} | ||
Function* func = builder.makeFunction(name, std::move(params), resultType, std::move(vars)); | ||
|
@@ -644,6 +688,7 @@ class S2WasmBuilder { | |
auto curr = allocator->alloc<Unary>(); | ||
curr->op = op; | ||
curr->value = getInput(); | ||
curr->type = type; | ||
curr->finalize(); | ||
setOutput(curr, assign); | ||
}; | ||
|
@@ -935,8 +980,13 @@ class S2WasmBuilder { | |
} else if (match("end_block")) { | ||
bstack.back()->cast<Block>()->finalize(); | ||
bstack.pop_back(); | ||
} else if (match(".LBB")) { | ||
s = strchr(s, '\n'); | ||
} else if (peek(".LBB")) { | ||
// FIXME legacy tests: it can be leftover from "loop" or "block", but it can be a label too | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sunfishcode: what's the status of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. .Lfunc_end is still in the .s file, but is emitted after the .end_func so s2wasm doesn't consider it to be part of the function body. .LBB is still present and isn't referenced from the actual code, though it probably is referenced by debug info, which is probably why this patch needs to parse it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, thanks @sunfishcode. Ok, @yurydelendik, looks like the right approach to me in this pull. So aside from the comments I noted, lgtm. |
||
auto p = s; | ||
while (*p && *p != ':' && *p != '#' && *p != '\n') p++; | ||
if (*p == ':') { // it's a label | ||
recordLabel(); | ||
} else s = strchr(s, '\n'); | ||
} else if (match("loop")) { | ||
auto curr = allocator->alloc<Loop>(); | ||
addToBlock(curr); | ||
|
@@ -997,8 +1047,30 @@ class S2WasmBuilder { | |
makeHost(CurrentMemory); | ||
} else if (match("grow_memory")) { | ||
makeHost1(GrowMemory); | ||
} else if (peek(".Lfunc_end")) { | ||
// TODO fix handwritten tests to have .endfunc | ||
recordLabel(); | ||
// skip the next line, which has a .size we can ignore | ||
s = strstr(s, ".size"); | ||
s = strchr(s, '\n'); | ||
break; // the function is done | ||
} else if (match(".endfunc")) { | ||
skipWhitespace(); | ||
// getting all labels at the end of function | ||
while (peek(".L") && strchr(s, ':') < strchr(s, '\n')) { | ||
recordLabel(); | ||
skipWhitespace(); | ||
} | ||
// skip the next line, which has a .size we can ignore | ||
s = strstr(s, ".size"); | ||
s = strchr(s, '\n'); | ||
break; // the function is done | ||
} else if (match(".file")) { | ||
recordFile(); | ||
} else if (match(".loc")) { | ||
recordLoc(); | ||
} else if (peek(".L") && strchr(s, ':') < strchr(s, '\n')) { | ||
recordLabel(); | ||
} else { | ||
abort_on("function element"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this wasn't obvious to me what it does, please add a comment