blob: 95b6bf368b577b05d1eeddc339ef220f2243f797 [file] [log] [blame] [edit]
REQUIRES: ld.lld
# Test that if a link is terminated by a signal (or the equivalent on
# Windows), e.g. CTRL-C, DTLTO temporary files are cleaned up.
RUN: rm -rf %t && split-file %s %t && cd %t
RUN: %clang --target=x86_64-linux-gnu -O2 t1.c t2.c -flto=thin -c
DEFINE: %{kill-dtlto} = %python killer.py %clang --target=x86_64-linux-gnu \
DEFINE: -nostdlib -O2 -flto=thin -fuse-ld=lld t1.o t2.o \
DEFINE: -fthinlto-distributor=%python \
DEFINE: -Xthinlto-distributor=local_codegen_and_wait.py
# Check that all temporary files are removed if the process is aborted.
RUN: mkdir none
RUN: %{kill-dtlto} -o none/t.elf
RUN: ls none | FileCheck %s --allow-empty --check-prefix=EMPTY
EMPTY-NOT: {{.}}
# Check that --save-temps preserves all the files.
RUN: rm send-signal && mkdir all
RUN: %{kill-dtlto} -Wl,--save-temps -o all/t.elf
RUN: ls all | sort | FileCheck %s --check-prefixes=BOOKEND,TEMPS,INDEX
# Check that --thinlto-emit-index-files preserves the index files.
RUN: rm send-signal && mkdir index
RUN: %{kill-dtlto} -Wl,--thinlto-emit-index-files -o index/t.elf
RUN: ls index | sort | FileCheck %s --check-prefixes=BOOKEND,INDEX
# No files are expected before.
BOOKEND-NOT: {{.}}
TEMPS: {{^}}t.[[#]].dist-file.json{{$}}
TEMPS: {{^}}t.elf.{{.+$}}
TEMPS: {{^}}t1.1.[[#]].native.o{{$}}
INDEX: {{^}}t1.1.[[#]].native.o.thinlto.bc{{$}}
TEMPS: {{^}}t2.2.[[#]].native.o{{$}}
INDEX: {{^}}t2.2.[[#]].native.o.thinlto.bc{{$}}
# No files are expected after.
BOOKEND-NOT: {{.}}
#--- t1.c
__attribute__((retain)) int t1(int x) { return x; }
#--- t2.c
__attribute__((retain)) int t2(int x) { return x; }
#--- local_codegen_and_wait.py
"""Perform codegen locally, create "send-signal" file and wait."""
from pathlib import Path
import json, subprocess, sys, time
# Load the DTLTO information from the input JSON file.
data = json.loads(Path(sys.argv[-1]).read_bytes())
# Iterate over the jobs and execute the codegen tool.
for job in data["jobs"]:
subprocess.check_call(data["common"]["args"] + job["args"])
Path("send-signal").touch()
while True:
time.sleep(1)
#--- killer.py
"""Run command, wait for "send-signal" file to exist, and then send a
termination signal."""
import os, sys, time, signal, subprocess
if os.name == "nt":
# CREATE_NEW_PROCESS_GROUP is used so that p.send_signal(CTRL_BREAK_EVENT)
# does not get sent to the LIT processes that are running the test.
kwargs = {"creationflags": subprocess.CREATE_NEW_PROCESS_GROUP}
else:
# Makes the child a process-group leader so os.killpg(p.pid, SIGINT) works.
kwargs = {"start_new_session": True}
p = subprocess.Popen(sys.argv[1:], **kwargs)
while not os.path.exists("send-signal"):
time.sleep(0.05)
if os.name == "nt":
# Note that CTRL_C_EVENT does not appear to work for clang.
p.send_signal(signal.CTRL_BREAK_EVENT)
else:
os.killpg(p.pid, signal.SIGINT)
p.wait()
sys.exit(0 if p.returncode != 0 else 1)