Skip to content

Commit

Permalink
[WebAssembly] remove instruction after builtin trap (llvm#90207)
Browse files Browse the repository at this point in the history
`llvm.trap` will be convert as `unreachable` which is terminator.
Instruction after terminator will cause validation failed.
This PR introduces a pass to clean instruction after terminator.
Fixes: llvm#68770.
  • Loading branch information
HerrCai0907 authored Apr 27, 2024
1 parent 7b5b521 commit ff03f23
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 8 deletions.
1 change: 1 addition & 0 deletions llvm/lib/Target/WebAssembly/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ add_llvm_target(WebAssemblyCodeGen
WebAssemblyArgumentMove.cpp
WebAssemblyAsmPrinter.cpp
WebAssemblyCFGStackify.cpp
WebAssemblyCleanCodeAfterTrap.cpp
WebAssemblyCFGSort.cpp
WebAssemblyDebugFixup.cpp
WebAssemblyDebugValueManager.cpp
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ FunctionPass *createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,
CodeGenOptLevel OptLevel);
FunctionPass *createWebAssemblyArgumentMove();
FunctionPass *createWebAssemblySetP2AlignOperands();
FunctionPass *createWebAssemblyCleanCodeAfterTrap();

// Late passes.
FunctionPass *createWebAssemblyReplacePhysRegs();
Expand All @@ -63,6 +64,7 @@ void initializeOptimizeReturnedPass(PassRegistry &);
void initializeWebAssemblyRefTypeMem2LocalPass(PassRegistry &);
void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &);
void initializeWebAssemblyArgumentMovePass(PassRegistry &);
void initializeWebAssemblyCleanCodeAfterTrapPass(PassRegistry &);
void initializeWebAssemblyCFGSortPass(PassRegistry &);
void initializeWebAssemblyCFGStackifyPass(PassRegistry &);
void initializeWebAssemblyDAGToDAGISelPass(PassRegistry &);
Expand Down
80 changes: 80 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyCleanCodeAfterTrap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===-- WebAssemblyCleanCodeAfterTrap.cpp - Clean Code After Trap ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file remove instruction after trap.
/// ``llvm.trap`` will be convert as ``unreachable`` which is terminator.
/// Instruction after terminator will cause validation failed.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "WebAssemblyUtilities.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

#define DEBUG_TYPE "wasm-clean-code-after-trap"

namespace {
class WebAssemblyCleanCodeAfterTrap final : public MachineFunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
WebAssemblyCleanCodeAfterTrap() : MachineFunctionPass(ID) {}

StringRef getPassName() const override {
return "WebAssembly Clean Code After Trap";
}

bool runOnMachineFunction(MachineFunction &MF) override;
};
} // end anonymous namespace

char WebAssemblyCleanCodeAfterTrap::ID = 0;
INITIALIZE_PASS(WebAssemblyCleanCodeAfterTrap, DEBUG_TYPE,
"WebAssembly Clean Code After Trap", false, false)

FunctionPass *llvm::createWebAssemblyCleanCodeAfterTrap() {
return new WebAssemblyCleanCodeAfterTrap();
}

bool WebAssemblyCleanCodeAfterTrap::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG({
dbgs() << "********** CleanCodeAfterTrap **********\n"
<< "********** Function: " << MF.getName() << '\n';
});

bool Changed = false;

for (MachineBasicBlock &BB : MF) {
bool HasTerminator = false;
llvm::SmallVector<MachineInstr *> RemoveMI{};
for (MachineInstr &MI : BB) {
if (HasTerminator)
RemoveMI.push_back(&MI);
if (MI.hasProperty(MCID::Trap) && MI.isTerminator())
HasTerminator = true;
}
if (!RemoveMI.empty()) {
Changed = true;
LLVM_DEBUG({
for (MachineInstr *MI : RemoveMI) {
llvm::dbgs() << "* remove ";
MI->print(llvm::dbgs());
}
});
for (MachineInstr *MI : RemoveMI)
MI->eraseFromParent();
}
}
return Changed;
}
4 changes: 4 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,10 @@ bool WebAssemblyPassConfig::addInstSelector() {
// Eliminate range checks and add default targets to br_table instructions.
addPass(createWebAssemblyFixBrTableDefaults());

// unreachable is terminator, non-terminator instruction after it is not
// allowed.
addPass(createWebAssemblyCleanCodeAfterTrap());

return false;
}

Expand Down
11 changes: 9 additions & 2 deletions llvm/test/CodeGen/WebAssembly/unreachable.ll
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ define void @trap_ret_void() {
; CHECK: .functype trap_ret_void () -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: unreachable
; CHECK-NEXT: # fallthrough-return
; CHECK-NEXT: end_function
call void @llvm.trap()
ret void
Expand All @@ -54,7 +53,6 @@ define void @trap_unreacheable() {
; CHECK: .functype trap_unreacheable () -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: unreachable
; CHECK-NEXT: unreachable
; CHECK-NEXT: end_function
call void @llvm.trap()
unreachable
Expand Down Expand Up @@ -94,3 +92,12 @@ define i32 @missing_ret_noreturn_unreachable() {
call void @ext_never_return()
unreachable
}

define i32 @no_crash_for_other_instruction_after_trap(ptr %p, i32 %b) {
; CHECK-LABEL: no_crash_for_other_instruction_after_trap:
; CHECK: unreachable
; CHECK-NEXT: end_function
%a = load i32, ptr %p
call void @llvm.trap()
ret i32 %a
}
12 changes: 6 additions & 6 deletions llvm/test/MC/WebAssembly/global-ctor-dtor.ll
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,29 @@ declare void @func3()
; CHECK-NEXT: Offset: 0x1D
; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
; CHECK-NEXT: Index: 6
; CHECK-NEXT: Offset: 0x2C
; CHECK-NEXT: Offset: 0x2B
; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
; CHECK-NEXT: Index: 5
; CHECK-NEXT: Offset: 0x37
; CHECK-NEXT: Offset: 0x36
; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
; CHECK-NEXT: Index: 3
; CHECK-NEXT: Offset: 0x3F
; CHECK-NEXT: Offset: 0x3E
; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
; CHECK-NEXT: Index: 4
; CHECK-NEXT: Offset: 0x45
; CHECK-NEXT: Offset: 0x44
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 5
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 1080808080000B
; CHECK-NEXT: - Index: 6
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 02404181808080004100418080808000108180808000450D0000000B0B
; CHECK-NEXT: Body: 02404181808080004100418080808000108180808000450D00000B0B
; CHECK-NEXT: - Index: 7
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 1082808080000B
; CHECK-NEXT: - Index: 8
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 02404182808080004100418080808000108180808000450D0000000B0B
; CHECK-NEXT: Body: 02404182808080004100418080808000108180808000450D00000B0B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Segments:
; CHECK-NEXT: - SectionOffset: 6
Expand Down

0 comments on commit ff03f23

Please sign in to comment.