diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 5052310f530..1fb39b14ec6 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -151,9 +151,18 @@ void IRBuilder::push(Expression* expr) { applyDebugLoc(expr); if (binaryPos && func && lastBinaryPos != *binaryPos) { - func->expressionLocations[expr] = + auto span = BinaryLocations::Span{BinaryLocation(lastBinaryPos - codeSectionOffset), BinaryLocation(*binaryPos - codeSectionOffset)}; + // Some expressions already have their start noted, and we are just seeing + // their last segment (like an Else). + auto [iter, inserted] = func->expressionLocations.insert({expr, span}); + if (!inserted) { + // Just update the end. + iter->second.end = span.end; + // The true start from before is before the start of the current segment. + assert(iter->second.start < span.start); + } lastBinaryPos = *binaryPos; } @@ -933,6 +942,10 @@ Result<> IRBuilder::visitElse() { if (binaryPos && func) { func->delimiterLocations[iff][BinaryLocations::Else] = lastBinaryPos - codeSectionOffset; + + // Note the start of the if (which will be lost as the If is closed and the + // Else begins, but the if spans them both). + func->expressionLocations[iff].start = scope.startPos - codeSectionOffset; } return pushScope(ScopeCtx::makeElse(std::move(scope))); @@ -980,6 +993,8 @@ Result<> IRBuilder::visitCatch(Name tag) { if (binaryPos && func) { auto& delimiterLocs = func->delimiterLocations[tryy]; delimiterLocs[delimiterLocs.size()] = lastBinaryPos - codeSectionOffset; + // TODO: As in visitElse, we likely need to stash the Try start. Here we + // also need to account for multiple catches. } CHECK_ERR(pushScope(ScopeCtx::makeCatch(std::move(scope), tryy))); diff --git a/test/lit/branch-hinting.wast b/test/lit/branch-hinting.wast index 07277f0bc67..ba8f3716c3f 100644 --- a/test/lit/branch-hinting.wast +++ b/test/lit/branch-hinting.wast @@ -259,6 +259,128 @@ ) ) + ;; CHECK: (func $branch-hints-if-else (type $0) (param $x i32) + ;; CHECK-NEXT: (@metadata.code.branch_hint "\01") + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $branch-hints-if-else (type $0) (param $x i32) + ;; RTRIP-NEXT: (@metadata.code.branch_hint "\01") + ;; RTRIP-NEXT: (if + ;; RTRIP-NEXT: (local.get $x) + ;; RTRIP-NEXT: (then + ;; RTRIP-NEXT: (drop + ;; RTRIP-NEXT: (i32.const 1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (else + ;; RTRIP-NEXT: (drop + ;; RTRIP-NEXT: (i32.const 0) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; SRCMP: (func $branch-hints-if-else (type $0) (param $x i32) + ;; SRCMP-NEXT: (@metadata.code.branch_hint "\01") + ;; SRCMP-NEXT: (if + ;; SRCMP-NEXT: (local.get $x) + ;; SRCMP-NEXT: (then + ;; SRCMP-NEXT: (drop + ;; SRCMP-NEXT: (i32.const 1) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: (else + ;; SRCMP-NEXT: (drop + ;; SRCMP-NEXT: (i32.const 0) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + (func $branch-hints-if-else (param $x i32) + (@metadata.code.branch_hint "\01") + (if + (local.get $x) + (then + (drop + (i32.const 1) + ) + ) + (else + (drop + (i32.const 0) + ) + ) + ) + ) + + ;; CHECK: (func $branch-hints-if-else-result (type $0) (param $x i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (@metadata.code.branch_hint "\01") + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $branch-hints-if-else-result (type $0) (param $x i32) + ;; RTRIP-NEXT: (drop + ;; RTRIP-NEXT: (@metadata.code.branch_hint "\01") + ;; RTRIP-NEXT: (if (result i32) + ;; RTRIP-NEXT: (local.get $x) + ;; RTRIP-NEXT: (then + ;; RTRIP-NEXT: (i32.const 1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (else + ;; RTRIP-NEXT: (i32.const 0) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; SRCMP: (func $branch-hints-if-else-result (type $0) (param $x i32) + ;; SRCMP-NEXT: (drop + ;; SRCMP-NEXT: (@metadata.code.branch_hint "\01") + ;; SRCMP-NEXT: (if (result i32) + ;; SRCMP-NEXT: (local.get $x) + ;; SRCMP-NEXT: (then + ;; SRCMP-NEXT: (i32.const 1) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: (else + ;; SRCMP-NEXT: (i32.const 0) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + ;; SRCMP-NEXT: ) + (func $branch-hints-if-else-result (param $x i32) + (drop + (@metadata.code.branch_hint "\01") + (if (result i32) + (local.get $x) + (then + (i32.const 1) + ) + (else + (i32.const 0) + ) + ) + ) + ) + ;; CHECK: (func $branch-hints-br_on (type $1) (param $x anyref) ;; CHECK-NEXT: (block $out ;; CHECK-NEXT: (drop