brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · 27b2ecd Raw
70 lines · plain
1; Tests that CoroSplit relocates a GNU computed-goto jump table (a module-level2; constant array of `blockaddress` values driving an `indirectbr`, e.g. glibc3; printf_positional's format dispatch) into a per-clone copy when its target4; blocks are cloned into a split function.5;6; The address-taken target blocks here are post-suspend, so CoroSplit clones7; them into @f.resume and the ramp's copies become unreachable. When CFG8; cleanup deletes those ramp blocks, BasicBlock::~BasicBlock RAUWs every9; `blockaddress` of a deleted block to the inttoptr(i32 1) sentinel. Before the10; fix this poisoned the *shared* @f.jt table that @f.resume still loaded from,11; so @f.resume's indirectbr read inttoptr(i32 1) (RED: traps as `unreachable`12; on wasm). The fix gives @f.resume its own remapped table referencing the13; cloned blocks, so its indirectbr stays valid (GREEN).14;15; RUN: opt < %s -passes='cgscc(coro-split),function(simplifycfg)' -S | FileCheck %s16 17@f.jt = internal constant [2 x ptr] [ptr blockaddress(@f, %target), ptr blockaddress(@f, %other)]18 19define ptr @f(i32 %idx) presplitcoroutine {20entry:21  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)22  %hdl = call ptr @llvm.coro.begin(token %id, ptr null)23  call void @print(i32 0)24  %sp = call i8 @llvm.coro.suspend(token none, i1 false)25  switch i8 %sp, label %suspend [i8 0, label %resume26                                 i8 1, label %cleanup]27resume:28  ; computed-goto: load a target from the blockaddress table with a runtime29  ; index (so the load is not constant-folded away before CoroSplit), then30  ; dispatch. The targets are reachable only from here (post-suspend).31  %slot = getelementptr inbounds [2 x ptr], ptr @f.jt, i32 0, i32 %idx32  %addr = load ptr, ptr %slot33  indirectbr ptr %addr, [label %target, label %other]34 35other:36  call void @print(i32 2)37  br label %cleanup38 39target:40  call void @print(i32 1)41  br label %cleanup42 43cleanup:44  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)45  br label %suspend46 47suspend:48  call void @llvm.coro.end(ptr %hdl, i1 0, token none)49  ret ptr %hdl50}51 52; The resume clone gets its OWN jump table whose blockaddress constants point at53; the resume clone's cloned target blocks -- not the poisoned sentinel.54; CHECK: @f.jt.f.resume = private constant [2 x ptr] [ptr blockaddress(@f.resume, %target), ptr blockaddress(@f.resume, %other)]55 56; The resume clone's computed-goto loads from its own table and dispatches to57; its own cloned blocks (RED pre-fix: it loaded from the poisoned @f.jt whose58; entries were RAUW'd to inttoptr (i32 1 to ptr)).59; CHECK-LABEL: define internal fastcc void @f.resume(60; CHECK:         %[[SLOT:.*]] = getelementptr inbounds [2 x ptr], ptr @f.jt.f.resume, i32 0,61; CHECK:         %[[ADDR:.*]] = load ptr, ptr %[[SLOT]]62; CHECK:         indirectbr ptr %[[ADDR]], [label %target, label %other]63 64declare ptr @llvm.coro.free(token, ptr)65declare i8  @llvm.coro.suspend(token, i1)66declare token @llvm.coro.id(i32, ptr, ptr, ptr)67declare ptr @llvm.coro.begin(token, ptr)68declare void @llvm.coro.end(ptr, i1, token)69declare void @print(i32)70