Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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