mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-10 21:06:33 +03:00
Merge branch 'master' into merge-2.075
Conflicts: runtime/druntime
This commit is contained in:
commit
41aae46b91
58 changed files with 1154 additions and 442 deletions
|
@ -4,6 +4,7 @@ jobs:
|
|||
docker:
|
||||
- image: gcc
|
||||
environment:
|
||||
- LLVM_VERSION: 5.0.0
|
||||
- HOST_LDC_VERSION: 1.3.0
|
||||
steps:
|
||||
- checkout
|
||||
|
@ -24,15 +25,22 @@ jobs:
|
|||
ninja --version
|
||||
gdb --version
|
||||
python -c "import lit; lit.main();" --version | head -n 1
|
||||
- run:
|
||||
name: Install LLVM nightly
|
||||
command: |
|
||||
add-apt-repository -y 'deb http://apt.llvm.org/unstable/ llvm-toolchain-5.0 main'
|
||||
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||
apt update
|
||||
apt install -y llvm-5.0 llvm-5.0-dev libclang-common-5.0-dev libfuzzer-5.0-dev
|
||||
- restore_cache:
|
||||
key: host-ldc-{{ .Environment.HOST_LDC_VERSION }}
|
||||
keys:
|
||||
- llvm-5.0.0
|
||||
- host-ldc-{{ .Environment.HOST_LDC_VERSION }}
|
||||
- run:
|
||||
name: Install LLVM 5.0.0
|
||||
command: |
|
||||
if [[ ! -d llvm-$LLVM_VERSION ]]; then
|
||||
wget -O llvm-$LLVM_VERSION.tar.xz http://releases.llvm.org/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-linux-x86_64-ubuntu16.04.tar.xz
|
||||
mkdir llvm-$LLVM_VERSION
|
||||
tar -xpf llvm-$LLVM_VERSION.tar.xz --strip 1 -C llvm-$LLVM_VERSION
|
||||
fi
|
||||
- save_cache:
|
||||
key: llvm-5.0.0
|
||||
paths:
|
||||
- llvm-5.0.0
|
||||
- run:
|
||||
name: Install LDC host compiler
|
||||
command: |
|
||||
|
@ -50,7 +58,7 @@ jobs:
|
|||
export HOST_LDMD=$PWD/ldc2-$HOST_LDC_VERSION-linux-x86_64/bin/ldmd2
|
||||
mkdir bootstrap
|
||||
cd bootstrap
|
||||
cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -DD_COMPILER=$HOST_LDMD ..
|
||||
cmake -G Ninja -DLDC_WITH_LLD=OFF -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DBUILD_SHARED_LIBS=OFF -DD_COMPILER=$HOST_LDMD ..
|
||||
ninja -j3
|
||||
bin/ldc2 -version
|
||||
cd ..
|
||||
|
@ -60,7 +68,7 @@ jobs:
|
|||
export HOST_LDMD=$PWD/bootstrap/bin/ldmd2
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DLDC_INSTALL_LTOPLUGIN=ON -DLDC_INSTALL_LLVM_RUNTIME_LIBS=ON -DD_COMPILER=$HOST_LDMD ..
|
||||
cmake -G Ninja -DLDC_WITH_LLD=OFF -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DLDC_INSTALL_LTOPLUGIN=ON -DLDC_INSTALL_LLVM_RUNTIME_LIBS=ON -DD_COMPILER=$HOST_LDMD ..
|
||||
ninja -j3 all all-test-runners
|
||||
bin/ldc2 -version
|
||||
cd ..
|
||||
|
|
14
.travis.yml
14
.travis.yml
|
@ -4,6 +4,9 @@ sudo: false
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
d: ldc
|
||||
env: LLVM_VERSION=5.0.0 OPTS="-DLIB_SUFFIX=64 -DLDC_WITH_LLD=OFF"
|
||||
- os: linux
|
||||
d: ldc
|
||||
env: LLVM_VERSION=4.0.1 OPTS="-DLIB_SUFFIX=64"
|
||||
|
@ -18,7 +21,7 @@ matrix:
|
|||
env: LLVM_VERSION=3.7.1 OPTS="-DTEST_COVERAGE=ON"
|
||||
- os: osx
|
||||
d: ldc-beta
|
||||
env: LLVM_VERSION=6.0.0-1 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON
|
||||
env: LLVM_VERSION=6.0.0-2 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON
|
||||
- os: osx
|
||||
d: ldc
|
||||
env: LLVM_VERSION=4.0.0 OPTS="-DBUILD_SHARED_LIBS=ON"
|
||||
|
@ -27,7 +30,8 @@ matrix:
|
|||
|
||||
cache:
|
||||
directories:
|
||||
- llvm-spirv-6.0.0-1
|
||||
- llvm-spirv-6.0.0-2
|
||||
- llvm-5.0.0
|
||||
- llvm-4.0.1
|
||||
- llvm-4.0.0
|
||||
- llvm-3.9.1
|
||||
|
@ -44,7 +48,9 @@ addons:
|
|||
before_install:
|
||||
-
|
||||
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
||||
if [ "${LLVM_VERSION}" = "4.0.1" ]; then
|
||||
if [ "${LLVM_VERSION}" = "5.0.0" ]; then
|
||||
export LLVM_ARCH="linux-x86_64-ubuntu14.04";
|
||||
elif [ "${LLVM_VERSION}" = "4.0.1" ]; then
|
||||
export LLVM_ARCH="x86_64-linux-gnu-debian8";
|
||||
else
|
||||
export LLVM_ARCH="x86_64-linux-gnu-ubuntu-14.04";
|
||||
|
@ -54,7 +60,7 @@ before_install:
|
|||
fi;
|
||||
if [ -z "$(ls -A llvm-$LLVM_VERSION)" ]; then
|
||||
if [ -n "${LLVM_SPIRV_AVAILABLE}" ]; then
|
||||
wget -O llvm-spirv-$LLVM_VERSION.tar.bz2 https://github.com/thewilsonator/llvm/releases/download/pre-intrinsics/LLVM-6.0.0git-7375e8c-Darwin.tar.bz2;
|
||||
wget -O llvm-spirv-$LLVM_VERSION.tar.bz2 https://github.com/thewilsonator/llvm/releases/download/pre-intrinsics/LLVM-6.0.0svn-Darwin.tar.bz2;
|
||||
mkdir llvm-spirv-$LLVM_VERSION;
|
||||
tar -xjf llvm-spirv-$LLVM_VERSION.tar.bz2 --strip 1 -C llvm-spirv-$LLVM_VERSION;
|
||||
else
|
||||
|
|
|
@ -127,23 +127,27 @@ if(NOT MSVC_IDE)
|
|||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(${D_COMPILER_ID} STREQUAL "DigitalMars")
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(STATUS "Let DMD output 64bit object files")
|
||||
message(STATUS "Let D host compiler output 64bit object files")
|
||||
append("-m64" DDMD_DFLAGS)
|
||||
else()
|
||||
message(STATUS "Let DMD output 32bit COFF object files")
|
||||
message(STATUS "Let D host compiler output 32bit COFF object files")
|
||||
if(${D_COMPILER_ID} STREQUAL "DigitalMars")
|
||||
append("-m32mscoff" DDMD_DFLAGS)
|
||||
else()
|
||||
append("-m32" DDMD_DFLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC_VERSION GREATER 1800) # VS 2015+
|
||||
if(${D_COMPILER_ID} STREQUAL "DigitalMars" AND (MSVC_VERSION GREATER 1800)) # VS 2015+
|
||||
append("-Llegacy_stdio_definitions.lib" DDMD_DFLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Link against the static MSVC runtime; CMake's C(++) flags apparently default to the dynamic one.
|
||||
# Host DMD/LDMD already defaults to linking against the static MSVC runtime.
|
||||
# NOTE: Requires LLVM to be built with CMake variable LLVM_USE_CRT_{RELEASE,DEBUG,...}=MT[d].
|
||||
if(${LLVM_CXXFLAGS} MATCHES "(^| )/MDd?( |$)")
|
||||
message(FATAL_ERROR "LLVM must be built with CMake option LLVM_USE_CRT_<CMAKE_BUILD_TYPE>=MT[d]")
|
||||
endif()
|
||||
foreach(flag_var
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
|
@ -449,10 +453,9 @@ endif()
|
|||
#
|
||||
# LLD integration (requires LLVM >= 3.9 with LLD headers & libs)
|
||||
#
|
||||
set(LDC_WITH_LLD OFF)
|
||||
if(LDC_LLVM_VER GREATER 308)
|
||||
if(NOT DEFINED LDC_WITH_LLD)
|
||||
if(LDC_LLVM_VER GREATER 308)
|
||||
# check for LLD header
|
||||
unset(LDC_WITH_LLD)
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_REQUIRED_FLAGS -std=c++11)
|
||||
endif()
|
||||
|
@ -460,10 +463,13 @@ if(LDC_LLVM_VER GREATER 308)
|
|||
CHECK_INCLUDE_FILE_CXX(lld/Driver/Driver.h LDC_WITH_LLD)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
if(LDC_WITH_LLD)
|
||||
else()
|
||||
set(LDC_WITH_LLD OFF)
|
||||
endif()
|
||||
endif()
|
||||
if(LDC_WITH_LLD)
|
||||
message(STATUS "Building LDC with LLD support")
|
||||
append("-DLDC_WITH_LLD" LDC_CXXFLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
|
@ -614,6 +620,12 @@ else()
|
|||
if(MSVC)
|
||||
# Issue 1297 – set LDC's stack to 8 MiB like on Linux and Mac (default: 1 MiB).
|
||||
list(APPEND LDC_TRANSLATED_LINKER_FLAGS "-L/STACK:8388608")
|
||||
# VS 2017+: Use undocumented /NOOPTTLS MS linker switch to keep on emitting
|
||||
# a .tls section. Required for older host druntime versions, otherwise the
|
||||
# GC TLS ranges are garbage starting with VS 2017 Update 15.3.
|
||||
if(MSVC_VERSION GREATER 1900) # VS 2017+
|
||||
list(APPEND LDC_TRANSLATED_LINKER_FLAGS "-L/NOOPTTLS")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -764,13 +776,22 @@ function(copy_compilerrt_lib llvm_lib_name ldc_lib_name fixup_dylib)
|
|||
endif()
|
||||
endfunction()
|
||||
if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
|
||||
# Locate LLVM sanitizer runtime libraries, and copy them to our lib folder
|
||||
# Note: libFuzzer is part of compiler-rt version >= 6.0, but was part of LLVM =< 5.0
|
||||
|
||||
if(APPLE)
|
||||
copy_compilerrt_lib("darwin/libclang_rt.asan_osx_dynamic.dylib" "libldc_rt.asan_osx_dynamic.dylib" TRUE)
|
||||
if(NOT (LDC_LLVM_VER LESS 600))
|
||||
copy_compilerrt_lib("darwin/libclang_rt.fuzzer_osx.a" "libldc_rt.fuzzer_osx.a" FALSE)
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
copy_compilerrt_lib("linux/libclang_rt.asan-x86_64.a" "libldc_rt.asan-x86_64.a" FALSE)
|
||||
if(NOT (LDC_LLVM_VER LESS 600))
|
||||
copy_compilerrt_lib("linux/libclang_rt.fuzzer-x86_64.a" "libldc_rt.fuzzer-x86_64.a" FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Locate libFuzzer runtime library, and copy it to our lib folder
|
||||
if(LDC_LLVM_VER LESS 600)
|
||||
set(LLVM_LIBFUZZER_PATH ${LLVM_LIBRARY_DIRS}/libFuzzer.a)
|
||||
if(EXISTS ${LLVM_LIBFUZZER_PATH})
|
||||
message(STATUS "Copying libFuzzer library: ${LLVM_LIBFUZZER_PATH} --> libFuzzer.a")
|
||||
|
@ -780,6 +801,7 @@ if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
|
|||
else()
|
||||
message(STATUS "Not found: ${LLVM_LIBFUZZER_PATH}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
LDC – the LLVM-based D Compiler
|
||||
===============================
|
||||
|
||||
[][6]
|
||||
[][4]
|
||||
[][1]
|
||||
[][5]
|
||||
|
@ -95,3 +96,4 @@ Feedback of any kind is very much appreciated!
|
|||
[3]: https://www.bountysource.com/trackers/283332-ldc?utm_source=283332&utm_medium=shield&utm_campaign=TRACKER_BADGE "Bountysource"
|
||||
[4]: https://semaphoreci.com/ldc-developers/ldc "Semaphore CI Build Status"
|
||||
[5]: https://ci.appveyor.com/project/kinke/ldc/history "AppVeyor CI Build Status"
|
||||
[6]: https://circleci.com/gh/ldc-developers/ldc/tree/master "Circle CI Build Status"
|
||||
|
|
|
@ -14,7 +14,7 @@ skip_tags: true
|
|||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_JOB_ARCH: x64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Previous Visual Studio 2017
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
D_COMPILER: ldc
|
||||
- APPVEYOR_JOB_ARCH: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
|
|
@ -201,10 +201,17 @@ int performWriteOperation(object::Archive *OldArchive,
|
|||
writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin,
|
||||
std::move(OldArchiveBuf));
|
||||
|
||||
#if LDC_LLVM_VER >= 600
|
||||
if (Result) {
|
||||
fail("error writing '" + ArchiveName + "': " + Result.message());
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
if (Result.second) {
|
||||
fail(Result.second, Result.first);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -519,6 +519,11 @@ cl::list<std::string>
|
|||
" list. Use 'ocl-xy0' for OpenCL x.y, and "
|
||||
"'cuda-xy0' for CUDA CC x.y"),
|
||||
cl::value_desc("targets"));
|
||||
cl::opt<std::string>
|
||||
dcomputeFilePrefix("mdcompute-file-prefix",
|
||||
cl::desc("Prefix to prepend to the generated kernel files."),
|
||||
cl::init("kernels"),
|
||||
cl::value_desc("prefix"));
|
||||
#endif
|
||||
|
||||
static cl::extrahelp footer(
|
||||
|
|
|
@ -124,6 +124,7 @@ extern cl::opt<std::string> saveOptimizationRecord;
|
|||
#endif
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
extern cl::list<std::string> dcomputeTargets;
|
||||
extern cl::opt<std::string> dcomputeFilePrefix;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -201,3 +201,19 @@ bool ConfigFile::read(const char *explicitConfFile, const char *section) {
|
|||
|
||||
return readConfig(pathcstr, section, binpath.c_str());
|
||||
}
|
||||
|
||||
void ConfigFile::extendCommandLine(llvm::SmallVectorImpl<const char *> &args) {
|
||||
// insert 'switches' before all user switches
|
||||
args.insert(args.begin() + 1, switches.begin(), switches.end());
|
||||
|
||||
// append 'post-switches', but before a first potential '-run'
|
||||
size_t runIndex = 0;
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
if (strcmp(args[i], "-run") == 0 || strcmp(args[i], "--run") == 0) {
|
||||
runIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
args.insert(runIndex == 0 ? args.end() : args.begin() + runIndex,
|
||||
postSwitches.begin(), postSwitches.end());
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
module driver.configfile;
|
||||
|
||||
import ddmd.root.array;
|
||||
import driver.config;
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.string;
|
||||
|
@ -29,16 +30,13 @@ string prepareBinDir(const(char)* binDir)
|
|||
}
|
||||
|
||||
|
||||
ArraySetting findSwitches(Setting s)
|
||||
ArraySetting findArraySetting(GroupSetting section, string name)
|
||||
{
|
||||
auto grp = cast(GroupSetting)s;
|
||||
if (!grp) return null;
|
||||
foreach (c; grp.children)
|
||||
if (!section) return null;
|
||||
foreach (c; section.children)
|
||||
{
|
||||
if (c.name == "switches")
|
||||
{
|
||||
return cast(ArraySetting)c;
|
||||
}
|
||||
if (c.type == Setting.Type.array && c.name == name)
|
||||
return cast(ArraySetting) c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -88,74 +86,78 @@ unittest
|
|||
}
|
||||
|
||||
|
||||
struct ConfigFile
|
||||
extern(C++) struct ConfigFile
|
||||
{
|
||||
public:
|
||||
|
||||
alias s_iterator = const(char)**;
|
||||
|
||||
private:
|
||||
|
||||
// representation
|
||||
|
||||
const(char)* pathcstr;
|
||||
s_iterator switches_b;
|
||||
s_iterator switches_e;
|
||||
Array!(const(char)*) switches;
|
||||
Array!(const(char)*) postSwitches;
|
||||
|
||||
extern(C++)
|
||||
bool readConfig(const(char)* cfPath, const(char)* section, const(char)* binDir)
|
||||
bool readConfig(const(char)* cfPath, const(char)* sectionName, const(char)* binDir)
|
||||
{
|
||||
switches.setDim(0);
|
||||
postSwitches.setDim(0);
|
||||
|
||||
immutable dBinDir = prepareBinDir(binDir);
|
||||
const dSec = section[0 .. strlen(section)];
|
||||
const dSec = sectionName[0 .. strlen(sectionName)];
|
||||
|
||||
try
|
||||
{
|
||||
auto settingSections = parseConfigFile(cfPath);
|
||||
|
||||
bool sectionFound;
|
||||
ArraySetting secSwitches;
|
||||
ArraySetting defSwitches;
|
||||
|
||||
foreach (s; settingSections)
|
||||
GroupSetting section, defaultSection;
|
||||
foreach (s; parseConfigFile(cfPath))
|
||||
{
|
||||
if (s.type != Setting.Type.group)
|
||||
continue;
|
||||
if (s.name == dSec)
|
||||
{
|
||||
sectionFound = true;
|
||||
secSwitches = findSwitches(s);
|
||||
}
|
||||
section = cast(GroupSetting) s;
|
||||
else if (s.name == "default")
|
||||
{
|
||||
sectionFound = true;
|
||||
defSwitches = findSwitches(s);
|
||||
}
|
||||
defaultSection = cast(GroupSetting) s;
|
||||
}
|
||||
|
||||
if (!sectionFound)
|
||||
if (!section && !defaultSection)
|
||||
{
|
||||
const dCfPath = cfPath[0 .. strlen(cfPath)];
|
||||
if (section)
|
||||
if (sectionName)
|
||||
throw new Exception("Could not look up section '" ~ cast(string) dSec
|
||||
~ "' nor the 'default' section in " ~ cast(string) dCfPath);
|
||||
else
|
||||
throw new Exception("Could not look up 'default' section in " ~ cast(string) dCfPath);
|
||||
}
|
||||
|
||||
auto switches = secSwitches ? secSwitches : defSwitches;
|
||||
if (!switches)
|
||||
ArraySetting findArray(string name)
|
||||
{
|
||||
auto r = findArraySetting(section, name);
|
||||
if (!r)
|
||||
r = findArraySetting(defaultSection, name);
|
||||
return r;
|
||||
}
|
||||
|
||||
auto switches = findArray("switches");
|
||||
auto postSwitches = findArray("post-switches");
|
||||
if (!switches && !postSwitches)
|
||||
{
|
||||
const dCfPath = cfPath[0 .. strlen(cfPath)];
|
||||
throw new Exception("Could not look up switches in " ~ cast(string) dCfPath);
|
||||
}
|
||||
|
||||
auto finalSwitches = new const(char)*[switches.vals.length];
|
||||
foreach (i, sw; switches.vals)
|
||||
void applyArray(ref Array!(const(char)*) output, ArraySetting input)
|
||||
{
|
||||
if (!input)
|
||||
return;
|
||||
|
||||
output.reserve(input.vals.length);
|
||||
foreach (sw; input.vals)
|
||||
{
|
||||
const finalSwitch = sw.replace("%%ldcbinarypath%%", dBinDir) ~ '\0';
|
||||
finalSwitches[i] = finalSwitch.ptr;
|
||||
output.push(finalSwitch.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
switches_b = finalSwitches.ptr;
|
||||
switches_e = finalSwitches.ptr + finalSwitches.length;
|
||||
applyArray(this.switches, switches);
|
||||
applyArray(this.postSwitches, postSwitches);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,20 +14,19 @@
|
|||
#ifndef LDC_DRIVER_CONFIGFILE_H
|
||||
#define LDC_DRIVER_CONFIGFILE_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "array.h"
|
||||
|
||||
class ConfigFile {
|
||||
public:
|
||||
using s_iterator = const char **;
|
||||
|
||||
bool read(const char *explicitConfFile, const char *section);
|
||||
|
||||
s_iterator switches_begin() { return switches_b; }
|
||||
s_iterator switches_end() { return switches_e; }
|
||||
|
||||
std::string path() { return std::string(pathcstr); }
|
||||
|
||||
void extendCommandLine(llvm::SmallVectorImpl<const char *> &args);
|
||||
|
||||
private:
|
||||
bool locate(std::string &pathstr);
|
||||
|
||||
|
@ -35,8 +34,8 @@ private:
|
|||
bool readConfig(const char *cfPath, const char *section, const char *binDir);
|
||||
|
||||
const char *pathcstr = nullptr;
|
||||
s_iterator switches_b = nullptr;
|
||||
s_iterator switches_e = nullptr;
|
||||
Array<const char *> switches;
|
||||
Array<const char *> postSwitches;
|
||||
};
|
||||
|
||||
#endif // LDC_DRIVER_CONFIGFILE_H
|
||||
|
|
|
@ -17,47 +17,67 @@
|
|||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#if !(LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX)
|
||||
|
||||
DComputeCodeGenManager::DComputeCodeGenManager(llvm::LLVMContext &c) : ctx(c) {}
|
||||
void DComputeCodeGenManager::emit(Module *) {}
|
||||
void DComputeCodeGenManager::writeModules() {}
|
||||
DComputeCodeGenManager::~DComputeCodeGenManager() {}
|
||||
|
||||
#else
|
||||
|
||||
DComputeTarget *
|
||||
DComputeCodeGenManager::createComputeTarget(const std::string &s) {
|
||||
int v;
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV
|
||||
#define OCL_VALID_VER_INIT 100, 110, 120, 200, 210, 220
|
||||
const std::array<int, 6> valid_ocl_versions = {{OCL_VALID_VER_INIT}};
|
||||
#define CUDA_VALID_VER_INIT 100, 110, 120, 130, 200, 210, 300, 350, 370,\
|
||||
500, 520, 600, 610, 620
|
||||
const std::array<int, 14> vaild_cuda_versions = {{CUDA_VALID_VER_INIT}};
|
||||
|
||||
if (s.substr(0, 4) == "ocl-") {
|
||||
v = atoi(s.c_str() + 4);
|
||||
const int v = atoi(s.c_str() + 4);
|
||||
if (std::find(valid_ocl_versions.begin(), valid_ocl_versions.end(), v) !=
|
||||
valid_ocl_versions.end()) {
|
||||
return createOCLTarget(ctx, v);
|
||||
}
|
||||
} else if (s.substr(0, 5) == "cuda-") {
|
||||
v = atoi(s.c_str() + 5);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (std::find(vaild_cuda_versions.begin(), vaild_cuda_versions.end(), v) !=
|
||||
vaild_cuda_versions.end()) {
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
#define CUDA_VALID_VER_INIT 100, 110, 120, 130, 200, 210, 300, 350, 370,\
|
||||
500, 520, 600, 610, 620
|
||||
const std::array<int, 14> valid_cuda_versions = {{CUDA_VALID_VER_INIT}};
|
||||
|
||||
if (s.substr(0, 5) == "cuda-") {
|
||||
const int v = atoi(s.c_str() + 5);
|
||||
if (std::find(valid_cuda_versions.begin(), valid_cuda_versions.end(), v) !=
|
||||
valid_cuda_versions.end()) {
|
||||
return createCUDATarget(ctx, v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define XSTR(x) #x
|
||||
#define STR(x) XSTR((x))
|
||||
|
||||
error(Loc(),
|
||||
"unrecognised or invalid DCompute targets: the format is ocl-xy0 "
|
||||
"for OpenCl x.y and cuda-xy0 for CUDA CC x.y. Valid versions "
|
||||
"for OpenCl are " STR(OCL_VALID_VER_INIT) ". Valid versions for CUDA "
|
||||
"are " STR(CUDA_VALID_VER_INIT));
|
||||
"for OpenCl x.y and cuda-xy0 for CUDA CC x.y."
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV
|
||||
" Valid versions for OpenCl are " STR(OCL_VALID_VER_INIT) "."
|
||||
#endif
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
" Valid versions for CUDA are " STR(CUDA_VALID_VER_INIT)
|
||||
#endif
|
||||
);
|
||||
fatal();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DComputeCodeGenManager::DComputeCodeGenManager(llvm::LLVMContext &c) : ctx(c) {
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
for (auto &option : opts::dcomputeTargets) {
|
||||
targets.push_back(createComputeTarget(option));
|
||||
}
|
||||
#endif
|
||||
oldGIR = gIR;
|
||||
oldGTargetMachine = gTargetMachine;
|
||||
}
|
||||
|
||||
void DComputeCodeGenManager::emit(Module *m) {
|
||||
|
@ -72,3 +92,10 @@ void DComputeCodeGenManager::writeModules() {
|
|||
target->writeModule();
|
||||
}
|
||||
}
|
||||
|
||||
DComputeCodeGenManager::~DComputeCodeGenManager() {
|
||||
gIR = oldGIR;
|
||||
gTargetMachine = oldGTargetMachine;
|
||||
}
|
||||
|
||||
#endif // LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
#include "gen/dcompute/target.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
class TargetMachine;
|
||||
}
|
||||
|
||||
// gets run on modules marked @compute
|
||||
// All @compute D modules are emitted into one LLVM module once per target.
|
||||
class DComputeCodeGenManager {
|
||||
|
@ -20,12 +24,14 @@ class DComputeCodeGenManager {
|
|||
llvm::LLVMContext &ctx;
|
||||
llvm::SmallVector<DComputeTarget *, 2> targets;
|
||||
DComputeTarget *createComputeTarget(const std::string &s);
|
||||
|
||||
IRState *oldGIR = nullptr;
|
||||
llvm::TargetMachine *oldGTargetMachine = nullptr;
|
||||
public:
|
||||
void emit(Module *m);
|
||||
void writeModules();
|
||||
|
||||
DComputeCodeGenManager(llvm::LLVMContext &c);
|
||||
~DComputeCodeGenManager();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -180,58 +180,38 @@ void ArgsBuilder::addLTOLinkFlags() {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Returns true on success.
|
||||
bool addDarwinASanLinkFlags(std::vector<std::string> &args) {
|
||||
std::string searchPaths[] = {
|
||||
exe_path::prependLibDir("libldc_rt.asan_osx_dynamic.dylib"),
|
||||
exe_path::prependLibDir("libclang_rt.asan_osx_dynamic.dylib"),
|
||||
};
|
||||
|
||||
for (const auto &filepath : searchPaths) {
|
||||
if (llvm::sys::fs::exists(filepath)) {
|
||||
args.push_back(filepath);
|
||||
|
||||
// Add @executable_path to rpath to support having the dylib copied with
|
||||
// the executable.
|
||||
args.push_back("-rpath");
|
||||
args.push_back("@executable_path");
|
||||
|
||||
// Add the path to the resource dir to rpath to support using the dylib
|
||||
// from the default location without copying.
|
||||
args.push_back("-rpath");
|
||||
args.push_back(llvm::sys::path::parent_path(filepath));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We did not find the library.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the arch name as used in the compiler_rt libs.
|
||||
// FIXME: implement correctly for non-x86 platforms (e.g. ARM)
|
||||
llvm::StringRef getCompilerRTArchName() {
|
||||
return global.params.targetTriple->getArchName();
|
||||
}
|
||||
|
||||
bool addUnixlikeASanLinkFlags(std::vector<std::string> &args) {
|
||||
// Returns the libname as full path and with arch suffix and extension.
|
||||
// For example, with name="libldc_rt.fuzzer", the returned string is
|
||||
// "libldc_rt.fuzzer_osx.a" on Darwin.
|
||||
std::string getFullCompilerRTLibPath(llvm::StringRef name,
|
||||
bool sharedLibrary = false) {
|
||||
if (global.params.targetTriple->isOSDarwin()) {
|
||||
return exe_path::prependLibDir(
|
||||
name + (sharedLibrary ? "_osx_dynamic.dylib" : "_osx.a"));
|
||||
} else {
|
||||
return exe_path::prependLibDir(name + "-" + getCompilerRTArchName() +
|
||||
(sharedLibrary ? ".so" : ".a"));
|
||||
}
|
||||
}
|
||||
|
||||
void ArgsBuilder::addASanLinkFlags() {
|
||||
// Examples: "libclang_rt.asan-x86_64.a" or "libclang_rt.asan-arm.a" and
|
||||
// "libclang_rt.asan-x86_64.so"
|
||||
|
||||
auto arch = getCompilerRTArchName();
|
||||
|
||||
// TODO: let user choose to link with shared lib. In case of shared ASan, I
|
||||
// think we also need to statically link with
|
||||
// libclang_rt.asan-preinit-<arch>.a
|
||||
bool linkSharedASan = false;
|
||||
const char *extension = linkSharedASan ? ".so" : ".a";
|
||||
|
||||
// TODO: let user choose to link with shared lib.
|
||||
// In case of shared ASan, I think we also need to statically link with
|
||||
// libclang_rt.asan-preinit-<arch>.a on Linux. On Darwin, the only option is
|
||||
// to use the shared library.
|
||||
bool linkSharedASan = global.params.targetTriple->isOSDarwin();
|
||||
std::string searchPaths[] = {
|
||||
exe_path::prependLibDir("libldc_rt.asan-" + llvm::Twine(arch) +
|
||||
extension),
|
||||
exe_path::prependLibDir("libclang_rt.asan-" + llvm::Twine(arch) +
|
||||
extension),
|
||||
getFullCompilerRTLibPath("libldc_rt.asan", linkSharedASan),
|
||||
getFullCompilerRTLibPath("libclang_rt.asan", linkSharedASan),
|
||||
};
|
||||
|
||||
for (const auto &filepath : searchPaths) {
|
||||
|
@ -239,39 +219,39 @@ bool addUnixlikeASanLinkFlags(std::vector<std::string> &args) {
|
|||
args.push_back(filepath);
|
||||
|
||||
if (linkSharedASan) {
|
||||
// TODO: add -rpath
|
||||
// Add @executable_path to rpath to support having the shared lib copied
|
||||
// with the executable.
|
||||
args.push_back("-rpath");
|
||||
args.push_back("@executable_path");
|
||||
|
||||
// Add the path to the resource dir to rpath to support using the shared
|
||||
// lib from the default location without copying.
|
||||
args.push_back("-rpath");
|
||||
args.push_back(llvm::sys::path::parent_path(filepath));
|
||||
}
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We did not find the library.
|
||||
return false;
|
||||
}
|
||||
|
||||
void ArgsBuilder::addASanLinkFlags() {
|
||||
bool success = false;
|
||||
if (global.params.targetTriple->isOSDarwin()) {
|
||||
success = addDarwinASanLinkFlags(args);
|
||||
} else {
|
||||
success = addUnixlikeASanLinkFlags(args);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// When we reach here, we did not find the ASan library.
|
||||
// Fallback, requires Clang. The asan library contains a versioned symbol
|
||||
// name and a linker error will happen when the LDC-LLVM and Clang-LLVM
|
||||
// versions don't match.
|
||||
args.push_back("-fsanitize=address");
|
||||
}
|
||||
}
|
||||
|
||||
// Adds all required link flags for -fsanitize=fuzzer when libFuzzer library is
|
||||
// found.
|
||||
void ArgsBuilder::addFuzzLinkFlags() {
|
||||
std::string searchPaths[] = {
|
||||
#if LDC_LLVM_VER >= 600
|
||||
getFullCompilerRTLibPath("libldc_rt.fuzzer"),
|
||||
getFullCompilerRTLibPath("libclang_rt.fuzzer"),
|
||||
#else
|
||||
exe_path::prependLibDir("libFuzzer.a"),
|
||||
exe_path::prependLibDir("libLLVMFuzzer.a"),
|
||||
#endif
|
||||
};
|
||||
|
||||
for (const auto &filepath : searchPaths) {
|
||||
|
|
|
@ -354,9 +354,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
|
|||
// just ignore errors for now, they are still printed
|
||||
cfg_file.read(explicitConfFile, cfg_triple.c_str());
|
||||
|
||||
// insert switches from config file before all explicit ones
|
||||
allArguments.insert(allArguments.begin() + 1, cfg_file.switches_begin(),
|
||||
cfg_file.switches_end());
|
||||
cfg_file.extendCommandLine(allArguments);
|
||||
|
||||
// finalize by expanding response files specified in config file
|
||||
expandResponseFiles(allocator, allArguments);
|
||||
|
@ -398,7 +396,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
|
|||
fprintf(global.stdmsg, "binary %s\n", exe_path::getExePath().c_str());
|
||||
fprintf(global.stdmsg, "version %s (DMD %s, LLVM %s)\n",
|
||||
global.ldc_version, global.version, global.llvm_version);
|
||||
const std::string &path = cfg_file.path();
|
||||
const std::string path = cfg_file.path();
|
||||
if (!path.empty()) {
|
||||
fprintf(global.stdmsg, "config %s (%s)\n", path.c_str(),
|
||||
cfg_triple.c_str());
|
||||
|
|
|
@ -599,6 +599,7 @@ static const char *alternateMnemonics[N_AltMn] = {
|
|||
#define N Opr_NoType
|
||||
|
||||
// D=dest, N=notype
|
||||
// clang-format off
|
||||
static AsmOpInfo asmOpInfo[N_AsmOpInfo] = {
|
||||
/* Op_Invalid */ {},
|
||||
/* Op_Adjust */ {{0, 0, 0}, 0, Clb_EAX /*just AX*/},
|
||||
|
@ -830,6 +831,7 @@ static AsmOpInfo asmOpInfo[N_AsmOpInfo] = {
|
|||
/// immediate does not contribute to size
|
||||
/// * Op_cmovCC */ { D|rw, mrw, 0, 1 } // ->dstsrc
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#undef mri
|
||||
#undef mr
|
||||
|
@ -2062,14 +2064,14 @@ struct AsmProcessor {
|
|||
}
|
||||
regInfo[i].gccName = std::string(buf, p - buf);
|
||||
if ((i <= Reg_ST || i > Reg_ST7) && i != Reg_EFLAGS) {
|
||||
regInfo[i].ident =
|
||||
Identifier::idPool(regInfo[i].name.data(), regInfo[i].name.size());
|
||||
regInfo[i].ident = Identifier::idPool(regInfo[i].name.data(),
|
||||
regInfo[i].name.size());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < N_PtrNames; i++) {
|
||||
ptrTypeIdentTable[i] = Identifier::idPool(ptrTypeNameTable[i],
|
||||
std::strlen(ptrTypeNameTable[i]));
|
||||
ptrTypeIdentTable[i] = Identifier::idPool(
|
||||
ptrTypeNameTable[i], std::strlen(ptrTypeNameTable[i]));
|
||||
}
|
||||
|
||||
Handled = createExpression(Loc(), TOKvoid, sizeof(Expression));
|
||||
|
@ -3398,48 +3400,38 @@ struct AsmProcessor {
|
|||
}
|
||||
|
||||
Expression *parseEqualExp() {
|
||||
Expression *exp = parseRelExp();
|
||||
while (1) {
|
||||
switch (token->value) {
|
||||
case TOKequal:
|
||||
case TOKnotequal: {
|
||||
TOK tok = token->value;
|
||||
nextToken();
|
||||
Expression *exp2 = parseRelExp();
|
||||
if (isIntExp(exp) && isIntExp(exp2)) {
|
||||
exp = intOp(tok, exp, exp2);
|
||||
} else {
|
||||
stmt->error("bad integral operand");
|
||||
}
|
||||
}
|
||||
default:
|
||||
const auto exp = parseRelExp();
|
||||
const auto tok = token->value;
|
||||
if (tok != TOKequal && tok != TOKnotequal) {
|
||||
return exp;
|
||||
}
|
||||
|
||||
nextToken();
|
||||
const auto exp2 = parseRelExp();
|
||||
if (isIntExp(exp) && isIntExp(exp2)) {
|
||||
return intOp(tok, exp, exp2);
|
||||
}
|
||||
|
||||
stmt->error("bad integral operand");
|
||||
// TODO: Return ErrorExp?
|
||||
return exp;
|
||||
}
|
||||
|
||||
Expression *parseRelExp() {
|
||||
Expression *exp = parseShiftExp();
|
||||
while (1) {
|
||||
switch (token->value) {
|
||||
case TOKgt:
|
||||
case TOKge:
|
||||
case TOKlt:
|
||||
case TOKle: {
|
||||
TOK tok = token->value;
|
||||
nextToken();
|
||||
Expression *exp2 = parseShiftExp();
|
||||
if (isIntExp(exp) && isIntExp(exp2)) {
|
||||
exp = intOp(tok, exp, exp2);
|
||||
} else {
|
||||
stmt->error("bad integral operand");
|
||||
}
|
||||
}
|
||||
default:
|
||||
const auto exp = parseShiftExp();
|
||||
const auto tok = token->value;
|
||||
if (tok != TOKgt && tok != TOKge && tok != TOKlt && tok != TOKle) {
|
||||
return exp;
|
||||
}
|
||||
|
||||
nextToken();
|
||||
const auto exp2 = parseShiftExp();
|
||||
if (isIntExp(exp) && isIntExp(exp2)) {
|
||||
return intOp(tok, exp, exp2);
|
||||
}
|
||||
|
||||
stmt->error("bad integral operand");
|
||||
// TODO: Return ErrorExp?
|
||||
return exp;
|
||||
}
|
||||
|
||||
|
@ -3975,13 +3967,6 @@ struct AsmProcessor {
|
|||
}
|
||||
};
|
||||
|
||||
#if D_GCC_VER < 40
|
||||
// struct rtx was modified for c++; this macro from rtl.h needs to
|
||||
// be modified accordingly.
|
||||
#undef XEXP
|
||||
#define XEXP(RTX, N) (RTL_CHECK2(RTX, N, 'e', 'u').rt_rtx)
|
||||
#endif
|
||||
|
||||
// FIXME
|
||||
#define HOST_WIDE_INT long
|
||||
bool getFrameRelativeValue(LLValue *decl, HOST_WIDE_INT *result) {
|
||||
|
|
|
@ -7,19 +7,21 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
|
||||
#include "ddmd/dsymbol.h"
|
||||
#include "ddmd/mars.h"
|
||||
#include "ddmd/module.h"
|
||||
#include "ddmd/scope.h"
|
||||
#include "driver/linker.h"
|
||||
#include "driver/toobj.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "gen/dcompute/target.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/runtime.h"
|
||||
#include <string>
|
||||
|
||||
void DComputeTarget::doCodeGen(Module *m) {
|
||||
|
||||
// process module members
|
||||
for (unsigned k = 0; k < m->members->dim; k++) {
|
||||
Dsymbol *dsym = (*m->members)[k];
|
||||
|
@ -45,7 +47,7 @@ void DComputeTarget::writeModule() {
|
|||
|
||||
std::string filename;
|
||||
llvm::raw_string_ostream os(filename);
|
||||
os << "kernels_" << short_name << tversion << '_'
|
||||
os << opts::dcomputeFilePrefix << '_' << short_name << tversion << '_'
|
||||
<< (global.params.is64bit ? 64 : 32) << '.' << binSuffix;
|
||||
|
||||
const char *path = FileName::combine(global.params.objdir, os.str().c_str());
|
||||
|
@ -56,3 +58,5 @@ void DComputeTarget::writeModule() {
|
|||
delete _ir;
|
||||
_ir = nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
|
||||
#ifndef LDC_GEN_DCOMPUTE_TARGET_H
|
||||
#define LDC_GEN_DCOMPUTE_TARGET_H
|
||||
|
||||
#include "gen/irstate.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include <array>
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
class Function;
|
||||
|
@ -51,7 +53,12 @@ public:
|
|||
virtual void addKernelMetadata(FuncDeclaration *df, llvm::Function *llf) = 0;
|
||||
};
|
||||
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
DComputeTarget *createCUDATarget(llvm::LLVMContext &c, int sm);
|
||||
#endif
|
||||
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV
|
||||
DComputeTarget *createOCLTarget(llvm::LLVMContext &c, int oclver);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
|
||||
#include "gen/dcompute/target.h"
|
||||
#include "gen/dcompute/druntime.h"
|
||||
#include "gen/metadata.h"
|
||||
|
@ -77,3 +79,5 @@ public:
|
|||
DComputeTarget *createCUDATarget(llvm::LLVMContext &c, int sm) {
|
||||
return new TargetCUDA(c, sm);
|
||||
};
|
||||
|
||||
#endif // LDC_LLVM_SUPPORTED_TARGET_NVPTX
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
// See the LICENSE file for details.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if LDC_LLVM_SUPPORTED_TARGET_SPIRV
|
||||
|
||||
#include "gen/dcompute/target.h"
|
||||
#include "gen/dcompute/druntime.h"
|
||||
#include "ddmd/template.h"
|
||||
|
@ -198,3 +200,5 @@ public:
|
|||
DComputeTarget *createOCLTarget(llvm::LLVMContext &c, int oclver) {
|
||||
return new TargetOCL(c, oclver);
|
||||
}
|
||||
|
||||
#endif // LDC_LLVM_SUPPORTED_TARGET_SPIRV
|
||||
|
|
|
@ -113,12 +113,26 @@ ldc::DIScope ldc::DIBuilder::GetCurrentScope() {
|
|||
return fn->diLexicalBlocks.top();
|
||||
}
|
||||
|
||||
void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var,
|
||||
// Sets the memory address for a debuginfo variable.
|
||||
void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *storage,
|
||||
ldc::DILocalVariable divar,
|
||||
ldc::DIExpression diexpr) {
|
||||
unsigned charnum = (loc.linnum ? loc.charnum : 0);
|
||||
auto debugLoc = llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope());
|
||||
DBuilder.insertDeclare(var, divar, diexpr, debugLoc, IR->scopebb());
|
||||
DBuilder.insertDeclare(storage, divar, diexpr, debugLoc, IR->scopebb());
|
||||
}
|
||||
|
||||
// Sets the (current) value for a debuginfo variable.
|
||||
void ldc::DIBuilder::SetValue(const Loc &loc, llvm::Value *value,
|
||||
ldc::DILocalVariable divar,
|
||||
ldc::DIExpression diexpr) {
|
||||
unsigned charnum = (loc.linnum ? loc.charnum : 0);
|
||||
auto debugLoc = llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope());
|
||||
DBuilder.insertDbgValueIntrinsic(value,
|
||||
#if LDC_LLVM_VER < 600
|
||||
0,
|
||||
#endif
|
||||
divar, diexpr, debugLoc, IR->scopebb());
|
||||
}
|
||||
|
||||
ldc::DIFile ldc::DIBuilder::CreateFile(Loc &loc) {
|
||||
|
@ -1020,7 +1034,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
|
|||
|
||||
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
||||
Type *type, bool isThisPtr,
|
||||
bool forceAsLocal,
|
||||
bool forceAsLocal, bool isRefRVal,
|
||||
llvm::ArrayRef<int64_t> addr) {
|
||||
if (!mustEmitFullDebugInfo())
|
||||
return;
|
||||
|
@ -1040,11 +1054,27 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|||
if (static_cast<llvm::MDNode *>(TD) == nullptr)
|
||||
return; // unsupported
|
||||
|
||||
if (vd->isRef() || vd->isOut()) {
|
||||
const bool isRefOrOut = vd->isRef() || vd->isOut(); // incl. special-ref vars
|
||||
|
||||
// For MSVC x64 targets, declare params rewritten by ExplicitByvalRewrite as
|
||||
// DI references, as if they were ref parameters.
|
||||
const bool isPassedExplicitlyByval =
|
||||
isTargetMSVCx64 && !isRefOrOut && isaArgument(ll) && addr.empty();
|
||||
|
||||
bool useDbgValueIntrinsic = false;
|
||||
if (isRefOrOut || isPassedExplicitlyByval) {
|
||||
// With the exception of special-ref loop variables, the reference/pointer
|
||||
// itself is constant. So we don't have to attach the debug information to a
|
||||
// memory location and can use llvm.dbg.value to set the constant pointer
|
||||
// for the DI reference.
|
||||
useDbgValueIntrinsic =
|
||||
isPassedExplicitlyByval || (!isSpecialRefVar(vd) && isRefRVal);
|
||||
#if LDC_LLVM_VER >= 308
|
||||
auto T = DtoType(type);
|
||||
TD = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, TD,
|
||||
getTypeAllocSize(T) * 8, // size (bits)
|
||||
// Note: createReferenceType expects the size to be the size of a pointer,
|
||||
// not the size of the type the reference refers to.
|
||||
TD = DBuilder.createReferenceType(
|
||||
llvm::dwarf::DW_TAG_reference_type, TD,
|
||||
gDataLayout->getPointerSizeInBits(), // size (bits)
|
||||
DtoAlignment(type) * 8); // align (bits)
|
||||
#else
|
||||
TD = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, TD);
|
||||
|
@ -1122,10 +1152,15 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|||
#endif
|
||||
variableMap[vd] = debugVariable;
|
||||
|
||||
// declare
|
||||
Declare(vd->loc, ll, debugVariable, addr.empty()
|
||||
? DBuilder.createExpression()
|
||||
if (useDbgValueIntrinsic) {
|
||||
SetValue(vd->loc, ll, debugVariable,
|
||||
addr.empty() ? DBuilder.createExpression()
|
||||
: DBuilder.createExpression(addr));
|
||||
} else {
|
||||
Declare(vd->loc, ll, debugVariable,
|
||||
addr.empty() ? DBuilder.createExpression()
|
||||
: DBuilder.createExpression(addr));
|
||||
}
|
||||
}
|
||||
|
||||
void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar,
|
||||
|
|
|
@ -115,15 +115,22 @@ public:
|
|||
|
||||
/// \brief Emits all things necessary for making debug info for a local
|
||||
/// variable vd.
|
||||
/// \param ll LL lvalue of the variable.
|
||||
/// \param ll LL value which, in combination with `addr`, yields the
|
||||
/// storage/lvalue of the variable. For special-ref loop variables, specify
|
||||
/// the storage/lvalue of the reference/pointer.
|
||||
/// \param vd Variable declaration to emit debug info for.
|
||||
/// \param type Type of variable if different from vd->type
|
||||
/// \param isThisPtr Variable is hidden this pointer
|
||||
/// \param forceAsLocal Emit as local even if the variable is a parameter
|
||||
/// \param addr An array of complex address operations.
|
||||
/// \param isRefRVal Only relevant for ref/out parameters: indicates whether
|
||||
/// ll & addr specify the reference's rvalue, i.e., the lvalue of the original
|
||||
/// variable, instead of the reference's lvalue.
|
||||
/// \param addr An array of complex address operations encoding a DWARF
|
||||
/// expression.
|
||||
void
|
||||
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
|
||||
bool isThisPtr = false, bool forceAsLocal = false,
|
||||
bool isRefRVal = false,
|
||||
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>());
|
||||
|
||||
/// \brief Emits all things necessary for making debug info for a global
|
||||
|
@ -139,7 +146,9 @@ private:
|
|||
llvm::LLVMContext &getContext();
|
||||
Module *getDefinedModule(Dsymbol *s);
|
||||
DIScope GetCurrentScope();
|
||||
void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar,
|
||||
void Declare(const Loc &loc, llvm::Value *storage, ldc::DILocalVariable divar,
|
||||
ldc::DIExpression diexpr);
|
||||
void SetValue(const Loc &loc, llvm::Value *value, ldc::DILocalVariable divar,
|
||||
ldc::DIExpression diexpr);
|
||||
void AddFields(AggregateDeclaration *sd, ldc::DIFile file,
|
||||
llvm::SmallVector<llvm::Metadata *, 16> &elems);
|
||||
|
|
|
@ -768,8 +768,14 @@ void defineParameters(IrFuncTy &irFty, VarDeclarations ¶meters) {
|
|||
++llArgIdx;
|
||||
}
|
||||
|
||||
if (global.params.symdebug)
|
||||
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType);
|
||||
// The debuginfos for captured params are handled later by
|
||||
// DtoCreateNestedContext().
|
||||
if (global.params.symdebug && vd->nestedrefs.dim == 0) {
|
||||
// Reference (ref/out) parameters have no storage themselves as they are
|
||||
// constant pointers, so pass the reference rvalue to EmitLocalVariable().
|
||||
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType, false,
|
||||
false, /*isRefRVal=*/true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,10 +130,13 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|||
Logger::cout() << "of type: " << *val->getType() << '\n';
|
||||
}
|
||||
const bool isRefOrOut = vd->isRef() || vd->isOut();
|
||||
if (!isSpecialRefVar(vd) && (byref || isRefOrOut)) {
|
||||
if (isSpecialRefVar(vd)) {
|
||||
// Handled appropriately by makeVarDValue() and EmitLocalVariable(), pass
|
||||
// storage of pointer (reference lvalue).
|
||||
} else if (byref || isRefOrOut) {
|
||||
val = DtoAlignedLoad(val);
|
||||
// ref/out variables get a reference-debuginfo-type in
|
||||
// DIBuilder::EmitLocalVariable()
|
||||
// ref/out variables get a reference-debuginfo-type in EmitLocalVariable();
|
||||
// pass the GEP as reference lvalue in that case.
|
||||
if (!isRefOrOut)
|
||||
gIR->DBuilder.OpDeref(dwarfAddrOps);
|
||||
IF_LOG {
|
||||
|
@ -143,11 +146,13 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|||
}
|
||||
|
||||
if (!skipDIDeclaration && global.params.symdebug) {
|
||||
#if LDC_LLVM_VER < 500
|
||||
// Because we are passing a GEP instead of an alloca to
|
||||
// llvm.dbg.declare, we have to make the address dereference explicit.
|
||||
gIR->DBuilder.OpDeref(dwarfAddrOps);
|
||||
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, true,
|
||||
dwarfAddrOps);
|
||||
#endif
|
||||
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false,
|
||||
/*forceAsLocal=*/true, false, dwarfAddrOps);
|
||||
}
|
||||
|
||||
return makeVarDValue(astype, vd, val);
|
||||
|
@ -472,6 +477,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
|
|||
|
||||
IrLocal *irLocal = getIrLocal(vd);
|
||||
LLValue *gep = DtoGEPi(frame, 0, irLocal->nestedIndex, vd->toChars());
|
||||
LLSmallVector<int64_t, 2> dwarfAddrOps;
|
||||
if (vd->isParameter()) {
|
||||
IF_LOG Logger::println("nested param: %s", vd->toChars());
|
||||
LOG_SCOPE
|
||||
|
@ -482,6 +488,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
|
|||
if (vd->isRef() || vd->isOut()) {
|
||||
Logger::println("Captured by reference, copying pointer to nested frame");
|
||||
DtoAlignedStore(parm->value, gep);
|
||||
// pass GEP as reference lvalue to EmitLocalVariable()
|
||||
} else {
|
||||
Logger::println("Copying to nested frame");
|
||||
// The parameter value is an alloca'd stack slot.
|
||||
|
@ -498,11 +505,13 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
|
|||
}
|
||||
|
||||
if (global.params.symdebug) {
|
||||
LLSmallVector<int64_t, 2> addr;
|
||||
#if LDC_LLVM_VER < 500
|
||||
// Because we are passing a GEP instead of an alloca to
|
||||
// llvm.dbg.declare, we have to make the address dereference explicit.
|
||||
gIR->DBuilder.OpDeref(addr);
|
||||
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, addr);
|
||||
gIR->DBuilder.OpDeref(dwarfAddrOps);
|
||||
#endif
|
||||
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, false,
|
||||
dwarfAddrOps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,12 @@ default:
|
|||
{
|
||||
// default switches injected before all explicit command-line switches
|
||||
switches = [
|
||||
"-I@RUNTIME_DIR@/src",
|
||||
"-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@", @MULTILIB_ADDITIONAL_PATH@@SHARED_LIBS_RPATH@
|
||||
"-I@RUNTIME_DIR@/src",@SHARED_LIBS_RPATH@
|
||||
"-defaultlib=druntime-ldc",
|
||||
"-debuglib=druntime-ldc-debug"@ADDITIONAL_DEFAULT_LDC_SWITCHES@
|
||||
];
|
||||
// default switches appended after all explicit command-line switches
|
||||
post-switches = [
|
||||
"-L-L@PROJECT_BINARY_DIR@/../lib@LIB_SUFFIX@",@MULTILIB_ADDITIONAL_PATH@
|
||||
];
|
||||
};
|
||||
|
|
|
@ -8,8 +8,11 @@ default:
|
|||
switches = [
|
||||
"-I@INCLUDE_INSTALL_DIR@/ldc",
|
||||
"-I@INCLUDE_INSTALL_DIR@",
|
||||
"-L-L@CMAKE_INSTALL_LIBDIR@", @MULTILIB_ADDITIONAL_INSTALL_PATH@
|
||||
"-defaultlib=phobos2-ldc,druntime-ldc",
|
||||
"-debuglib=phobos2-ldc-debug,druntime-ldc-debug"@ADDITIONAL_DEFAULT_LDC_SWITCHES@
|
||||
];
|
||||
// default switches appended after all explicit command-line switches
|
||||
post-switches = [
|
||||
"-L-L@CMAKE_INSTALL_LIBDIR@",@MULTILIB_ADDITIONAL_INSTALL_PATH@
|
||||
];
|
||||
};
|
||||
|
|
|
@ -8,9 +8,12 @@ default:
|
|||
switches = [
|
||||
"-I@RUNTIME_DIR@/src",
|
||||
"-I@PROFILERT_DIR@/d",
|
||||
"-I@PHOBOS2_DIR@",
|
||||
"-L-L@CMAKE_BINARY_DIR@/lib@LIB_SUFFIX@", @MULTILIB_ADDITIONAL_PATH@@SHARED_LIBS_RPATH@
|
||||
"-I@PHOBOS2_DIR@",@SHARED_LIBS_RPATH@
|
||||
"-defaultlib=phobos2-ldc,druntime-ldc",
|
||||
"-debuglib=phobos2-ldc-debug,druntime-ldc-debug"@ADDITIONAL_DEFAULT_LDC_SWITCHES@
|
||||
];
|
||||
// default switches appended after all explicit command-line switches
|
||||
post-switches = [
|
||||
"-L-L@CMAKE_BINARY_DIR@/lib@LIB_SUFFIX@",@MULTILIB_ADDITIONAL_PATH@
|
||||
];
|
||||
};
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
project(runtime)
|
||||
project(runtime C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
# Verify required variables if this CMake project is NOT embedded in the LDC CMake project.
|
||||
if(NOT LDC_EXE)
|
||||
if(NOT LDC_EXE_FULL)
|
||||
|
@ -37,14 +41,19 @@ set(D_FLAGS -w CACHE STRING "Runt
|
|||
set(D_FLAGS_DEBUG -g;-link-debuglib CACHE STRING "Runtime D compiler flags (debug libraries), separated by ';'")
|
||||
set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime D compiler flags (release libraries), separated by ';'")
|
||||
set(COMPILE_ALL_D_FILES_AT_ONCE ON CACHE BOOL "Compile all D files for a lib in a single command line instead of separately")
|
||||
set(RT_ARCHIVE_WITH_LDC AUTO CACHE STRING "Whether to archive the static runtime libs via LDC instead of CMake archiver")
|
||||
set(RT_CFLAGS "" CACHE STRING "Runtime extra C compiler flags, separated by ' '")
|
||||
set(LD_FLAGS "" CACHE STRING "Runtime extra C linker flags, separated by ' '")
|
||||
set(C_SYSTEM_LIBS AUTO CACHE STRING "C system libraries for linking shared libraries and test runners, separated by ';'")
|
||||
set(TARGET_SYSTEM AUTO CACHE STRING "Targeted platform for cross-compilation (e.g., 'Linux;UNIX', 'Darwin;APPLE;UNIX', 'Windows;MSVC')")
|
||||
set(TARGET_SYSTEM AUTO CACHE STRING "Target OS/toolchain for cross-compilation (e.g., 'Linux;UNIX', 'Darwin;APPLE;UNIX', 'Windows;MSVC')")
|
||||
set(LDC_TARGET_PRESET "" CACHE STRING "Use a preset target configuration for cross-compilation, by passing format OS-arch (e.g., 'Linux-arm', 'Mac-x64', 'Windows-aarch64', 'Android-x86')")
|
||||
|
||||
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
|
||||
|
||||
# Auto-detect TARGET_SYSTEM
|
||||
# Use LDC_TARGET_PRESET to configure target runtime
|
||||
include(PresetRuntimeConfiguration)
|
||||
|
||||
# Auto-detect TARGET_SYSTEM from host
|
||||
if("${TARGET_SYSTEM}" STREQUAL "AUTO")
|
||||
set(TARGET_SYSTEM ${CMAKE_SYSTEM_NAME})
|
||||
# Additionally add MSVC, APPLE and/or UNIX
|
||||
|
@ -75,8 +84,19 @@ else()
|
|||
set(MULTILIB_SUFFIX 64)
|
||||
endif()
|
||||
|
||||
if(${RT_ARCHIVE_WITH_LDC} STREQUAL "AUTO")
|
||||
# LLVM's MSVC archiver (v4.0.1) apparently has issues with objects with debuginfos,
|
||||
# leading to MS linker warnings when linking against the static debug runtime libs.
|
||||
if("${TARGET_SYSTEM}" MATCHES "MSVC")
|
||||
set(RT_ARCHIVE_WITH_LDC OFF)
|
||||
else()
|
||||
set(RT_ARCHIVE_WITH_LDC ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SHARED_LIBS_SUPPORTED OFF)
|
||||
if("${TARGET_SYSTEM}" MATCHES "Linux|FreeBSD|APPLE")
|
||||
if("${TARGET_SYSTEM}" MATCHES "Linux|FreeBSD|APPLE"
|
||||
AND (NOT "${TARGET_SYSTEM}" MATCHES "Android"))
|
||||
set(SHARED_LIBS_SUPPORTED ON)
|
||||
endif()
|
||||
|
||||
|
@ -102,7 +122,9 @@ endif()
|
|||
|
||||
# Auto-detect C system libraries
|
||||
if("${C_SYSTEM_LIBS}" STREQUAL "AUTO")
|
||||
if("${TARGET_SYSTEM}" MATCHES "Linux")
|
||||
if("${TARGET_SYSTEM}" MATCHES "Android")
|
||||
set(C_SYSTEM_LIBS m c)
|
||||
elseif("${TARGET_SYSTEM}" MATCHES "Linux")
|
||||
set(C_SYSTEM_LIBS m pthread rt dl)
|
||||
else()
|
||||
set(C_SYSTEM_LIBS m pthread)
|
||||
|
@ -293,7 +315,7 @@ foreach(target ${LLVM_TARGETS_TO_BUILD})
|
|||
endforeach()
|
||||
|
||||
# Always build zlib and other C parts of the runtime in release mode, regardless
|
||||
# of what the user chose for LDC itself.
|
||||
# of what the user chose for LDC itself. Also add other C_FLAGS here.
|
||||
# 1) Set up CMAKE_C_FLAGS_RELEASE
|
||||
if("${TARGET_SYSTEM}" MATCHES "MSVC")
|
||||
# Omit all references to the default C runtime libs.
|
||||
|
@ -305,6 +327,11 @@ if("${TARGET_SYSTEM}" MATCHES "MSVC")
|
|||
# warning C4996: zlib uses 'deprecated' POSIX names
|
||||
append("/wd4131 /wd4206 /wd4996" CMAKE_C_FLAGS_RELEASE)
|
||||
endif()
|
||||
CHECK_INCLUDE_FILE(unistd.h HAVE_UNISTD_H)
|
||||
if (HAVE_UNISTD_H)
|
||||
# Needed for zlib
|
||||
append("-DHAVE_UNISTD_H" CMAKE_C_FLAGS_RELEASE)
|
||||
endif()
|
||||
# 2) Set all other CMAKE_C_FLAGS variants to CMAKE_C_FLAGS_RELEASE
|
||||
set(variables
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
|
@ -417,13 +444,24 @@ macro(compile_phobos2 d_flags lib_suffix path_suffix all_at_once outlist_o outli
|
|||
)
|
||||
endmacro()
|
||||
|
||||
# Define an optional 'D' CMake linker language for the static runtime libs,
|
||||
# using LDC as archiver. LDC handles (cross-)archiving internally via LLVM
|
||||
# and supports LTO objects.
|
||||
set(CMAKE_D_CREATE_STATIC_LIBRARY "${LDC_EXE_FULL} -lib -of=<TARGET> <OBJECTS>")
|
||||
foreach(f ${D_FLAGS})
|
||||
append("\"${f}\"" CMAKE_D_CREATE_STATIC_LIBRARY)
|
||||
endforeach()
|
||||
|
||||
# Sets the common properties for all library targets.
|
||||
function(set_common_library_properties target)
|
||||
function(set_common_library_properties target is_shared)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
VERSION ${DMDFE_VERSION}
|
||||
SOVERSION ${DMDFE_PATCH_VERSION}
|
||||
LINKER_LANGUAGE C
|
||||
)
|
||||
if(RT_ARCHIVE_WITH_LDC AND NOT is_shared)
|
||||
set_target_properties(${target} PROPERTIES LINKER_LANGUAGE D)
|
||||
endif()
|
||||
|
||||
# ldc2 defaults to position-independent code on Linux to match the implicit
|
||||
# linker default on Ubuntu 16.10 and above. As we might be building on an
|
||||
|
@ -458,7 +496,7 @@ macro(build_runtime_libs druntime_o druntime_bc phobos2_o phobos2_bc c_flags ld_
|
|||
COMPILE_FLAGS "${c_flags}"
|
||||
LINK_FLAGS "${ld_flags}"
|
||||
)
|
||||
set_common_library_properties(druntime-ldc${target_suffix})
|
||||
set_common_library_properties(druntime-ldc${target_suffix} "${is_shared}")
|
||||
|
||||
# When building a shared library, we need to link in all the default
|
||||
# libraries otherwise implicitly added by LDC to make it loadable from
|
||||
|
@ -481,7 +519,7 @@ macro(build_runtime_libs druntime_o druntime_bc phobos2_o phobos2_bc c_flags ld_
|
|||
COMPILE_FLAGS "${c_flags}"
|
||||
LINK_FLAGS "${ld_flags}"
|
||||
)
|
||||
set_common_library_properties(phobos2-ldc${target_suffix})
|
||||
set_common_library_properties(phobos2-ldc${target_suffix} "${is_shared}")
|
||||
|
||||
if("${is_shared}" STREQUAL "ON")
|
||||
target_link_libraries(phobos2-ldc${target_suffix}
|
||||
|
@ -595,7 +633,7 @@ macro(build_all_runtime_variants d_flags c_flags ld_flags path_suffix outlist_ta
|
|||
# static profile-rt
|
||||
build_profile_runtime("${d_flags};${D_FLAGS};${D_FLAGS_RELEASE}" "${c_flags}" "${ld_flags}" "" "${path_suffix}" ${outlist_targets})
|
||||
get_target_suffix("" "${path_suffix}" target_suffix)
|
||||
set_common_library_properties(ldc-profile-rt${target_suffix})
|
||||
set_common_library_properties(ldc-profile-rt${target_suffix} OFF)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
|
97
runtime/PresetRuntimeConfiguration.cmake
Normal file
97
runtime/PresetRuntimeConfiguration.cmake
Normal file
|
@ -0,0 +1,97 @@
|
|||
# - Preset cross-compilation configurations for C/ASM and D compilation
|
||||
# and linking, for supported targets
|
||||
#
|
||||
# This module sets compiler flags for a few C and assembly files in
|
||||
# DRuntime and Phobos, and linker flags to link the standard library as
|
||||
# a shared library and build the test runners, for various
|
||||
# cross-compilation targets that the LDC developers have tried out.
|
||||
#
|
||||
# It is enabled by setting LDC_TARGET_PRESET to a supported platform,
|
||||
# after which the appropriate TARGET_SYSTEM is set and a target triple
|
||||
# is appended to D_FLAGS.
|
||||
#
|
||||
# You can pass in custom RT_CFLAGS and LD_FLAGS of your choosing, but
|
||||
# if they're left unconfigured, they will also be set to sensible
|
||||
# defaults.
|
||||
|
||||
if(NOT LDC_TARGET_PRESET STREQUAL "")
|
||||
if(LDC_TARGET_PRESET MATCHES "Android")
|
||||
set(ANDROID_API "21")
|
||||
endif()
|
||||
# This initial RT_CFLAGS/LD_FLAGS configuration for Android is a
|
||||
# convenience for natively compiling, because CMake cannot detect
|
||||
# Android as a separate platform from Linux.
|
||||
if(RT_CFLAGS STREQUAL "" AND LDC_TARGET_PRESET MATCHES "Android")
|
||||
set(RT_CFLAGS_UNCONFIGURED True)
|
||||
set(RT_CFLAGS "-ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -g -DNDEBUG -DANDROID -D__ANDROID_API__=${ANDROID_API} -Wa,--noexecstack -Wformat -Werror=format-security -fpie")
|
||||
|
||||
if(LDC_TARGET_PRESET MATCHES "arm")
|
||||
append("-target armv7-none-linux-androideabi${ANDROID_API} -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Os" RT_CFLAGS)
|
||||
elseif(LDC_TARGET_PRESET MATCHES "aarch64")
|
||||
append("-target aarch64-none-linux-android -O2" RT_CFLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LD_FLAGS STREQUAL "" AND LDC_TARGET_PRESET MATCHES "Android")
|
||||
set(LD_FLAGS_UNCONFIGURED True)
|
||||
set(LD_FLAGS "-Wl,--gc-sections -Wl,-z,nocopyreloc -no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -fpie -pie")
|
||||
|
||||
if(LDC_TARGET_PRESET MATCHES "arm")
|
||||
append("-target armv7-none-linux-androideabi${ANDROID_API} -Wl,--fix-cortex-a8" LD_FLAGS)
|
||||
elseif(LDC_TARGET_PRESET MATCHES "aarch64")
|
||||
append("-target aarch64-none-linux-android" LD_FLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LDC_TARGET_PRESET MATCHES "Windows")
|
||||
set(TARGET_SYSTEM "Windows;MSVC")
|
||||
if(LDC_TARGET_PRESET MATCHES "x64")
|
||||
# stub example, fill in with the rest
|
||||
list(APPEND D_FLAGS "-mtriple=x86_64-pc-windows-msvc")
|
||||
endif()
|
||||
elseif(LDC_TARGET_PRESET MATCHES "Android")
|
||||
set(TARGET_SYSTEM "Android;Linux;UNIX")
|
||||
|
||||
# Check if we're using the NDK by looking for the toolchains
|
||||
# directory in CC
|
||||
if(CMAKE_C_COMPILER MATCHES "toolchains")
|
||||
# Extract the NDK path and platform from CC
|
||||
string(REGEX REPLACE ".toolchains.+" "" NDK_PATH ${CMAKE_C_COMPILER})
|
||||
string(REGEX REPLACE ".+/prebuilt/([^/]+)/.+" "\\1" NDK_HOST_PLATFORM ${CMAKE_C_COMPILER})
|
||||
|
||||
if(LDC_TARGET_PRESET MATCHES "arm")
|
||||
set(TARGET_ARCH "arm")
|
||||
set(LLVM_TARGET_TRIPLE "armv7-none-linux-android")
|
||||
set(TOOLCHAIN_TARGET_TRIPLE "arm-linux-androideabi")
|
||||
elseif(LDC_TARGET_PRESET MATCHES "aarch64")
|
||||
set(TARGET_ARCH "arm64")
|
||||
set(LLVM_TARGET_TRIPLE "aarch64-none-linux-android")
|
||||
set(TOOLCHAIN_TARGET_TRIPLE "aarch64-linux-android")
|
||||
else()
|
||||
message(FATAL_ERROR "Android platform ${LDC_TARGET_PRESET} is not supported.")
|
||||
endif()
|
||||
list(APPEND D_FLAGS "-mtriple=${LLVM_TARGET_TRIPLE}")
|
||||
set(TOOLCHAIN_VERSION "4.9")
|
||||
|
||||
if(RT_CFLAGS_UNCONFIGURED)
|
||||
append("-gcc-toolchain ${NDK_PATH}/toolchains/${TOOLCHAIN_TARGET_TRIPLE}-${TOOLCHAIN_VERSION}/prebuilt/${NDK_HOST_PLATFORM} --sysroot ${NDK_PATH}/sysroot -isystem ${NDK_PATH}/sysroot/usr/include/${TOOLCHAIN_TARGET_TRIPLE}" RT_CFLAGS)
|
||||
|
||||
if(LDC_TARGET_PRESET MATCHES "arm")
|
||||
append("-fno-integrated-as" RT_CFLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LD_FLAGS_UNCONFIGURED)
|
||||
set(LD_BFD "-fuse-ld=bfd")
|
||||
# work around Windows bug, android-ndk/ndk#75
|
||||
if(NDK_HOST_PLATFORM MATCHES "windows")
|
||||
set(LD_BFD "${LD_BFD}.exe")
|
||||
endif()
|
||||
|
||||
append("--sysroot=${NDK_PATH}/platforms/android-${ANDROID_API}/arch-${TARGET_ARCH} -gcc-toolchain ${NDK_PATH}/toolchains/${TOOLCHAIN_TARGET_TRIPLE}-${TOOLCHAIN_VERSION}/prebuilt/${NDK_HOST_PLATFORM} ${LD_BFD}" LD_FLAGS)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "LDC_TARGET_PRESET ${LDC_TARGET_PRESET} is not supported yet, pull requests to add common flags are welcome.")
|
||||
endif()
|
||||
endif()
|
|
@ -1 +1 @@
|
|||
Subproject commit 4e6daad2916745dcb426d4211d87fb76536c2c4f
|
||||
Subproject commit b96cff50fcdd944b0648d77170e8cd88b9743e24
|
|
@ -12,6 +12,8 @@ struct Config {
|
|||
string ldcSourceDir;
|
||||
bool ninja;
|
||||
bool buildTestrunners;
|
||||
string targetPreset;
|
||||
string[] targetSystem;
|
||||
string[] dFlags;
|
||||
string[] cFlags;
|
||||
string[] linkerFlags;
|
||||
|
@ -117,10 +119,10 @@ void prepareLdcSource() {
|
|||
removeVersionSuffix("git-");
|
||||
removeVersionSuffix("-dirty");
|
||||
|
||||
const localArchiveFile = "ldc-src.tar.gz";
|
||||
if (!localArchiveFile.exists) {
|
||||
import std.format : format;
|
||||
const url = "https://github.com/ldc-developers/ldc/releases/download/v%1$s/ldc-%1$s-src.tar.gz".format(ldcVersion);
|
||||
const localArchiveFile = "ldc-src.zip";
|
||||
if (!localArchiveFile.exists) {
|
||||
const url = "https://github.com/ldc-developers/ldc/releases/download/v%1$s/ldc-%1$s-src.zip".format(ldcVersion);
|
||||
writefln("Downloading LDC source archive: %s", url);
|
||||
import std.net.curl : download;
|
||||
download(url, localArchiveFile);
|
||||
|
@ -133,28 +135,36 @@ void prepareLdcSource() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!ldcSrc.exists)
|
||||
mkdir(ldcSrc);
|
||||
|
||||
import std.array : split;
|
||||
exec("tar -xzf ldc-src.tar.gz --strip 1 -C ldc-src".split);
|
||||
extractZipArchive(localArchiveFile, ".");
|
||||
rename("ldc-%1$s-src".format(ldcVersion), ldcSrc);
|
||||
}
|
||||
|
||||
void runCMake() {
|
||||
import std.array : byPair, join;
|
||||
import std.array : empty, byPair, join;
|
||||
import std.regex : matchFirst;
|
||||
|
||||
const wd = WorkingDirScope(config.buildDir);
|
||||
|
||||
if(config.dFlags.empty)
|
||||
config.dFlags ~= "-w";
|
||||
|
||||
if(config.targetSystem.empty)
|
||||
config.targetSystem ~= "AUTO";
|
||||
|
||||
string[] args = [
|
||||
"cmake",
|
||||
"-DLDC_EXE_FULL=" ~ config.ldcExecutable,
|
||||
"-DD_VERSION=@D_VERSION@",
|
||||
"-DDMDFE_MINOR_VERSION=@DMDFE_MINOR_VERSION@",
|
||||
"-DDMDFE_PATCH_VERSION=@DMDFE_PATCH_VERSION@",
|
||||
"-DLDC_TARGET_PRESET=" ~ config.targetPreset,
|
||||
"-DTARGET_SYSTEM=" ~ config.targetSystem.join(";"),
|
||||
"-DD_FLAGS=" ~ config.dFlags.join(";"),
|
||||
"-DRT_CFLAGS=" ~ config.cFlags.join(" "),
|
||||
"-DLD_FLAGS=" ~ config.linkerFlags.join(" "),
|
||||
];
|
||||
if(config.targetPreset.matchFirst("^Android"))
|
||||
args ~= ["-DCMAKE_SYSTEM_NAME=Linux", "-DCMAKE_C_COMPILER_WORKS=True"];
|
||||
foreach (pair; config.cmakeVars.byPair)
|
||||
args ~= "-D" ~ pair[0] ~ '=' ~ pair[1];
|
||||
if (config.ninja)
|
||||
|
@ -200,6 +210,23 @@ void exec(string[] command ...) {
|
|||
}
|
||||
}
|
||||
|
||||
void extractZipArchive(string archivePath, string destination) {
|
||||
import std.string : endsWith;
|
||||
import std.zip;
|
||||
|
||||
auto archive = new ZipArchive(std.file.read(archivePath));
|
||||
foreach (name, am; archive.directory) {
|
||||
const destPath = buildNormalizedPath(destination, name);
|
||||
|
||||
const isDir = name.endsWith("/");
|
||||
const destDir = isDir ? destPath : destPath.dirName;
|
||||
mkdirRecurse(destDir);
|
||||
|
||||
if (!isDir)
|
||||
std.file.write(destPath, archive.expand(am));
|
||||
}
|
||||
}
|
||||
|
||||
void parseCommandLine(string[] args) {
|
||||
import std.getopt : arraySep, getopt, defaultGetoptPrinter;
|
||||
|
||||
|
@ -212,6 +239,8 @@ void parseCommandLine(string[] args) {
|
|||
"ldcSrcDir", "Path to LDC source directory (if not specified: downloads & extracts source archive into '<buildDir>/ldc-src')", &config.ldcSourceDir,
|
||||
"ninja", "Use Ninja as CMake build system", &config.ninja,
|
||||
"testrunners", "Build the testrunner executables too", &config.buildTestrunners,
|
||||
"targetPreset","Target configuration preset by LDC devs, e.g. Android-arm", &config.targetPreset,
|
||||
"targetSystem","Target OS/toolchain (separated by ';'), e.g. Windows;MSVC", &config.targetSystem,
|
||||
"dFlags", "LDC flags for the D modules (separated by ';')", &config.dFlags,
|
||||
"cFlags", "C/ASM compiler flags for the handful of C/ASM files (separated by ';')", &config.cFlags,
|
||||
"linkerFlags", "C linker flags for shared libraries and testrunner executables (separated by ';')", &config.linkerFlags,
|
||||
|
@ -237,7 +266,7 @@ void parseCommandLine(string[] args) {
|
|||
" * CMake\n" ~
|
||||
" * either Make or Ninja (recommended, enable with '--ninja')\n" ~
|
||||
" * C toolchain (compiler and linker)\n" ~
|
||||
" * tar (can be worked around via '--ldcSrcDir=path/to/src')\n" ~
|
||||
"--targetPreset currently supports Android-arm or Android-aarch64.\n" ~
|
||||
"All arguments are optional.\n" ~
|
||||
"CMake variables (see runtime/CMakeLists.txt in LDC source) can be specified via arguments like 'VAR=value'.\n",
|
||||
helpInformation.options
|
||||
|
|
|
@ -153,7 +153,17 @@ INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
|||
VALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \
|
||||
INSTR_PROF_COMMA
|
||||
VALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA
|
||||
#ifndef VALUE_RANGE_PROF
|
||||
VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
|
||||
#else /* VALUE_RANGE_PROF */
|
||||
VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) \
|
||||
INSTR_PROF_COMMA
|
||||
VALUE_PROF_FUNC_PARAM(uint64_t, PreciseRangeStart, Type::getInt64Ty(Ctx)) \
|
||||
INSTR_PROF_COMMA
|
||||
VALUE_PROF_FUNC_PARAM(uint64_t, PreciseRangeLast, Type::getInt64Ty(Ctx)) \
|
||||
INSTR_PROF_COMMA
|
||||
VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx))
|
||||
#endif /*VALUE_RANGE_PROF */
|
||||
#undef VALUE_PROF_FUNC_PARAM
|
||||
#undef INSTR_PROF_COMMA
|
||||
/* VALUE_PROF_FUNC_PARAM end */
|
||||
|
@ -174,13 +184,15 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
|
|||
* name hash and the function address.
|
||||
*/
|
||||
VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0)
|
||||
/* For memory intrinsic functions size profiling. */
|
||||
VALUE_PROF_KIND(IPVK_MemOPSize, 1)
|
||||
/* These two kinds must be the last to be
|
||||
* declared. This is to make sure the string
|
||||
* array created with the template can be
|
||||
* indexed with the kind value.
|
||||
*/
|
||||
VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget)
|
||||
VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget)
|
||||
VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize)
|
||||
|
||||
#undef VALUE_PROF_KIND
|
||||
/* VALUE_PROF_KIND end */
|
||||
|
@ -234,6 +246,31 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \
|
|||
/* COVMAP_HEADER end. */
|
||||
|
||||
|
||||
#ifdef INSTR_PROF_SECT_ENTRY
|
||||
#define INSTR_PROF_DATA_DEFINED
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_data, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_cnts, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_name, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_vals, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_covmap, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,")
|
||||
|
||||
#undef INSTR_PROF_SECT_ENTRY
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef INSTR_PROF_VALUE_PROF_DATA
|
||||
#define INSTR_PROF_DATA_DEFINED
|
||||
|
||||
|
@ -610,17 +647,47 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
|||
* specified via command line. */
|
||||
#define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename
|
||||
|
||||
/* section name strings common to all targets other
|
||||
than WIN32 */
|
||||
#define INSTR_PROF_DATA_COMMON __llvm_prf_data
|
||||
#define INSTR_PROF_NAME_COMMON __llvm_prf_names
|
||||
#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts
|
||||
#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
|
||||
#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
|
||||
#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
|
||||
/* Win32 */
|
||||
#define INSTR_PROF_DATA_COFF .lprfd
|
||||
#define INSTR_PROF_NAME_COFF .lprfn
|
||||
#define INSTR_PROF_CNTS_COFF .lprfc
|
||||
#define INSTR_PROF_VALS_COFF .lprfv
|
||||
#define INSTR_PROF_VNODES_COFF .lprfnd
|
||||
#define INSTR_PROF_COVMAP_COFF .lcovmap
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Runtime section names and name strings. */
|
||||
#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data
|
||||
#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names
|
||||
#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals
|
||||
#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF
|
||||
/* Value profile nodes section. */
|
||||
#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap
|
||||
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
|
||||
#else
|
||||
/* Runtime section names and name strings. */
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON
|
||||
/* Value profile nodes section. */
|
||||
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON
|
||||
#endif
|
||||
|
||||
#define INSTR_PROF_DATA_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME)
|
||||
|
@ -649,6 +716,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
|||
#define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target
|
||||
#define INSTR_PROF_VALUE_PROF_FUNC_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC)
|
||||
#define INSTR_PROF_VALUE_RANGE_PROF_FUNC __llvm_profile_instrument_range
|
||||
#define INSTR_PROF_VALUE_RANGE_PROF_FUNC_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALUE_RANGE_PROF_FUNC)
|
||||
|
||||
/* InstrProfile per-function control data alignment. */
|
||||
#define INSTR_PROF_DATA_ALIGNMENT 8
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
COMPILER_RT_WEAK uint64_t INSTR_PROF_RAW_VERSION_VAR = INSTR_PROF_RAW_VERSION;
|
||||
|
||||
COMPILER_RT_WEAK char INSTR_PROF_PROFILE_NAME_VAR[1] = {0};
|
||||
|
||||
COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) {
|
||||
return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64)
|
||||
: (INSTR_PROF_RAW_MAGIC_32);
|
||||
|
|
|
@ -45,15 +45,24 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
|
|||
(CountersEnd - CountersBegin) * sizeof(uint64_t) + NamesSize + Padding;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer) {
|
||||
BufferWriter->Write = lprofBufferWriter;
|
||||
BufferWriter->WriterCtx = Buffer;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
|
||||
return lprofWriteData(lprofBufferWriter, Buffer, 0);
|
||||
ProfDataWriter BufferWriter;
|
||||
initBufferWriter(&BufferWriter, Buffer);
|
||||
return lprofWriteData(&BufferWriter, 0, 0);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
||||
char *Buffer, const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
|
||||
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
|
||||
return lprofWriteDataImpl(lprofBufferWriter, Buffer, DataBegin, DataEnd,
|
||||
CountersBegin, CountersEnd, 0, NamesBegin,
|
||||
NamesEnd);
|
||||
ProfDataWriter BufferWriter;
|
||||
initBufferWriter(&BufferWriter, Buffer);
|
||||
return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
|
||||
CountersEnd, 0, NamesBegin, NamesEnd, 0);
|
||||
}
|
||||
|
|
|
@ -91,24 +91,39 @@ static const char *getCurFilename(char *FilenameBuf);
|
|||
static unsigned doMerging() { return lprofCurFilename.MergePoolSize; }
|
||||
|
||||
/* Return 1 if there is an error, otherwise return 0. */
|
||||
static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
||||
void **WriterCtx) {
|
||||
static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
|
||||
uint32_t NumIOVecs) {
|
||||
uint32_t I;
|
||||
FILE *File = (FILE *)*WriterCtx;
|
||||
FILE *File = (FILE *)This->WriterCtx;
|
||||
for (I = 0; I < NumIOVecs; I++) {
|
||||
if (IOVecs[I].Data) {
|
||||
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
|
||||
IOVecs[I].NumElm)
|
||||
return 1;
|
||||
} else {
|
||||
if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void initFileWriter(ProfDataWriter *This, FILE *File) {
|
||||
This->Write = fileWriter;
|
||||
This->WriterCtx = File;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY ProfBufferIO *
|
||||
lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
|
||||
FreeHook = &free;
|
||||
DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
|
||||
VPBufferSize = BufferSz;
|
||||
return lprofCreateBufferIO(fileWriter, File);
|
||||
ProfDataWriter *fileWriter =
|
||||
(ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
|
||||
initFileWriter(fileWriter, File);
|
||||
ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
|
||||
IO->OwnFileWriter = 1;
|
||||
return IO;
|
||||
}
|
||||
|
||||
static void setupIOBuffer() {
|
||||
|
@ -122,9 +137,10 @@ static void setupIOBuffer() {
|
|||
|
||||
/* Read profile data in \c ProfileFile and merge with in-memory
|
||||
profile counters. Returns -1 if there is fatal error, otheriwse
|
||||
0 is returned.
|
||||
0 is returned. Returning 0 does not mean merge is actually
|
||||
performed. If merge is actually done, *MergeDone is set to 1.
|
||||
*/
|
||||
static int doProfileMerging(FILE *ProfileFile) {
|
||||
static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
|
||||
uint64_t ProfileFileSize;
|
||||
char *ProfileBuffer;
|
||||
|
||||
|
@ -169,9 +185,21 @@ static int doProfileMerging(FILE *ProfileFile) {
|
|||
__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
|
||||
(void)munmap(ProfileBuffer, ProfileFileSize);
|
||||
|
||||
*MergeDone = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the directory holding the file, if needed. */
|
||||
static void createProfileDir(const char *Filename) {
|
||||
size_t Length = strlen(Filename);
|
||||
if (lprofFindFirstDirSeparator(Filename)) {
|
||||
char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
|
||||
strncpy(Copy, Filename, Length + 1);
|
||||
__llvm_profile_recursive_mkdir(Copy);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the profile data for merging. It opens the file in r+b mode with
|
||||
* file locking. If the file has content which is compatible with the
|
||||
* current process, it also reads in the profile data in the file and merge
|
||||
|
@ -180,23 +208,23 @@ static int doProfileMerging(FILE *ProfileFile) {
|
|||
* dumper. With profile merging enabled, each executable as well as any of
|
||||
* its instrumented shared libraries dump profile data into their own data file.
|
||||
*/
|
||||
static FILE *openFileForMerging(const char *ProfileFileName) {
|
||||
static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
|
||||
FILE *ProfileFile;
|
||||
int rc;
|
||||
|
||||
createProfileDir(ProfileFileName);
|
||||
ProfileFile = lprofOpenFileEx(ProfileFileName);
|
||||
if (!ProfileFile)
|
||||
return NULL;
|
||||
|
||||
rc = doProfileMerging(ProfileFile);
|
||||
if (rc || COMPILER_RT_FTRUNCATE(ProfileFile, 0L) ||
|
||||
rc = doProfileMerging(ProfileFile, MergeDone);
|
||||
if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
|
||||
fseek(ProfileFile, 0L, SEEK_SET) == -1) {
|
||||
PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
|
||||
strerror(errno));
|
||||
fclose(ProfileFile);
|
||||
return NULL;
|
||||
}
|
||||
fseek(ProfileFile, 0L, SEEK_SET);
|
||||
return ProfileFile;
|
||||
}
|
||||
|
||||
|
@ -205,17 +233,20 @@ static int writeFile(const char *OutputName) {
|
|||
int RetVal;
|
||||
FILE *OutputFile;
|
||||
|
||||
int MergeDone = 0;
|
||||
if (!doMerging())
|
||||
OutputFile = fopen(OutputName, "ab");
|
||||
else
|
||||
OutputFile = openFileForMerging(OutputName);
|
||||
OutputFile = openFileForMerging(OutputName, &MergeDone);
|
||||
|
||||
if (!OutputFile)
|
||||
return -1;
|
||||
|
||||
FreeHook = &free;
|
||||
setupIOBuffer();
|
||||
RetVal = lprofWriteData(fileWriter, OutputFile, lprofGetVPDataReader());
|
||||
ProfDataWriter fileWriter;
|
||||
initFileWriter(&fileWriter, OutputFile);
|
||||
RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
|
||||
|
||||
fclose(OutputFile);
|
||||
return RetVal;
|
||||
|
@ -233,18 +264,13 @@ static void truncateCurrentFile(void) {
|
|||
if (!Filename)
|
||||
return;
|
||||
|
||||
/* Create the directory holding the file, if needed. */
|
||||
if (lprofFindFirstDirSeparator(Filename)) {
|
||||
char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
|
||||
strncpy(Copy, Filename, Length + 1);
|
||||
__llvm_profile_recursive_mkdir(Copy);
|
||||
}
|
||||
|
||||
/* By pass file truncation to allow online raw profile
|
||||
* merging. */
|
||||
if (lprofCurFilename.MergePoolSize)
|
||||
return;
|
||||
|
||||
createProfileDir(Filename);
|
||||
|
||||
/* Truncate the file. Later we'll reopen and append. */
|
||||
File = fopen(Filename, "w");
|
||||
if (!File)
|
||||
|
@ -524,6 +550,7 @@ int __llvm_profile_write_file(void) {
|
|||
int rc, Length;
|
||||
const char *Filename;
|
||||
char *FilenameBuf;
|
||||
int PDeathSig = 0;
|
||||
|
||||
if (lprofProfileDumped()) {
|
||||
PROF_NOTE("Profile data not written to file: %s.\n",
|
||||
|
@ -550,10 +577,18 @@ int __llvm_profile_write_file(void) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Temporarily suspend getting SIGKILL when the parent exits.
|
||||
PDeathSig = lprofSuspendSigKill();
|
||||
|
||||
/* Write profile data to the file. */
|
||||
rc = writeFile(Filename);
|
||||
if (rc)
|
||||
PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
|
||||
|
||||
// Restore SIGKILL.
|
||||
if (PDeathSig == 1)
|
||||
lprofRestoreSigKill();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,17 +48,21 @@ typedef struct ProfDataIOVec {
|
|||
size_t NumElm;
|
||||
} ProfDataIOVec;
|
||||
|
||||
typedef uint32_t (*WriterCallback)(ProfDataIOVec *, uint32_t NumIOVecs,
|
||||
void **WriterCtx);
|
||||
struct ProfDataWriter;
|
||||
typedef uint32_t (*WriterCallback)(struct ProfDataWriter *This, ProfDataIOVec *,
|
||||
uint32_t NumIOVecs);
|
||||
|
||||
typedef struct ProfDataWriter {
|
||||
WriterCallback Write;
|
||||
void *WriterCtx;
|
||||
} ProfDataWriter;
|
||||
|
||||
/*!
|
||||
* The data structure for buffered IO of profile data.
|
||||
*/
|
||||
typedef struct ProfBufferIO {
|
||||
/* File handle. */
|
||||
void *File;
|
||||
/* Low level IO callback. */
|
||||
WriterCallback FileWriter;
|
||||
ProfDataWriter *FileWriter;
|
||||
uint32_t OwnFileWriter;
|
||||
/* The start of the buffer. */
|
||||
uint8_t *BufferStart;
|
||||
/* Total size of the buffer. */
|
||||
|
@ -73,7 +77,7 @@ ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t BufferSz);
|
|||
/*!
|
||||
* This is the interface to create a handle for buffered IO.
|
||||
*/
|
||||
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File);
|
||||
ProfBufferIO *lprofCreateBufferIO(ProfDataWriter *FileWriter);
|
||||
|
||||
/*!
|
||||
* The interface to destroy the bufferIO handle and reclaim
|
||||
|
@ -96,8 +100,9 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
|
|||
/* The low level interface to write data into a buffer. It is used as the
|
||||
* callback by other high level writer methods such as buffered IO writer
|
||||
* and profile data writer. */
|
||||
uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
||||
void **WriterCtx);
|
||||
uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
|
||||
uint32_t NumIOVecs);
|
||||
void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer);
|
||||
|
||||
struct ValueProfData;
|
||||
struct ValueProfRecord;
|
||||
|
@ -133,15 +138,17 @@ typedef struct VPDataReaderType {
|
|||
uint32_t N);
|
||||
} VPDataReaderType;
|
||||
|
||||
int lprofWriteData(WriterCallback Writer, void *WriterCtx,
|
||||
VPDataReaderType *VPDataReader);
|
||||
int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||
/* Write profile data to destinitation. If SkipNameDataWrite is set to 1,
|
||||
the name data is already in destintation, we just skip over it. */
|
||||
int lprofWriteData(ProfDataWriter *Writer, VPDataReaderType *VPDataReader,
|
||||
int SkipNameDataWrite);
|
||||
int lprofWriteDataImpl(ProfDataWriter *Writer,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const uint64_t *CountersBegin,
|
||||
const uint64_t *CountersEnd,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd);
|
||||
const char *NamesEnd, int SkipNameDataWrite);
|
||||
|
||||
/* Merge value profile data pointed to by SrcValueProfData into
|
||||
* in-memory profile counters pointed by to DstData. */
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//===- InstrProfilingNameVar.c - profile name variable setup --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/*===- InstrProfilingNameVar.c - profile name variable setup -------------===*\
|
||||
|*
|
||||
|* The LLVM Compiler Infrastructure
|
||||
|*
|
||||
|* This file is distributed under the University of Illinois Open Source
|
||||
|* License. See LICENSE.TXT for details.
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "InstrProfiling.h"
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <signal.h>
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void __llvm_profile_recursive_mkdir(char *path) {
|
||||
int i;
|
||||
|
@ -219,3 +224,21 @@ COMPILER_RT_VISIBILITY const char *lprofFindLastDirSeparator(const char *Path) {
|
|||
#endif
|
||||
return Sep;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int lprofSuspendSigKill() {
|
||||
#if defined(__linux__)
|
||||
int PDeachSig = 0;
|
||||
/* Temporarily suspend getting SIGKILL upon exit of the parent process. */
|
||||
if (prctl(PR_GET_PDEATHSIG, &PDeachSig) == 0 && PDeachSig == SIGKILL)
|
||||
prctl(PR_SET_PDEATHSIG, 0);
|
||||
return (PDeachSig == SIGKILL);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY void lprofRestoreSigKill() {
|
||||
#if defined(__linux__)
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -51,4 +51,12 @@ int lprofGetHostName(char *Name, int Len);
|
|||
unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
|
||||
void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
|
||||
|
||||
/* Temporarily suspend SIGKILL. Return value of 1 means a restore is needed.
|
||||
* Other return values mean no restore is needed.
|
||||
*/
|
||||
int lprofSuspendSigKill();
|
||||
|
||||
/* Restore previously suspended SIGKILL. */
|
||||
void lprofRestoreSigKill();
|
||||
|
||||
#endif /* PROFILE_INSTRPROFILINGUTIL_H */
|
||||
|
|
|
@ -219,6 +219,35 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The target values are partitioned into multiple regions/ranges. There is one
|
||||
* contiguous region which is precise -- every value in the range is tracked
|
||||
* individually. A value outside the precise region will be collapsed into one
|
||||
* value depending on the region it falls in.
|
||||
*
|
||||
* There are three regions:
|
||||
* 1. (-inf, PreciseRangeStart) and (PreciseRangeLast, LargeRangeValue) belong
|
||||
* to one region -- all values here should be mapped to one value of
|
||||
* "PreciseRangeLast + 1".
|
||||
* 2. [PreciseRangeStart, PreciseRangeLast]
|
||||
* 3. Large values: [LargeValue, +inf) maps to one value of LargeValue.
|
||||
*
|
||||
* The range for large values is optional. The default value of INT64_MIN
|
||||
* indicates it is not specified.
|
||||
*/
|
||||
COMPILER_RT_VISIBILITY void __llvm_profile_instrument_range(
|
||||
uint64_t TargetValue, void *Data, uint32_t CounterIndex,
|
||||
int64_t PreciseRangeStart, int64_t PreciseRangeLast, int64_t LargeValue) {
|
||||
|
||||
if (LargeValue != INT64_MIN && (int64_t)TargetValue >= LargeValue)
|
||||
TargetValue = LargeValue;
|
||||
else if ((int64_t)TargetValue < PreciseRangeStart ||
|
||||
(int64_t)TargetValue > PreciseRangeLast)
|
||||
TargetValue = PreciseRangeLast + 1;
|
||||
|
||||
__llvm_profile_instrument_target(TargetValue, Data, CounterIndex);
|
||||
}
|
||||
|
||||
/*
|
||||
* A wrapper struct that represents value profile runtime data.
|
||||
* Like InstrProfRecord class which is used by profiling host tools,
|
||||
|
|
|
@ -31,41 +31,44 @@ COMPILER_RT_VISIBILITY uint32_t VPBufferSize = 0;
|
|||
/* The buffer writer is reponsponsible in keeping writer state
|
||||
* across the call.
|
||||
*/
|
||||
COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs,
|
||||
uint32_t NumIOVecs,
|
||||
void **WriterCtx) {
|
||||
COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataWriter *This,
|
||||
ProfDataIOVec *IOVecs,
|
||||
uint32_t NumIOVecs) {
|
||||
uint32_t I;
|
||||
char **Buffer = (char **)WriterCtx;
|
||||
char **Buffer = (char **)&This->WriterCtx;
|
||||
for (I = 0; I < NumIOVecs; I++) {
|
||||
size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
|
||||
if (IOVecs[I].Data)
|
||||
memcpy(*Buffer, IOVecs[I].Data, Length);
|
||||
*Buffer += Length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter,
|
||||
void *File, uint8_t *Buffer, uint32_t BufferSz) {
|
||||
BufferIO->File = File;
|
||||
static void llvmInitBufferIO(ProfBufferIO *BufferIO, ProfDataWriter *FileWriter,
|
||||
uint8_t *Buffer, uint32_t BufferSz) {
|
||||
BufferIO->FileWriter = FileWriter;
|
||||
BufferIO->OwnFileWriter = 0;
|
||||
BufferIO->BufferStart = Buffer;
|
||||
BufferIO->BufferSz = BufferSz;
|
||||
BufferIO->CurOffset = 0;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY ProfBufferIO *
|
||||
lprofCreateBufferIO(WriterCallback FileWriter, void *File) {
|
||||
lprofCreateBufferIO(ProfDataWriter *FileWriter) {
|
||||
uint8_t *Buffer = DynamicBufferIOBuffer;
|
||||
uint32_t BufferSize = VPBufferSize;
|
||||
if (!Buffer) {
|
||||
Buffer = &BufferIOBuffer[0];
|
||||
BufferSize = sizeof(BufferIOBuffer);
|
||||
}
|
||||
llvmInitBufferIO(&TheBufferIO, FileWriter, File, Buffer, BufferSize);
|
||||
llvmInitBufferIO(&TheBufferIO, FileWriter, Buffer, BufferSize);
|
||||
return &TheBufferIO;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
|
||||
if (BufferIO->OwnFileWriter)
|
||||
FreeHook(BufferIO->FileWriter);
|
||||
if (DynamicBufferIOBuffer) {
|
||||
FreeHook(DynamicBufferIOBuffer);
|
||||
DynamicBufferIOBuffer = 0;
|
||||
|
@ -83,13 +86,16 @@ lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) {
|
|||
/* Special case, bypass the buffer completely. */
|
||||
ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}};
|
||||
if (Size > BufferIO->BufferSz) {
|
||||
if (BufferIO->FileWriter(IO, 1, &BufferIO->File))
|
||||
if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
|
||||
return -1;
|
||||
} else {
|
||||
/* Write the data to buffer */
|
||||
uint8_t *Buffer = BufferIO->BufferStart + BufferIO->CurOffset;
|
||||
lprofBufferWriter(IO, 1, (void **)&Buffer);
|
||||
BufferIO->CurOffset = Buffer - BufferIO->BufferStart;
|
||||
ProfDataWriter BufferWriter;
|
||||
initBufferWriter(&BufferWriter, (char *)Buffer);
|
||||
lprofBufferWriter(&BufferWriter, IO, 1);
|
||||
BufferIO->CurOffset =
|
||||
(uint8_t *)BufferWriter.WriterCtx - BufferIO->BufferStart;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -98,7 +104,7 @@ COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
|
|||
if (BufferIO->CurOffset) {
|
||||
ProfDataIOVec IO[] = {
|
||||
{BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}};
|
||||
if (BufferIO->FileWriter(IO, 1, &BufferIO->File))
|
||||
if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
|
||||
return -1;
|
||||
BufferIO->CurOffset = 0;
|
||||
}
|
||||
|
@ -201,7 +207,7 @@ static int writeOneValueProfData(ProfBufferIO *BufferIO,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
||||
static int writeValueProfData(ProfDataWriter *Writer,
|
||||
VPDataReaderType *VPDataReader,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd) {
|
||||
|
@ -211,7 +217,7 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
|||
if (!VPDataReader)
|
||||
return 0;
|
||||
|
||||
BufferIO = lprofCreateBufferIO(Writer, WriterCtx);
|
||||
BufferIO = lprofCreateBufferIO(Writer);
|
||||
|
||||
for (DI = DataBegin; DI < DataEnd; DI++) {
|
||||
if (writeOneValueProfData(BufferIO, VPDataReader, DI))
|
||||
|
@ -225,9 +231,9 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
|
||||
void *WriterCtx,
|
||||
VPDataReaderType *VPDataReader) {
|
||||
COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
|
||||
VPDataReaderType *VPDataReader,
|
||||
int SkipNameDataWrite) {
|
||||
/* Match logic in __llvm_profile_write_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
|
@ -235,18 +241,17 @@ COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
|
|||
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *NamesBegin = __llvm_profile_begin_names();
|
||||
const char *NamesEnd = __llvm_profile_end_names();
|
||||
return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
|
||||
CountersBegin, CountersEnd, VPDataReader,
|
||||
NamesBegin, NamesEnd);
|
||||
return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin,
|
||||
CountersEnd, VPDataReader, NamesBegin, NamesEnd,
|
||||
SkipNameDataWrite);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int
|
||||
lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd) {
|
||||
const char *NamesEnd, int SkipNameDataWrite) {
|
||||
|
||||
/* Calculate size of sections. */
|
||||
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
|
@ -268,14 +273,14 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
|||
#include "InstrProfData.inc"
|
||||
|
||||
/* Write the data. */
|
||||
ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1},
|
||||
ProfDataIOVec IOVec[] = {
|
||||
{&Header, sizeof(__llvm_profile_header), 1},
|
||||
{DataBegin, sizeof(__llvm_profile_data), DataSize},
|
||||
{CountersBegin, sizeof(uint64_t), CountersSize},
|
||||
{NamesBegin, sizeof(uint8_t), NamesSize},
|
||||
{SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize},
|
||||
{Zeroes, sizeof(uint8_t), Padding}};
|
||||
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
|
||||
if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec)))
|
||||
return -1;
|
||||
|
||||
return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
|
||||
DataEnd);
|
||||
return writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd);
|
||||
}
|
||||
|
|
|
@ -519,8 +519,10 @@ void __llvm_profile_initialize_file(void) {
|
|||
|
||||
EnvFilenamePat = getFilenamePatFromEnv();
|
||||
if (EnvFilenamePat) {
|
||||
SelectedPat = EnvFilenamePat;
|
||||
PNS = PNS_environment;
|
||||
/* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
|
||||
at the moment when __llvm_profile_write_file() gets executed. */
|
||||
parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
|
||||
return;
|
||||
} else if (hasCommandLineOverrider) {
|
||||
SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
|
||||
PNS = PNS_command_line;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//===- InstrProfilingNameVar.c - profile name variable setup --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/*===- InstrProfilingNameVar.c - profile name variable setup -------------===*\
|
||||
|*
|
||||
|* The LLVM Compiler Infrastructure
|
||||
|*
|
||||
|* This file is distributed under the University of Illinois Open Source
|
||||
|* License. See LICENSE.TXT for details.
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "InstrProfiling.h"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// REQUIRES: target_SPIRV
|
||||
// RUN: %ldc -c -mdcompute-targets=ocl-220 -m64 -output-ll -output-o %s && FileCheck %s --check-prefix=LL < kernels_ocl220_64.ll \
|
||||
// RUN: && %llvm-spirv -to-text kernels_ocl220_64.spv && FileCheck %s --check-prefix=SPT < kernels_ocl220_64.spt
|
||||
// RUN: %ldc -c -mdcompute-targets=ocl-220 -m64 -mdcompute-file-prefix=addrspace -output-ll -output-o %s && FileCheck %s --check-prefix=LL < addrspace_ocl220_64.ll \
|
||||
// RUN: && %llvm-spirv -to-text addrspace_ocl220_64.spv && FileCheck %s --check-prefix=SPT < addrspace_ocl220_64.spt
|
||||
@compute(CompileFor.deviceOnly) module dcompute_cl_addrspaces;
|
||||
import ldc.dcompute;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// REQUIRES: atleast_llvm309
|
||||
// REQUIRES: target_NVPTX
|
||||
// RUN: %ldc -c -mdcompute-targets=cuda-350 -m64 -output-ll -output-o %s && FileCheck %s --check-prefix=LL < kernels_cuda350_64.ll && FileCheck %s --check-prefix=PTX < kernels_cuda350_64.ptx
|
||||
// RUN: %ldc -c -mdcompute-targets=cuda-350 -m64 -mdcompute-file-prefix=addrspace -output-ll -output-o %s && FileCheck %s --check-prefix=LL < addrspace_cuda350_64.ll && FileCheck %s --check-prefix=PTX < addrspace_cuda350_64.ptx
|
||||
@compute(CompileFor.deviceOnly) module dcompute_cu_addrspaces;
|
||||
import ldc.dcompute;
|
||||
|
||||
|
|
16
tests/codegen/dcompute_host_and_device.d
Normal file
16
tests/codegen/dcompute_host_and_device.d
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Check that we can generate code for both the host and device in one compiler invocation
|
||||
// REQUIRES: atleast_llvm309
|
||||
// REQUIRES: target_NVPTX
|
||||
// RUN: %ldc -mdcompute-targets=cuda-350 -mdcompute-file-prefix=host_and_device -Iinputs %s %S/inputs/kernel.d
|
||||
|
||||
import inputs.kernel : foo;
|
||||
|
||||
int tlGlobal;
|
||||
__gshared int gGlobal;
|
||||
|
||||
void main(string[] args)
|
||||
{
|
||||
tlGlobal = 0;
|
||||
gGlobal = 0;
|
||||
string s = foo.mangleof;
|
||||
}
|
5
tests/codegen/inputs/kernel.d
Normal file
5
tests/codegen/inputs/kernel.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
@compute(CompileFor.deviceOnly)
|
||||
module inputs.kernel;
|
||||
|
||||
import ldc.dcompute;
|
||||
@kernel void foo() {}
|
|
@ -13,17 +13,21 @@ import core.simd;
|
|||
// enable case sensitive symbol lookup
|
||||
// CDB: .symopt-1
|
||||
|
||||
struct Small { size_t val; }
|
||||
struct Large { size_t a, b, c, d, e, f, g, h; }
|
||||
|
||||
int byValue(ubyte ub, ushort us, uint ui, ulong ul,
|
||||
float f, double d, real r,
|
||||
cdouble c, int delegate() dg, int function() fun,
|
||||
int[] slice, float[int] aa, ubyte[16] fa,
|
||||
float4 f4, double4 d4,
|
||||
Interface ifc, TypeInfo_Class ti, typeof(null) np)
|
||||
Small small, Large large,
|
||||
TypeInfo_Class ti, typeof(null) np)
|
||||
{
|
||||
// CDB: bp `args_cdb.d:25`
|
||||
// CDB: bp `args_cdb.d:27`
|
||||
// CDB: g
|
||||
// arguments implicitly passed by reference on x64 and not shown if unused
|
||||
float cim = c.im + fa[7] + dg() + ifc.offset;
|
||||
// arguments implicitly passed by reference aren't shown if unused
|
||||
float cim = c.im + fa[7] + dg() + small.val + large.a;
|
||||
return 1;
|
||||
// CHECK: !args_cdb.byValue
|
||||
// CDB: dv /t
|
||||
|
@ -42,12 +46,13 @@ int byValue(ubyte ub, ushort us, uint ui, ulong ul,
|
|||
// CHECK: <function> * fun = {{0x[0-9a-f`]*}}
|
||||
// x86: struct int[] slice =
|
||||
// CHECK: unsigned char * aa = {{0x[0-9a-f`]*}}
|
||||
// "Internal implementation error for fa" with cdb on x64, ok in VS
|
||||
// x64: unsigned char (*)[16] fa
|
||||
// x86: unsigned char [16] fa
|
||||
// x86: float [4] f4 = float [4]
|
||||
// x86: double [4] d4 = double [4]
|
||||
// x64: Interface * ifc
|
||||
// x86: Interface ifc
|
||||
// CHECK: Small small
|
||||
// x64: Large * large
|
||||
// x86: Large large
|
||||
// CHECK: struct TypeInfo_Class * ti = {{0x[0-9a-f`]*}}
|
||||
// CHECK: void * np = {{0x[0`]*}}
|
||||
|
||||
|
@ -64,31 +69,35 @@ int byValue(ubyte ub, ushort us, uint ui, ulong ul,
|
|||
|
||||
// CDB: ?? dg
|
||||
// CHECK: int delegate()
|
||||
// CHECK-NEXT: context
|
||||
// CHECK-NEXT: funcptr
|
||||
// CHECK-NEXT: context :
|
||||
// CHECK-NEXT: funcptr :
|
||||
// CHECK-SAME: args_cdb.main.__lambda
|
||||
|
||||
// CDB: ?? slice
|
||||
// CHECK: struct int[]
|
||||
// CHECK-NEXT: length : 2
|
||||
// CHECK-NEXT: ptr
|
||||
// CHECK-NEXT: ptr :
|
||||
// CHECK-SAME: 0n10
|
||||
|
||||
// CDB: ?? fa[1]
|
||||
// "Internal implementation error for fa" with cdb on x64, ok in VS
|
||||
// no-x86: unsigned char 0x0e (displays 0xf6)
|
||||
// CDB: ?? (*fa)[1]
|
||||
// x64: unsigned char 0x0e
|
||||
// no-x86: would be fa[1], but displays garbage anyway
|
||||
|
||||
// CDB: ?? f4[1]
|
||||
// CHECK: float 16
|
||||
|
||||
// CDB: ?? d4[2]
|
||||
// CDB: ?? d4[1]
|
||||
// CHECK: double 17
|
||||
|
||||
// CDB: ?? ifc
|
||||
// CHECK: Interface
|
||||
// CHECK-NEXT: classinfo
|
||||
// CHECK-NEXT: vtbl
|
||||
// x64-NEXT: offset : 0x12
|
||||
// no-x86-NEXT: offset : 0x12 (displays 0)
|
||||
// CDB: ?? small
|
||||
// CHECK: Small
|
||||
// x64-NEXT: val : 0x12
|
||||
// no-x86-NEXT: val : 0x12 (displays garbage)
|
||||
|
||||
// CDB: ?? large
|
||||
// CHECK: Large
|
||||
// x64-NEXT: a : 0x13
|
||||
// no-x86-NEXT: a : 0x13 (displays garbage)
|
||||
|
||||
// CDB: ?? ti
|
||||
// CHECK: TypeInfo_Class
|
||||
|
@ -100,9 +109,10 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
|
|||
cdouble* c, int delegate()* dg, int function()* fun,
|
||||
int[]* slice, float[int]* aa, ubyte[16]* fa,
|
||||
float4* f4, double4* d4,
|
||||
Interface* ifc, TypeInfo_Class* ti, typeof(null)* np)
|
||||
Small* small, Large* large,
|
||||
TypeInfo_Class* ti, typeof(null)* np)
|
||||
{
|
||||
// CDB: bp `args_cdb.d:106`
|
||||
// CDB: bp `args_cdb.d:115`
|
||||
// CDB: g
|
||||
return 3;
|
||||
// CHECK: !args_cdb.byPtr
|
||||
|
@ -127,8 +137,8 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
|
|||
// CHECK-NEXT: im : 9
|
||||
// CDB: ?? *dg
|
||||
// CHECK: int delegate()
|
||||
// CHECK-NEXT: context
|
||||
// CHECK-NEXT: funcptr
|
||||
// CHECK-NEXT: context :
|
||||
// CHECK-NEXT: funcptr :
|
||||
// CHECK-SAME: args_cdb.main.__lambda
|
||||
// CDB: ?? *fun
|
||||
// CHECK: <function> *
|
||||
|
@ -145,13 +155,16 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
|
|||
// CHECK: float 16
|
||||
// CDB: ?? (*d4)[2]
|
||||
// CHECK: double 17
|
||||
// CDB: ?? *ifc
|
||||
// CHECK: struct Interface
|
||||
// CHECK: offset : 0x12
|
||||
// CDB: ?? *small
|
||||
// CHECK: struct Small
|
||||
// CHECK-NEXT: val : 0x12
|
||||
// CDB: ?? *large
|
||||
// CHECK: struct Large
|
||||
// CHECK-NEXT: a : 0x13
|
||||
// CHECK-NEXT: b :
|
||||
// CDB: ?? *ti
|
||||
// CHECK: struct TypeInfo_Class
|
||||
// CHECK-NEXT: m_init : byte[]
|
||||
// shows bad member values
|
||||
// CDB: ?? *np
|
||||
// CHECK: void * {{0x[0`]*}}
|
||||
}
|
||||
|
@ -161,9 +174,10 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
|
|||
ref cdouble c, ref int delegate() dg, ref int function() fun,
|
||||
ref int[] slice, ref float[int] aa, ref ubyte[16] fa,
|
||||
ref float4 f4, ref double4 d4,
|
||||
ref Interface ifc, ref TypeInfo_Class ti, ref typeof(null) np)
|
||||
ref Small small, ref Large large,
|
||||
ref TypeInfo_Class ti, ref typeof(null) np)
|
||||
{
|
||||
// CDB: bp `args_cdb.d:218`
|
||||
// CDB: bp `args_cdb.d:180`
|
||||
// CDB: g
|
||||
// CHECK: !args_cdb.byRef
|
||||
|
||||
|
@ -189,7 +203,7 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
|
|||
// CHECK-NEXT: im : 9
|
||||
// CDB: ?? *dg
|
||||
// CHECK: int delegate()
|
||||
// CHECK-NEXT: context
|
||||
// CHECK-NEXT: context :
|
||||
// CHECK-NEXT: funcptr : {{0x[0-9a-f`]*}}
|
||||
// CHECK-SAME: args_cdb.main.__lambda
|
||||
// CDB: ?? *fun
|
||||
|
@ -206,16 +220,23 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
|
|||
// CHECK: float 16
|
||||
// CDB: ?? (*d4)[2]
|
||||
// CHECK: double 17
|
||||
// CDB: ?? *ifc
|
||||
// CHECK: struct Interface
|
||||
// CHECK: offset : 0x12
|
||||
// CDB: ?? *small
|
||||
// CHECK: struct Small
|
||||
// CHECK-NEXT: val : 0x12
|
||||
// CDB: ?? *large
|
||||
// CHECK: struct Large
|
||||
// CHECK-NEXT: a : 0x13
|
||||
// CHECK-NEXT: b :
|
||||
// CDB: ?? *ti
|
||||
// CHECK: struct TypeInfo_Class * {{0x[0-9a-f`]*}}
|
||||
// CHECK-NEXT: m_init : byte[]
|
||||
// CDB: ?? *np
|
||||
// CHECK: void * {{0x[0`]*}}
|
||||
// no-CHECK: void * {{0x[0`]*}} (not available)
|
||||
|
||||
// needs access to references to actually generate debug info
|
||||
float cim = c.im + fa[7] + dg() + fun() + slice.length + aa.length + f4[0] + d4[1] +
|
||||
small.val + large.a + ti.initializer.length;
|
||||
|
||||
// needs access to references to actually generate debug info
|
||||
ub++;
|
||||
us++;
|
||||
ui++;
|
||||
|
@ -231,7 +252,8 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
|
|||
fa[0]++;
|
||||
f4.array[0] = f4.array[0] + 1;
|
||||
d4.array[0] = d4.array[0] + 1;
|
||||
ifc = Interface(typeid(Object), null, 18);
|
||||
small.val++;
|
||||
large.a++;
|
||||
ti = typeid(TypeInfo);
|
||||
np = null;
|
||||
return 2;
|
||||
|
@ -254,13 +276,14 @@ int main()
|
|||
ubyte[16] fa; fa[] = 14;
|
||||
float4 f4 = 16;
|
||||
double4 d4 = 17;
|
||||
Interface ifc = Interface(typeid(Object), null, 18);
|
||||
Small small = Small(18);
|
||||
Large large = Large(19);
|
||||
TypeInfo_Class ti = typeid(TypeInfo);
|
||||
typeof(null) np = null;
|
||||
|
||||
byValue(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, ifc, ti, np);
|
||||
byPtr(&ub, &us, &ui, &ul, &f, &d, &r, &c, &dg, &fun, &slice, &aa, &fa, &f4, &d4, &ifc, &ti, &np);
|
||||
byRef(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, ifc, ti, np);
|
||||
byValue(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, small, large, ti, np);
|
||||
byPtr(&ub, &us, &ui, &ul, &f, &d, &r, &c, &dg, &fun, &slice, &aa, &fa, &f4, &d4, &small, &large, &ti, &np);
|
||||
byRef(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, small, large, ti, np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
67
tests/debuginfo/nested_cdb.d
Normal file
67
tests/debuginfo/nested_cdb.d
Normal file
|
@ -0,0 +1,67 @@
|
|||
// REQUIRES: atleast_llvm500
|
||||
// REQUIRES: Windows
|
||||
// REQUIRES: cdb
|
||||
// RUN: %ldc -g -of=%t.exe %s
|
||||
// RUN: sed -e "/^\\/\\/ CDB:/!d" -e "s,// CDB:,," %s \
|
||||
// RUN: | %cdb -snul -lines -y . %t.exe >%t.out
|
||||
// RUN: FileCheck %s -check-prefix=CHECK -check-prefix=%arch < %t.out
|
||||
|
||||
// CDB: ld /f nested_cdb*
|
||||
// enable case sensitive symbol lookup
|
||||
// CDB: .symopt-1
|
||||
|
||||
void encloser(int arg0, ref int arg1)
|
||||
{
|
||||
int enc_n = 123;
|
||||
// CDB: bp `nested_cdb.d:16`
|
||||
// CDB: g
|
||||
// CDB: dv /t
|
||||
// CHECK: int arg0 = 0n1
|
||||
// (cdb displays references as pointers)
|
||||
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
|
||||
// CHECK-NEXT: int enc_n = 0n123
|
||||
// CDB: ?? *arg1
|
||||
// CHECK: int 0n2
|
||||
enc_n += arg1;
|
||||
|
||||
void nested(int nes_i)
|
||||
{
|
||||
int blub = arg0 + arg1 + enc_n;
|
||||
// CDB: bp `nested_cdb.d:30`
|
||||
// CDB: g
|
||||
// CDB: dv /t
|
||||
// CHECK: int arg0 = 0n1
|
||||
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
|
||||
// CHECK-NEXT: int enc_n = 0n125
|
||||
// CDB: ?? *arg1
|
||||
// CHECK: int 0n2
|
||||
arg0 = arg1 = enc_n = nes_i;
|
||||
// CDB: bp `nested_cdb.d:39`
|
||||
// CDB: g
|
||||
// CDB: dv /t
|
||||
// CHECK: int arg0 = 0n456
|
||||
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
|
||||
// CHECK-NEXT: int enc_n = 0n456
|
||||
// CDB: ?? *arg1
|
||||
// CHECK: int 0n456
|
||||
}
|
||||
|
||||
nested(456);
|
||||
// CDB: bp `nested_cdb.d:50`
|
||||
// CDB: g
|
||||
// CDB: dv /t
|
||||
// CHECK: int arg0 = 0n456
|
||||
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
|
||||
// CHECK-NEXT: int enc_n = 0n456
|
||||
// CDB: ?? *arg1
|
||||
// CHECK: int 0n456
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int arg1 = 2;
|
||||
encloser(1, arg1);
|
||||
}
|
||||
|
||||
// CDB: q
|
||||
// CHECK: quit
|
61
tests/debuginfo/nested_gdb.d
Normal file
61
tests/debuginfo/nested_gdb.d
Normal file
|
@ -0,0 +1,61 @@
|
|||
// REQUIRES: gdb
|
||||
// RUN: %ldc %_gdb_dflags -g -of=%t %s
|
||||
// RUN: sed -e "/^\\/\\/ GDB:/!d" -e "s,// GDB:,," %s >%t.gdb
|
||||
// RUN: gdb %t --batch -x %t.gdb >%t.out 2>&1
|
||||
// RUN: FileCheck %s -check-prefix=CHECK < %t.out
|
||||
|
||||
void encloser(int arg0, ref int arg1)
|
||||
{
|
||||
int enc_n = 123;
|
||||
// GDB: b 10
|
||||
// GDB: r
|
||||
// GDB: p arg0
|
||||
// CHECK: $1 = 1
|
||||
// GDB: p arg1
|
||||
// CHECK: $2 = (int &) @{{0x[0-9a-f]*}}: 2
|
||||
// GDB: p enc_n
|
||||
// CHECK: $3 = 123
|
||||
enc_n += arg1;
|
||||
|
||||
void nested(int nes_i)
|
||||
{
|
||||
int blub = arg0 + arg1 + enc_n;
|
||||
// GDB: b 23
|
||||
// GDB: c
|
||||
// GDB: p arg0
|
||||
// CHECK: $4 = 1
|
||||
// GDB: p arg1
|
||||
// CHECK: $5 = (int &) @{{0x[0-9a-f]*}}: 2
|
||||
// GDB: p enc_n
|
||||
// CHECK: $6 = 125
|
||||
arg0 = arg1 = enc_n = nes_i;
|
||||
// GDB: b 32
|
||||
// GDB: c
|
||||
// GDB: p arg0
|
||||
// CHECK: $7 = 456
|
||||
// GDB: p arg1
|
||||
// CHECK: $8 = (int &) @{{0x[0-9a-f]*}}: 456
|
||||
// GDB: p enc_n
|
||||
// CHECK: $9 = 456
|
||||
}
|
||||
|
||||
nested(456);
|
||||
// GDB: b 43
|
||||
// GDB: c
|
||||
// GDB: p arg0
|
||||
// no-CHECK: $10 = 456 (`<optimized out>` for LLVM < 5.0)
|
||||
// GDB: p arg1
|
||||
// CHECK: $11 = (int &) @{{0x[0-9a-f]*}}: 456
|
||||
// GDB: p enc_n
|
||||
// CHECK: $12 = 456
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int arg1 = 2;
|
||||
encloser(1, arg1);
|
||||
}
|
||||
|
||||
// GDB: c
|
||||
// GDB: q
|
||||
// CHECK: exited normally
|
11
tests/driver/inputs/post_switches.conf
Normal file
11
tests/driver/inputs/post_switches.conf
Normal file
|
@ -0,0 +1,11 @@
|
|||
default:
|
||||
{
|
||||
switches = [
|
||||
"-L-normal-switch",
|
||||
"-L-normal-two-switch"
|
||||
];
|
||||
post-switches = [
|
||||
"-L-post-switch",
|
||||
"-L-post-two-switch"
|
||||
];
|
||||
};
|
21
tests/driver/post_switches.d
Normal file
21
tests/driver/post_switches.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
// RUN: not %ldc -I=%runtimedir/src -conf=%S/inputs/post_switches.conf %s -v -L-user-passed-switch | FileCheck %s
|
||||
|
||||
// CHECK: -normal-switch
|
||||
// CHECK-SAME: -normal-two-switch
|
||||
// CHECK-SAME: -user-passed-switch
|
||||
// CHECK-SAME: -post-switch
|
||||
// CHECK-SAME: -post-two-switch
|
||||
|
||||
|
||||
// RUN: not %ldc -I=%runtimedir/src -conf=%S/inputs/post_switches.conf -v -L-user-passed-switch -run %s -L-after-run | FileCheck %s --check-prefix=WITHrUN
|
||||
|
||||
// WITHrUN: -normal-switch
|
||||
// WITHrUN-SAME: -normal-two-switch
|
||||
// WITHrUN-SAME: -user-passed-switch
|
||||
// WITHrUN-SAME: -post-switch
|
||||
// WITHrUN-SAME: -post-two-switch
|
||||
// WITHrUN-NOT: -after-run
|
||||
|
||||
void main()
|
||||
{
|
||||
}
|
|
@ -14,6 +14,7 @@ config.ldcprofdata_bin = "@LDCPROFDATA_BIN@"
|
|||
config.ldcprunecache_bin = "@LDCPRUNECACHE_BIN@"
|
||||
config.ldc2_bin_dir = "@LDC2_BIN_DIR@"
|
||||
config.ldc2_lib_dir = "@LDC2_LIB_DIR@"
|
||||
config.ldc2_runtime_dir = "@RUNTIME_DIR@"
|
||||
config.test_source_root = "@TESTS_IR_DIR@"
|
||||
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
|
||||
config.llvm_version = @LDC_LLVM_VER@
|
||||
|
@ -45,6 +46,10 @@ config.excludes = [
|
|||
if not config.with_PGO:
|
||||
config.excludes.append('PGO')
|
||||
|
||||
# Explicit forwarding of environment variables
|
||||
env_cc = os.environ.get('CC', '')
|
||||
if env_cc:
|
||||
config.environment['CC'] = env_cc
|
||||
|
||||
# Define available features so that we can disable tests depending on LLVM version
|
||||
config.available_features.add("llvm%d" % config.llvm_version)
|
||||
|
@ -71,7 +76,8 @@ if (platform.system() == 'Windows') and (config.default_target_bits == 32):
|
|||
if (platform.system() == 'Windows') and (config.default_target_bits == 64):
|
||||
config.available_features.add('Windows_x64')
|
||||
|
||||
# Add "LTO" feature if linker support is available (LTO is supported from LLVM 3.9)
|
||||
# Add "LTO" feature if linker support and LTO plugin are available
|
||||
# (LTO is supported from LLVM 3.9)
|
||||
canDoLTO = False
|
||||
if (config.llvm_version >= 309):
|
||||
if (platform.system() == 'Darwin'):
|
||||
|
@ -79,14 +85,14 @@ if (config.llvm_version >= 309):
|
|||
p = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, universal_newlines=True)
|
||||
text = p.stderr.read()
|
||||
if "LTO support" in text:
|
||||
if ("LTO support" in text and os.path.isfile(config.ldc2_lib_dir + '/libLTO-ldc.dylib')):
|
||||
canDoLTO = True
|
||||
elif (platform.system() == 'Linux'):
|
||||
command = ['ld', '-plugin']
|
||||
p = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, universal_newlines=True)
|
||||
text = p.stderr.read()
|
||||
if "plugin: missing argument" in text:
|
||||
if ("plugin: missing argument" in text and os.path.isfile(config.ldc2_lib_dir + '/LLVMgold-ldc.so')):
|
||||
canDoLTO = True
|
||||
if canDoLTO:
|
||||
config.available_features.add('LTO')
|
||||
|
@ -110,6 +116,7 @@ config.substitutions.append( ('%ldc', config.ldc2_bin) )
|
|||
config.substitutions.append( ('%profdata', config.ldcprofdata_bin) )
|
||||
config.substitutions.append( ('%prunecache', config.ldcprunecache_bin) )
|
||||
config.substitutions.append( ('%llvm-spirv', os.path.join(config.llvm_tools_dir, 'llvm-spirv')) )
|
||||
config.substitutions.append( ('%runtimedir', config.ldc2_runtime_dir ) )
|
||||
|
||||
# Add platform-dependent file extension substitutions
|
||||
if (platform.system() == 'Windows'):
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
bool FuzzMe(const ubyte* data, size_t dataSize)
|
||||
{
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_cmp
|
||||
// CHECK: call {{.*}}_sanitizer_cov_trace_{{(const_)?}}cmp
|
||||
|
||||
return dataSize >= 3 &&
|
||||
data[0] == 'F' &&
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Test Fuzz+ASan functionality
|
||||
|
||||
// REQUIRES: atleast_llvm500
|
||||
// REQUIRES: Fuzzer, ASan
|
||||
|
||||
// See https://github.com/ldc-developers/ldc/issues/2222 for -disable-fp-elim
|
||||
|
@ -8,18 +9,15 @@
|
|||
|
||||
bool FuzzMe(ubyte* data, size_t dataSize)
|
||||
{
|
||||
return dataSize >= 6 &&
|
||||
return dataSize >= 3 &&
|
||||
data[0] == 'F' &&
|
||||
data[1] == 'U' &&
|
||||
data[2] == 'Z' &&
|
||||
data[3] == 'F' &&
|
||||
data[4] == 'U' &&
|
||||
data[5] == 'Z' &&
|
||||
// CHECK: stack-buffer-overflow
|
||||
// CHECK-NEXT: READ of size 1
|
||||
// CHECK-NEXT: #0 {{.*}} in {{.*fuzz_asan6FuzzMe.*}} {{.*}}fuzz_asan.d:
|
||||
// FIXME, debug line info is wrong (Github issue #2090). Once fixed, add [[@LINE+1]]
|
||||
data[6] == 'Z'; // :‑<
|
||||
data[3] == 'Z'; // :‑<
|
||||
}
|
||||
|
||||
extern (C) int LLVMFuzzerTestOneInput(const(ubyte*) data, size_t size)
|
||||
|
@ -33,7 +31,7 @@ extern (C) int LLVMFuzzerTestOneInput(const(ubyte*) data, size_t size)
|
|||
init = true;
|
||||
}
|
||||
|
||||
ubyte[6] stackdata;
|
||||
ubyte[3] stackdata;
|
||||
if (data)
|
||||
{
|
||||
for (auto i = 0; (i < size) && (i < stackdata.length); ++i)
|
||||
|
@ -45,5 +43,5 @@ extern (C) int LLVMFuzzerTestOneInput(const(ubyte*) data, size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// The test unit should start with "FUZFUZ"
|
||||
// CHECK: FUZFUZ
|
||||
// The test unit should start with "FUZ"
|
||||
// CHECK: FUZ
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Test basic fuzz test crash
|
||||
|
||||
// REQUIRES: atleast_llvm500
|
||||
// REQUIRES: Fuzzer
|
||||
|
||||
// RUN: %ldc -g -fsanitize=fuzzer %s -of=%t%exe
|
||||
|
@ -9,8 +10,7 @@
|
|||
|
||||
void FuzzMe(const(ubyte*) data, size_t size)
|
||||
{
|
||||
if ((size >= 6) && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z'
|
||||
&& data[3] == 'L' && data[4] == 'D' && data[5] == 'C')
|
||||
if ((size >= 3) && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z')
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
@ -34,5 +34,5 @@ extern (C) int LLVMFuzzerTestOneInput(const(ubyte*) data, size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// The test unit should start with "FUZLDC"
|
||||
// CHECK: FUZLDC
|
||||
// The test unit should start with "FUZ"
|
||||
// CHECK: FUZ
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// Test linking C++ stdlib (or not) with -fsanitize=fuzzer
|
||||
|
||||
// REQUIRES: atleast_llvm500
|
||||
// REQUIRES: Fuzzer
|
||||
|
||||
// RUN: %ldc -v -fsanitize=fuzzer %s | FileCheck %s
|
||||
// RUN: not %ldc -v -fsanitize=fuzzer -link-no-cpp %s | FileCheck %s --check-prefix=NOCPP
|
||||
|
||||
// CHECK: libFuzzer.a
|
||||
// "libFuzzer.a" before LLVM 6.0, "lib(ldc|clang)_rt.fuzzer.*.a" since LLVM 6.0
|
||||
// CHECK: {{(libFuzzer\.a|_rt\.fuzzer.*\.a)}}
|
||||
// CHECK-SAME: -l{{(c|stdc)}}++
|
||||
|
||||
// NOCPP-NOT: -l{{(c|stdc)}}++
|
||||
|
|
|
@ -9,7 +9,7 @@ if (platform.system() == 'Darwin') or (platform.system() == 'Linux'):
|
|||
if m is not None:
|
||||
config.available_features.add('ASan')
|
||||
continue
|
||||
m = re.match('.*Fuzzer.*', file)
|
||||
m = re.match('.*(F|f)uzzer.*', file)
|
||||
if m is not None:
|
||||
config.available_features.add('Fuzzer')
|
||||
continue
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue