Skip to content
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

Use IRBuilder in the binary parser #6963

Merged
merged 139 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
8543f16
[NFC-ish] Eagerly create Functions in binary parser
tlively Sep 19, 2024
b83bec4
[NFC] Eagerly create segments when parsing datacount
tlively Sep 19, 2024
a124292
[NFC] Walk module to update names in binary parser
tlively Sep 19, 2024
8f4ca9f
skip unparsed functions when printing
tlively Sep 19, 2024
8d8eb13
update and fix test of datacount error
tlively Sep 19, 2024
945a807
Merge branch 'main' into binary-parser-eager-funcs
tlively Sep 19, 2024
4d0deb1
Merge branch 'binary-parser-eager-funcs' into binary-parser-eager-data
tlively Sep 19, 2024
70585fc
Merge branch 'binary-parser-eager-data' into binary-parser-refactor-n…
tlively Sep 19, 2024
098bd4f
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Sep 21, 2024
4d5096f
Use IRBuilder in the binary parser
tlively Sep 18, 2024
b2b011c
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Oct 21, 2024
95758e0
Merge branch 'binary-parser-refactor-name-fixup' into binary-ir-builder
tlively Oct 21, 2024
2f8f294
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Oct 25, 2024
9c91006
Merge branch 'binary-parser-refactor-name-fixup' into binary-ir-builder
tlively Oct 25, 2024
e31a2b0
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Oct 28, 2024
a39fde5
Merge branch 'binary-parser-refactor-name-fixup' into binary-ir-builder
tlively Oct 28, 2024
b8e35d2
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Nov 6, 2024
25dd297
Merge branch 'binary-parser-refactor-name-fixup' into binary-ir-builder
tlively Nov 6, 2024
54ebeb3
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Nov 7, 2024
c06e531
Merge branch 'binary-parser-refactor-name-fixup' into binary-ir-builder
tlively Nov 7, 2024
a22dd5f
Merge branch 'main' into binary-parser-refactor-name-fixup
tlively Nov 12, 2024
f2be566
Merge branch 'binary-parser-refactor-name-fixup' into binary-ir-builder
tlively Nov 12, 2024
06a2198
Consolidate printing of function signatures
tlively Nov 12, 2024
e0b992e
Read the names section first
tlively Nov 12, 2024
ff3b653
Merge branch 'binary-parser-names-first' into binary-ir-builder
tlively Nov 13, 2024
2d1d914
address comments
tlively Nov 13, 2024
24fb433
Merge branch 'binary-parser-eager-local-names' into binary-ir-builder
tlively Nov 13, 2024
33efda5
Merge branch 'main' into binary-parser-names-first
tlively Nov 13, 2024
a00a621
Merge branch 'binary-parser-eager-local-names' into binary-ir-builder
tlively Nov 13, 2024
c9436a5
Merge branch 'main' into binary-ir-builder
tlively Nov 13, 2024
68b5012
Fixup pops when necessary in IRBuilder
tlively Nov 13, 2024
6486c93
Merge branch 'ir-builder-pop-fixup' into binary-ir-builder
tlively Nov 13, 2024
6909626
generalize
tlively Nov 13, 2024
397b0a4
Merge branch 'ir-builder-pop-fixup' into binary-ir-builder
tlively Nov 13, 2024
535bd22
update stacky eh binary tests
tlively Nov 14, 2024
2506558
Merge branch 'main' into binary-ir-builder
tlively Nov 14, 2024
2a75afd
[NFC] Eagerly set local names in binary reader
tlively Nov 14, 2024
92797f1
Merge branch 'eager-local-names' into binary-ir-builder
tlively Nov 14, 2024
aa15420
update tests
tlively Nov 14, 2024
e8b6b37
wip dwarf with logging
tlively Nov 14, 2024
eb430fb
restore warning about OOB function indices
tlively Nov 14, 2024
f4d736a
Merge branch 'eager-local-names' into binary-ir-builder
tlively Nov 14, 2024
19e297e
Merge branch 'main' into binary-ir-builder
tlively Nov 14, 2024
849c992
Update lit test output
tlively Nov 14, 2024
2aa3ca5
Record binary locations for nested blocks
tlively Nov 14, 2024
1479151
Merge branch 'dwarf-nested-blocks' into binary-ir-builder
tlively Nov 14, 2024
1ddb156
Merge branch 'main' into binary-ir-builder
tlively Nov 14, 2024
e1270a8
wip
tlively Nov 14, 2024
07c6b9b
Use empty blocks instead of nops for empty scopes in IRBuilder
tlively Nov 15, 2024
5e0c0b9
update source map test
tlively Nov 15, 2024
21ef873
Reset function context when ending a function in IRBuilder
tlively Nov 15, 2024
54134fd
fix gtest
tlively Nov 15, 2024
fdeb5e4
Merge branch 'ir-builder-empty-block' into ir-builder-reset-func
tlively Nov 15, 2024
65493b8
Merge branch 'ir-builder-reset-func' into binary-ir-builder
tlively Nov 15, 2024
ab150cd
update binaryen.js tests
tlively Nov 15, 2024
7e14525
Merge branch 'ir-builder-empty-block' into ir-builder-reset-func
tlively Nov 15, 2024
7ad5bf2
Merge branch 'ir-builder-reset-func' into binary-ir-builder
tlively Nov 15, 2024
fa07c51
Add missing CHECK_ERR
tlively Nov 15, 2024
cdfe642
Merge branch 'main' into ir-builder-reset-func
tlively Nov 15, 2024
e3fd213
Merge branch 'ir-builder-reset-func' into binary-ir-builder
tlively Nov 15, 2024
6a34e42
Merge branch 'main' into binary-ir-builder
tlively Nov 15, 2024
5b16bf7
Merge branch 'main' into binary-ir-builder
tlively Nov 15, 2024
2589329
Merge branch 'main' into binary-ir-builder
tlively Nov 15, 2024
c18d60a
[NFC] Finalize blocks with explicit breakability in IRBuilder
tlively Nov 16, 2024
79a446c
Merge branch 'ir-builder-breakability' into binary-ir-builder
tlively Nov 16, 2024
3981163
Merge branch 'main' into ir-builder-breakability
tlively Nov 18, 2024
b4ce294
Merge branch 'ir-builder-name-hints' into binary-ir-builder
tlively Nov 18, 2024
5b2c76f
Use hints when generating fresh labels in IRBuilder
tlively Nov 18, 2024
a89dbc3
update tests for label name changes
tlively Nov 18, 2024
f4695a2
improve comment
tlively Nov 18, 2024
2006320
Merge branch 'ir-builder-breakability' into ir-builder-name-hints
tlively Nov 18, 2024
ecfccdb
Merge branch 'ir-builder-name-hints' into binary-ir-builder
tlively Nov 18, 2024
f98a282
Merge branch 'main' into binary-ir-builder
tlively Nov 18, 2024
a1c930c
remove debug logging
tlively Nov 19, 2024
904d6fb
remove stale comment
tlively Nov 19, 2024
2bb1a96
Merge branch 'main' into binary-ir-builder
tlively Nov 19, 2024
4557b7d
Make more Ifs unreachable
tlively Nov 20, 2024
6b51083
add test
tlively Nov 20, 2024
835b08e
update flatten
tlively Nov 20, 2024
2eea7c2
update unsubtyping
tlively Nov 20, 2024
ac9bc8e
update flatten again
tlively Nov 20, 2024
965f748
update autodrop
tlively Nov 20, 2024
351e03a
address feedback
tlively Nov 21, 2024
43d5e15
Merge branch 'main' into relax-unreachable-if
tlively Nov 21, 2024
e4a4356
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 21, 2024
24ead40
Merge branch 'main' into relax-unreachable-if
tlively Nov 21, 2024
37a74e0
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 21, 2024
6e48fdb
Merge branch 'main' into relax-unreachable-if
tlively Nov 21, 2024
265e2d8
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 21, 2024
74ee9b6
Fix printing of unreachable br_on_cast{_fail}
tlively Nov 21, 2024
801ab14
update comment
tlively Nov 21, 2024
20cd7ea
Merge branch 'print-unreachable-br-on' into relax-unreachable-if
tlively Nov 21, 2024
3d490e7
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 21, 2024
239d315
Merge branch 'main' into relax-unreachable-if
tlively Nov 22, 2024
6fd98bf
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 22, 2024
6256964
Remove AutoDrop
tlively Nov 22, 2024
749a66b
Merge branch 'main' into drop-autodrop
tlively Nov 22, 2024
71a6bad
Merge branch 'drop-autodrop' into relax-unreachable-if
tlively Nov 22, 2024
5c4fc22
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 22, 2024
55c5f55
Print castType for unreachable br_on_cast{_fail}
tlively Nov 22, 2024
ed19eac
Merge branch 'fix-br-on-print' into binary-ir-builder
tlively Nov 22, 2024
47753ed
Print unreachable loads with valid types
tlively Nov 22, 2024
0e66ad0
Merge branch 'fix-print-unreachable-load' into binary-ir-builder
tlively Nov 22, 2024
485ac7d
Do note code fold ifs with concrete arms
tlively Nov 23, 2024
deb276b
Merge branch 'main' into relax-unreachable-if
tlively Nov 23, 2024
be95b36
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 23, 2024
3173283
Merge branch 'code-folding-no-concrete' into relax-unreachable-if
tlively Nov 23, 2024
55dc9f9
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 23, 2024
ef975ee
revert obsolete changes to CodeFolding
tlively Nov 23, 2024
4cf17a6
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 23, 2024
4d94f34
Take BrOn into account in CodeFolding
tlively Nov 23, 2024
c0cc639
Merge branch 'code-folding-br-on' into relax-unreachable-if
tlively Nov 23, 2024
e36d65a
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 23, 2024
640a101
Fix memory.grow bounds and overflow checks for mem64
tlively Nov 25, 2024
2d8a8bc
Handle unoptimized branches in CodeFolding
tlively Nov 23, 2024
4ba1882
Use BranchUtils
tlively Nov 25, 2024
2a6c25b
Merge branch 'code-folding-br-on' into binary-ir-builder
tlively Nov 25, 2024
990d956
Merge branch 'mem-grow-i64-checks' into binary-ir-builder
tlively Nov 25, 2024
4076665
Merge branch 'main' into code-folding-no-concrete
tlively Nov 25, 2024
82533fb
Merge branch 'code-folding-no-concrete' into relax-unreachable-if
tlively Nov 25, 2024
0c0dca3
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 25, 2024
3bf4661
Merge branch 'main' into code-folding-no-concrete
tlively Nov 25, 2024
83ad344
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 25, 2024
2c3ddeb
Merge branch 'code-folding-no-concrete' into relax-unreachable-if
tlively Nov 25, 2024
2936897
Handle concrete values in CodeFolding
tlively Nov 26, 2024
0800007
remove redundant opt that would need refinalize
tlively Nov 26, 2024
0d9d994
update tests
tlively Nov 26, 2024
55f093f
Merge branch 'code-folding-concrete' into binary-ir-builder
tlively Nov 26, 2024
c243013
cleanup empty ifs
tlively Nov 26, 2024
3c0f5dd
Skip ifs with unreachable conditions in CodeFolding
tlively Nov 26, 2024
d400bcf
Merge branch 'main' into code-folding-concrete
tlively Nov 26, 2024
30be648
Merge branch 'code-folding-concrete' into relax-unreachable-if
tlively Nov 26, 2024
fa9fb83
Merge branch 'main' into code-folding-concrete
tlively Nov 26, 2024
6f624aa
Merge branch 'code-folding-concrete' into relax-unreachable-if
tlively Nov 26, 2024
75c7681
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 26, 2024
5d69456
Merge branch 'main' into relax-unreachable-if
tlively Nov 27, 2024
2dc8fc8
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 27, 2024
2ef8d9f
update tests
tlively Nov 27, 2024
1c22acf
Merge branch 'relax-unreachable-if' into binary-ir-builder
tlively Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ir/subtype-exprs.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
}
}
void visitIf(If* curr) {
if (curr->ifFalse) {
if (curr->ifFalse && curr->type != Type::unreachable) {
self()->noteSubtype(curr->ifTrue, curr);
self()->noteSubtype(curr->ifFalse, curr);
}
Expand Down
7 changes: 7 additions & 0 deletions src/passes/CodeFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,13 @@ struct CodeFolding
if (!curr->ifFalse) {
return;
}
if (curr->condition->type == Type::unreachable) {
// If the arms are foldable and concrete, we would be replacing an
// unreachable If with a concrete block, which may or may not be valid,
// depending on the context. Leave this for DCE rather than trying to
// handle that.
return;
}
// If both are blocks, look for a tail we can merge.
auto* left = curr->ifTrue->dynCast<Block>();
auto* right = curr->ifFalse->dynCast<Block>();
Expand Down
16 changes: 10 additions & 6 deletions src/passes/Flatten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,24 @@ struct Flatten
// arm preludes go in the arms. we must also remove an if value
auto* originalIfTrue = iff->ifTrue;
auto* originalIfFalse = iff->ifFalse;
auto type = iff->type;
auto type = iff->ifFalse ? Type::getLeastUpperBound(iff->ifTrue->type,
iff->ifFalse->type)
: Type::none;
Expression* prelude = nullptr;
if (type.isConcrete()) {
Index temp = builder.addVar(getFunction(), type);
if (iff->ifTrue->type.isConcrete()) {
iff->ifTrue = builder.makeLocalSet(temp, iff->ifTrue);
}
if (iff->ifFalse && iff->ifFalse->type.isConcrete()) {
if (iff->ifFalse->type.isConcrete()) {
iff->ifFalse = builder.makeLocalSet(temp, iff->ifFalse);
}
// the whole if (+any preludes from the condition) is now a prelude
prelude = rep;
// and we leave just a get of the value
rep = builder.makeLocalGet(temp, type);
if (curr->type.isConcrete()) {
// the whole if (+any preludes from the condition) is now a prelude
prelude = rep;
// and we leave just a get of the value
rep = builder.makeLocalGet(temp, type);
}
}
iff->ifTrue = getPreludesWithExpression(originalIfTrue, iff->ifTrue);
if (iff->ifFalse) {
Expand Down
11 changes: 9 additions & 2 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,16 @@ struct PrintExpressionContents
}
void visitIf(If* curr) {
printMedium(o, "if");
if (curr->type.isConcrete()) {
// Ifs are unreachable if their condition is unreachable, but in that case
// the arms might have some concrete type we have to account for to produce
// valid wat.
auto type = curr->type;
if (curr->condition->type == Type::unreachable && curr->ifFalse) {
type = Type::getLeastUpperBound(curr->ifTrue->type, curr->ifFalse->type);
}
if (type.isConcrete()) {
o << ' ';
printBlockType(Signature(Type::none, curr->type));
printBlockType(Signature(Type::none, type));
}
}
void visitLoop(Loop* curr) {
Expand Down
182 changes: 9 additions & 173 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "ir/module-utils.h"
#include "parsing.h"
#include "wasm-builder.h"
#include "wasm-ir-builder.h"
#include "wasm-traversal.h"
#include "wasm-validator.h"
#include "wasm.h"
Expand Down Expand Up @@ -1543,8 +1544,6 @@ class WasmBinaryReader {
Signature getSignatureByTypeIndex(Index index);
Signature getSignatureByFunctionIndex(Index index);

size_t nextLabel;

Name getNextLabel();

// We read the names section first so we know in advance what names various
Expand Down Expand Up @@ -1573,67 +1572,19 @@ class WasmBinaryReader {
void readVars();
void setLocalNames(Function& func, Index i);

Result<> readInst();

void readExports();

// The strings in the strings section (which are referred to by StringConst).
std::vector<Name> strings;
void readStrings();
Name getIndexedString();

Expression* readExpression();
void readGlobals();

struct BreakTarget {
Name name;
Type type;
BreakTarget(Name name, Type type) : name(name), type(type) {}
};
std::vector<BreakTarget> breakStack;
// the names that breaks target. this lets us know if a block has breaks to it
// or not.
std::unordered_set<Name> breakTargetNames;
// the names that delegates target.
std::unordered_set<Name> exceptionTargetNames;

std::vector<Expression*> expressionStack;

// Control flow structure parsing: these have not just the normal binary
// data for an instruction, but also some bytes later on like "end" or "else".
// We must be aware of the connection between those things, for debug info.
std::vector<Expression*> controlFlowStack;

// Called when we parse the beginning of a control flow structure.
void startControlFlow(Expression* curr);

// set when we know code is unreachable in the sense of the wasm spec: we are
// in a block and after an unreachable element. this helps parse stacky wasm
// code, which can be unsuitable for our IR when unreachable.
bool unreachableInTheWasmSense;

// set when the current code being processed will not be emitted in the
// output, which is the case when it is literally unreachable, for example,
// (block $a
// (unreachable)
// (block $b
// ;; code here is reachable in the wasm sense, even though $b as a whole
// ;; is not
// (unreachable)
// ;; code here is unreachable in the wasm sense
// )
// )
bool willBeIgnored;

BinaryConsts::ASTNodes lastSeparator = BinaryConsts::End;

// process a block-type scope, until an end or else marker, or the end of the
// function
void processExpressions();
void skipUnreachableCode();

void pushExpression(Expression* curr);
Expression* popExpression();
Expression* popNonVoidExpression();
Expression* popTuple(size_t numElems);
Expression* popTypedExpression(Type type);
IRBuilder builder;

// validations that cannot be performed on the Module
void validateBinary();
Expand Down Expand Up @@ -1663,127 +1614,12 @@ class WasmBinaryReader {
void readNextDebugLocation();
void readSourceMapHeader();

// AST reading
int depth = 0; // only for debugging

BinaryConsts::ASTNodes readExpression(Expression*& curr);
void pushBlockElements(Block* curr, Type type, size_t start);
void visitBlock(Block* curr);

// Gets a block of expressions. If it's just one, return that singleton.
Expression* getBlockOrSingleton(Type type);

BreakTarget getBreakTarget(int32_t offset);
Name getExceptionTargetName(int32_t offset);

Index readMemoryAccess(Address& alignment, Address& offset);
std::tuple<Name, Address, Address> getMemarg();

void visitIf(If* curr);
void visitLoop(Loop* curr);
void visitBreak(Break* curr, uint8_t code);
void visitSwitch(Switch* curr);
void visitCall(Call* curr);
void visitCallIndirect(CallIndirect* curr);
void visitLocalGet(LocalGet* curr);
void visitLocalSet(LocalSet* curr, uint8_t code);
void visitGlobalGet(GlobalGet* curr);
void visitGlobalSet(GlobalSet* curr);
bool maybeVisitLoad(Expression*& out,
uint8_t code,
std::optional<BinaryConsts::ASTNodes> prefix);
bool maybeVisitStore(Expression*& out,
uint8_t code,
std::optional<BinaryConsts::ASTNodes> prefix);
bool maybeVisitNontrappingTrunc(Expression*& out, uint32_t code);
bool maybeVisitAtomicRMW(Expression*& out, uint8_t code);
bool maybeVisitAtomicCmpxchg(Expression*& out, uint8_t code);
bool maybeVisitAtomicWait(Expression*& out, uint8_t code);
bool maybeVisitAtomicNotify(Expression*& out, uint8_t code);
bool maybeVisitAtomicFence(Expression*& out, uint8_t code);
bool maybeVisitConst(Expression*& out, uint8_t code);
bool maybeVisitUnary(Expression*& out, uint8_t code);
bool maybeVisitBinary(Expression*& out, uint8_t code);
bool maybeVisitTruncSat(Expression*& out, uint32_t code);
bool maybeVisitSIMDBinary(Expression*& out, uint32_t code);
bool maybeVisitSIMDUnary(Expression*& out, uint32_t code);
bool maybeVisitSIMDConst(Expression*& out, uint32_t code);
bool maybeVisitSIMDStore(Expression*& out, uint32_t code);
bool maybeVisitSIMDExtract(Expression*& out, uint32_t code);
bool maybeVisitSIMDReplace(Expression*& out, uint32_t code);
bool maybeVisitSIMDShuffle(Expression*& out, uint32_t code);
bool maybeVisitSIMDTernary(Expression*& out, uint32_t code);
bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code);
bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
bool maybeVisitDataDrop(Expression*& out, uint32_t code);
bool maybeVisitMemoryCopy(Expression*& out, uint32_t code);
bool maybeVisitMemoryFill(Expression*& out, uint32_t code);
bool maybeVisitTableSize(Expression*& out, uint32_t code);
bool maybeVisitTableGrow(Expression*& out, uint32_t code);
bool maybeVisitTableFill(Expression*& out, uint32_t code);
bool maybeVisitTableCopy(Expression*& out, uint32_t code);
bool maybeVisitTableInit(Expression*& out, uint32_t code);
bool maybeVisitRefI31(Expression*& out, uint32_t code);
bool maybeVisitI31Get(Expression*& out, uint32_t code);
bool maybeVisitRefTest(Expression*& out, uint32_t code);
bool maybeVisitRefCast(Expression*& out, uint32_t code);
bool maybeVisitBrOn(Expression*& out, uint32_t code);
bool maybeVisitStructNew(Expression*& out, uint32_t code);
bool maybeVisitStructGet(Expression*& out, uint32_t code);
bool maybeVisitStructSet(Expression*& out, uint32_t code);
bool maybeVisitArrayNewData(Expression*& out, uint32_t code);
bool maybeVisitArrayNewElem(Expression*& out, uint32_t code);
bool maybeVisitArrayNewFixed(Expression*& out, uint32_t code);
bool maybeVisitArrayGet(Expression*& out, uint32_t code);
bool maybeVisitArraySet(Expression*& out, uint32_t code);
bool maybeVisitArrayLen(Expression*& out, uint32_t code);
bool maybeVisitArrayCopy(Expression*& out, uint32_t code);
bool maybeVisitArrayFill(Expression*& out, uint32_t code);
bool maybeVisitArrayInit(Expression*& out, uint32_t code);
bool maybeVisitStringNew(Expression*& out, uint32_t code);
bool maybeVisitStringAsWTF16(Expression*& out, uint32_t code);
bool maybeVisitStringConst(Expression*& out, uint32_t code);
bool maybeVisitStringMeasure(Expression*& out, uint32_t code);
bool maybeVisitStringEncode(Expression*& out, uint32_t code);
bool maybeVisitStringConcat(Expression*& out, uint32_t code);
bool maybeVisitStringEq(Expression*& out, uint32_t code);
bool maybeVisitStringWTF16Get(Expression*& out, uint32_t code);
bool maybeVisitStringSliceWTF(Expression*& out, uint32_t code);
void visitSelect(Select* curr, uint8_t code);
void visitReturn(Return* curr);
void visitMemorySize(MemorySize* curr);
void visitMemoryGrow(MemoryGrow* curr);
void visitNop(Nop* curr);
void visitUnreachable(Unreachable* curr);
void visitDrop(Drop* curr);
void visitRefNull(RefNull* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
void visitRefEq(RefEq* curr);
void visitTableGet(TableGet* curr);
void visitTableSet(TableSet* curr);
void visitTryOrTryInBlock(Expression*& out);
void visitTryTable(TryTable* curr);
void visitThrow(Throw* curr);
void visitRethrow(Rethrow* curr);
void visitThrowRef(ThrowRef* curr);
void visitCallRef(CallRef* curr);
void visitRefAsCast(RefCast* curr, uint32_t code);
void visitRefAs(RefAs* curr, uint8_t code);
void visitContNew(ContNew* curr);
void visitContBind(ContBind* curr);
void visitResume(Resume* curr);
void visitSuspend(Suspend* curr);

[[noreturn]] void throwError(std::string text);

// Struct/Array instructions have an unnecessary heap type that is just for
// validation (except for the case of unreachability, but that's not a problem
// anyhow, we can ignore it there). That is, we also have a reference typed
// child from which we can infer the type anyhow, and we just need to check
// that type is the same.
void validateHeapTypeUsingChild(Expression* child, HeapType heapType);
[[noreturn]] void throwError(std::string text) {
throw ParseException(text, 0, pos);
}

private:
bool hasDWARFSections();
Expand Down
25 changes: 25 additions & 0 deletions src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
// of instructions after this is called.
Result<Expression*> build();

// If the IRBuilder is empty, then it's ready to parse a new self-contained
// sequence of instructions.
[[nodiscard]] bool empty() { return scopeStack.empty(); }

// Call visit() on an existing Expression with its non-child fields
// initialized to initialize the child fields and refinalize it.
Result<> visit(Expression*);
Expand All @@ -59,6 +63,15 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
// pushed instruction.
void setDebugLocation(const std::optional<Function::DebugLocation>&);

// Give the builder a pointer to the counter tracking the current location in
// the binary. If this pointer is non-null, the builder will record the binary
// locations relative to the given code section offset for all instructions
// and delimiters inside functions.
void setBinaryLocation(size_t* binaryPos, size_t codeSectionOffset) {
this->binaryPos = binaryPos;
this->codeSectionOffset = codeSectionOffset;
}

// Set the function used to add scratch locals when constructing an isolated
// sequence of IR.
void setFunction(Function* func) { this->func = func; }
Expand Down Expand Up @@ -232,6 +245,11 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
Function* func = nullptr;
Builder builder;

// Used for setting DWARF expression locations.
size_t* binaryPos = nullptr;
size_t lastBinaryPos = 0;
size_t codeSectionOffset = 0;

// The location lacks debug info as it was marked as not having it.
struct NoDebug : public std::monostate {};
// The location lacks debug info, but was not marked as not having
Expand Down Expand Up @@ -316,6 +334,9 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
// stack-polymorphic unreachable mode.
bool unreachable = false;

// The binary location of the start of the scope, used to set debug info.
size_t startPos = 0;

ScopeCtx() : scope(NoScope{}) {}
ScopeCtx(Scope scope) : scope(scope) {}
ScopeCtx(Scope scope, Name label, bool labelUsed)
Expand Down Expand Up @@ -529,6 +550,10 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
// Record the original label to handle references to it correctly.
labelDepths[label].push_back(scopeStack.size() + 1);
}
if (binaryPos) {
scope.startPos = lastBinaryPos;
lastBinaryPos = *binaryPos;
}
scopeStack.push_back(scope);
}

Expand Down
Loading