Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial test for a mapper that doesn't make too many bindings #20

Draft
wants to merge 15 commits into
base: julia-release/16.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/cmake/modules/AddClang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ macro(add_clang_tool name)
get_target_export_arg(${name} Clang export_to_clangtargets)
install(TARGETS ${name}
${export_to_clangtargets}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
RUNTIME DESTINATION "${LLVM_TOOLS_INSTALL_DIR}"
COMPONENT ${name})

if(NOT LLVM_ENABLE_IDE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ namespace __sanitizer {
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);

unsigned ucontext_t_sz(void *ctx) {
# if SANITIZER_GLIBC && SANITIZER_X64
# if SANITIZER_GLIBC && SANITIZER_X64 && __GLIBC_PREREQ (2, 27)
// Added in Linux kernel 3.4.0, merged to glibc in 2.16
# ifndef FP_XSTATE_MAGIC1
# define FP_XSTATE_MAGIC1 0x46505853U
Expand Down
6 changes: 6 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include "sanitizer_flags.h"
#include "sanitizer_platform_interceptors.h"

#if !defined(__APPLE__)
#include <malloc.h>
#endif

namespace __sanitizer {
#if SANITIZER_INTERCEPT_TLS_GET_ADDR

Expand Down Expand Up @@ -139,6 +143,8 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
tls_beg = header->start;
VReport(2, "__tls_get_addr: glibc >=2.19 suspected; tls={0x%zx 0x%zx}\n",
tls_beg, tls_size);
} else if (uptr size = malloc_usable_size((void *)tls_beg)) {
tls_size = size;
} else {
VReport(2, "__tls_get_addr: Can't guess glibc version\n");
// This may happen inside the DTOR of main thread, so just ignore it.
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/msan/Linux/signal_mcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

void handler(int sig, siginfo_t *info, void *uctx) {
__msan_check_mem_is_initialized(uctx, sizeof(ucontext_t));
#if defined(__GLIBC__) && defined(__x86_64__)
#if defined(__GLIBC__) && defined(__x86_64__) && __GLIBC_PREREQ(2, 27)
auto *mctx = &static_cast<ucontext_t *>(uctx)->uc_mcontext;
if (auto *fpregs = mctx->fpregs) {
// The member names differ across header versions, but the actual layout
Expand Down
156 changes: 156 additions & 0 deletions libunwind/src/CompactUnwinder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,50 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
uint32_t savedRegistersLocations =
EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);

// If we have not stored EBP yet
if (functionStart == registers.getIP()) {
uint64_t rsp = registers.getSP();
// old esp is ebp less return address
registers.setSP(rsp+8);
// pop return address into eip
registers.setIP(addressSpace.get64(rsp));

return UNW_STEP_SUCCESS;
} else if (functionStart + 1 == registers.getIP()) {
uint64_t rsp = registers.getSP();
// old esp is ebp less return address
registers.setSP(rsp + 16);
// pop return address into eip
registers.setIP(addressSpace.get64(rsp + 8));

return UNW_STEP_SUCCESS;
}

// If we're about to return, we've already popped the base pointer
uint8_t b = addressSpace.get8(registers.getIP());

// This is a hack to detect VZEROUPPER but in between popq rbp and ret
// It's not pretty but it works
if (b == 0xC5) {
if ((b = addressSpace.get8(registers.getIP() + 1)) == 0xF8 &&
(b = addressSpace.get8(registers.getIP() + 2)) == 0x77)
b = addressSpace.get8(registers.getIP() + 3);
else
goto skip_ret;
}

if (b == 0xC3 || b == 0xCB || b == 0xC2 || b == 0xCA) {
uint64_t rbp = registers.getSP();
// old esp is ebp less return address
registers.setSP(rbp + 16);
// pop return address into eip
registers.setIP(addressSpace.get64(rbp + 8));

return UNW_STEP_SUCCESS;
}

skip_ret:

uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset;
for (int i = 0; i < 5; ++i) {
switch (savedRegistersLocations & 0x7) {
Expand Down Expand Up @@ -431,6 +475,118 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
}
}
}

// Note that the order of these registers is so that
// registersSaved[0] is the one that will be pushed onto the stack last.
// Thus, if we want to walk this from the top, we need to go in reverse.
assert(regCount <= 6);

// check whether we are still in the prologue
uint64_t curAddr = functionStart;
if (regCount > 0) {
for (int8_t i = (int8_t)(regCount) - 1; i >= 0; --i) {
if (registers.getIP() == curAddr) {
// None of the registers have been modified yet, so we don't need to reload them
framelessUnwind(addressSpace, registers.getSP() + 8 * (regCount - (uint64_t)(i + 1)), registers);
return UNW_STEP_SUCCESS;
} else {
assert(curAddr < registers.getIP());
}


// pushq %rbp and pushq %rbx is 1 byte. Everything else 2
if ((UNWIND_X86_64_REG_RBP == registersSaved[i]) ||
(UNWIND_X86_64_REG_RBX == registersSaved[i]))
curAddr += 1;
else
curAddr += 2;
}
}
if (registers.getIP() == curAddr) {
// None of the registers have been modified yet, so we don't need to reload them
framelessUnwind(addressSpace, registers.getSP() + 8*regCount, registers);
return UNW_STEP_SUCCESS;
} else {
assert(curAddr < registers.getIP());
}


// And now for the epilogue
{
uint8_t i = 0;
uint64_t p = registers.getIP();
uint8_t b = 0;

while (true) {
b = addressSpace.get8(p++);
// This is a hack to detect VZEROUPPER but in between the popq's and ret
// It's not pretty but it works
if (b == 0xC5) {
if ((b = addressSpace.get8(p++)) == 0xF8 && (b = addressSpace.get8(p++)) == 0x77)
b = addressSpace.get8(p++);
else
break;
}
// popq %rbx popq %rbp
if (b == 0x5B || b == 0x5D) {
i++;
} else if (b == 0x41) {
b = addressSpace.get8(p++);
if (b == 0x5C || b == 0x5D || b == 0x5E || b == 0x5F)
i++;
else
break;
} else if (b == 0xC3 || b == 0xCB || b == 0xC2 || b == 0xCA) {
// i pop's haven't happened yet
uint64_t savedRegisters = registers.getSP() + 8 * i;
if (regCount > 0) {
for (int8_t j = (int8_t)(regCount) - 1; j >= (int8_t)(regCount) - i; --j) {
uint64_t addr = savedRegisters - 8 * (regCount - (uint64_t)(j));
switch (registersSaved[j]) {
case UNWIND_X86_64_REG_RBX:
registers.setRBX(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R12:
registers.setR12(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R13:
registers.setR13(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R14:
registers.setR14(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R15:
registers.setR15(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_RBP:
registers.setRBP(addressSpace.get64(addr));
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
"function starting at 0x%llX",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
}
}
framelessUnwind(addressSpace, savedRegisters, registers);
return UNW_STEP_SUCCESS;
} else {
break;
}
}
}

/*
0x10fe2733a: 5b popq %rbx
0x10fe2733b: 41 5c popq %r12
0x10fe2733d: 41 5d popq %r13
0x10fe2733f: 41 5e popq %r14
0x10fe27341: 41 5f popq %r15
0x10fe27343: 5d popq %rbp
*/


uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount;
for (uint32_t i = 0; i < regCount; ++i) {
switch (registersSaved[i]) {
Expand Down
4 changes: 2 additions & 2 deletions lld/cmake/modules/AddLLD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ macro(add_lld_library name)
${export_to_lldtargets}
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
RUNTIME DESTINATION ${LLVM_TOOLS_INSTALL_DIR})

if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES)
add_llvm_install_targets(install-${name}
Expand All @@ -47,7 +47,7 @@ macro(add_lld_tool name)
get_target_export_arg(${name} LLD export_to_lldtargets)
install(TARGETS ${name}
${export_to_lldtargets}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
RUNTIME DESTINATION ${LLVM_TOOLS_INSTALL_DIR}
COMPONENT ${name})

if(NOT CMAKE_CONFIGURATION_TYPES)
Expand Down
11 changes: 10 additions & 1 deletion llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,16 @@ class BasicLayout {
struct ContiguousPageBasedLayoutSizes {
uint64_t StandardSegs = 0;
uint64_t FinalizeSegs = 0;

uint64_t total() const { return StandardSegs + FinalizeSegs; }
};

struct SplitPageBasedLayoutSizes {
uint64_t TextSegs = 0;
uint64_t DataSegs = 0;
uint64_t FinalizeSegs = 0;
uint64_t total() const { return TextSegs + DataSegs + FinalizeSegs; }
};

private:
using SegmentMap = orc::AllocGroupSmallMap<Segment>;

Expand All @@ -266,6 +272,9 @@ class BasicLayout {
Expected<ContiguousPageBasedLayoutSizes>
getContiguousPageBasedLayoutSizes(uint64_t PageSize);

// Same as above but returns the segments split into text, data, and finalize
Expected<SplitPageBasedLayoutSizes>
getSplitPageBasedLayoutSizes(uint64_t PageSize);
/// Returns an iterator over the segments of the layout.
iterator_range<SegmentMap::iterator> segments() {
return {Segments.begin(), Segments.end()};
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25219,6 +25219,7 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS,
!TLI.isOperationLegalOrCustom(TheSelect->getOpcode(),
LLD->getBasePtr().getValueType()))
return false;
return false;

// The loads must not depend on one another.
if (LLD->isPredecessorOf(RLD) || RLD->isPredecessorOf(LLD))
Expand Down
25 changes: 25 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,31 @@ BasicLayout::getContiguousPageBasedLayoutSizes(uint64_t PageSize) {
return SegsSizes;
}

Expected<BasicLayout::SplitPageBasedLayoutSizes>
BasicLayout::getSplitPageBasedLayoutSizes(uint64_t PageSize) {
SplitPageBasedLayoutSizes SegsSizes;

for (auto &KV : segments()) {
auto &AG = KV.first;
auto &Seg = KV.second;

if (Seg.Alignment > PageSize)
return make_error<StringError>("Segment alignment greater than page size",
inconvertibleErrorCode());

uint64_t SegSize = alignTo(Seg.ContentSize + Seg.ZeroFillSize, PageSize);
if (AG.getMemDeallocPolicy() == orc::MemDeallocPolicy::Standard)
if ((AG.getMemProt() & orc::MemProt::Exec) != orc::MemProt::None) // Text
SegsSizes.TextSegs += SegSize;
else // Data
SegsSizes.DataSegs += SegSize;
else
SegsSizes.FinalizeSegs += SegSize;
}

return SegsSizes;
}

Error BasicLayout::apply() {
for (auto &KV : Segments) {
auto &Seg = KV.second;
Expand Down
41 changes: 29 additions & 12 deletions llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,52 +64,69 @@ void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
BasicLayout BL(G);

// find required address space
auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize());
auto SegsSizes = BL.getSplitPageBasedLayoutSizes(Mapper->getPageSize());

if (!SegsSizes) {
OnAllocated(SegsSizes.takeError());
return;
}

auto TotalSize = SegsSizes->total();

auto CompleteAllocation = [this, &G, BL = std::move(BL),
auto CompleteAllocation = [this, &SegsSizes, &G, BL = std::move(BL),
OnAllocated = std::move(OnAllocated)](
Expected<ExecutorAddrRange> Result) mutable {
if (!Result) {
Mutex.unlock();
return OnAllocated(Result.takeError());
}

auto NextSegAddr = Result->Start;

auto DataSegAddr = Result->Start;
ExecutorAddr TextSegAddr(alignDown(Result->End.getValue() - SegsSizes->TextSegs, Mapper->getPageSize()));
auto FinalizeSegAddr = Result->Start + alignTo(SegsSizes->DataSegs,Mapper->getPageSize());
auto FinalizeSegAddrInit = FinalizeSegAddr;
auto TextSegAddrInit = TextSegAddr;
assert((FinalizeSegAddr + SegsSizes->FinalizeSegs) < (TextSegAddr, Mapper->getPageSize()) && "Not enough memory in the slab");
std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;

for (auto &KV : BL.segments()) {
auto &AG = KV.first;
auto &Seg = KV.second;

auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;

Seg.Addr = NextSegAddr;
Seg.WorkingMem = Mapper->prepare(NextSegAddr, TotalSize);
ExecutorAddr *CurrAddr;
if (AG.getMemDeallocPolicy() == orc::MemDeallocPolicy::Standard) {
if ((AG.getMemProt() & orc::MemProt::Exec) != orc::MemProt::None) {
CurrAddr = &TextSegAddr;
} else {
CurrAddr = &DataSegAddr;
}
} else {
CurrAddr = &FinalizeSegAddr;
}

NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
Seg.Addr = *CurrAddr;
Seg.WorkingMem = Mapper->prepare(*CurrAddr, TotalSize);
*CurrAddr += alignTo(TotalSize, Mapper->getPageSize());

MemoryMapper::AllocInfo::SegInfo SI;
SI.Offset = Seg.Addr - Result->Start;
SI.ContentSize = Seg.ContentSize;
SI.ZeroFillSize = Seg.ZeroFillSize;
SI.AG = AG;
SI.WorkingMem = Seg.WorkingMem;

SegInfos.push_back(SI);
}
assert(DataSegAddr < FinalizeSegAddrInit && "Data overwrote the finalize segment");
assert(FinalizeSegAddr < TextSegAddrInit && "Finalize overwrote the text segment");
assert(TextSegAddr < Result->End && "Text overwrote the end of the slab");

UsedMemory.insert({Result->Start, NextSegAddr - Result->Start});

if (NextSegAddr < Result->End) {
UsedMemory.insert({Result->Start, FinalizeSegAddr - Result->Start});
UsedMemory.insert({TextSegAddrInit, Result->End - TextSegAddrInit});
if (FinalizeSegAddr < TextSegAddrInit) {
// Save the remaining memory for reuse in next allocation(s)
AvailableMemory.insert(NextSegAddr, Result->End - 1, true);
AvailableMemory.insert(FinalizeSegAddr, TextSegAddrInit - 1, true);
}
Mutex.unlock();

Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/MC/MCObjectFileInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
MachO::S_ATTR_STRIP_STATIC_SYMS | MachO::S_ATTR_LIVE_SUPPORT,
SectionKind::getReadOnly());

if (T.isOSDarwin() &&
(T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32))
SupportsCompactUnwindWithoutEHFrame = true;
// Disabled for now, since we need to emit EH Frames for stack unwinding in the JIT
// if (T.isOSDarwin() &&
// (T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32))
// SupportsCompactUnwindWithoutEHFrame = true;

switch (Ctx->emitDwarfUnwindInfo()) {
case EmitDwarfUnwindType::Always:
Expand Down