Upgrade to LLVM 11 Stable

This commit is contained in:
Nekotekina 2020-11-02 06:07:58 +03:00
parent 06ecc2ae68
commit 1b8bf081b5
15 changed files with 186 additions and 76 deletions

1
3rdparty/llvm.cmake vendored
View file

@ -11,7 +11,6 @@ if(WITH_LLVM)
option(LLVM_INCLUDE_TESTS OFF) option(LLVM_INCLUDE_TESTS OFF)
option(LLVM_INCLUDE_TOOLS OFF) option(LLVM_INCLUDE_TOOLS OFF)
option(LLVM_INCLUDE_UTILS OFF) option(LLVM_INCLUDE_UTILS OFF)
option(WITH_POLLY OFF)
option(LLVM_CCACHE_BUILD ON) option(LLVM_CCACHE_BUILD ON)
set(CXX_FLAGS_OLD ${CMAKE_CXX_FLAGS}) set(CXX_FLAGS_OLD ${CMAKE_CXX_FLAGS})

View file

@ -285,6 +285,7 @@ asmjit::Runtime& asmjit::get_global_runtime()
#endif #endif
#include "llvm/Support/TargetSelect.h" #include "llvm/Support/TargetSelect.h"
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/ObjectCache.h"

View file

@ -38,7 +38,7 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros"> <PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator> <CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI> <CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../glslang</CmakeCLI>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>$(CmakeCLI) <NMakeBuildCommandLine>$(CmakeCLI)

View file

@ -38,7 +38,7 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros"> <PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator> <CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI> <CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT -DSPIRV-Headers_SOURCE_DIR=$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../spirv-headers')) ../spirv-tools</CmakeCLI>
<PropsAbsPath>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\common_default.props'))</PropsAbsPath> <PropsAbsPath>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\common_default.props'))</PropsAbsPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

2
llvm

@ -1 +1 @@
Subproject commit f5679565d34863e2f5917f6bb6d3867760862a1e Subproject commit 8c02f52a12550c2044fef262c9864ca2e3cc193e

View file

@ -1,7 +1,7 @@
REM You need cmake and python to update the project files REM You need cmake and python to update the project files
REM this script relies on CWD being the path that this script is in REM this script relies on CWD being the path that this script is in
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 16 2019 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_DEFAULT_TARGET_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_HOST_TRIPLE:STRING=x86_64-pc-windows-msvc -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_INTEL_JITEVENTS=ON -DLLVM_ENABLE_Z3_SOLVER=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=10.0 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm
RD /S /Q cmake RD /S /Q cmake
RD /S /Q CMakeFiles RD /S /Q CMakeFiles

View file

@ -39,7 +39,7 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros"> <PropertyGroup Label="UserMacros">
<CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator> <CmakeGenerator>"Visual Studio $(VisualStudioVersion.Substring(0,2))"</CmakeGenerator>
<CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DCMAKE_CXX_STANDARD=20 -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI> <CmakeCLI>cmake -G $(CmakeGenerator) -A x64 -Thost=x64 -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=$(WindowsTargetPlatformVersion) -DLLVM_USE_CRT_DEBUG=MTd -DLLVM_USE_CRT_RELEASE=MT ../llvm</CmakeCLI>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>

View file

@ -74,9 +74,9 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type)
uint s2 = val->getType()->getScalarSizeInBits(); uint s2 = val->getType()->getScalarSizeInBits();
if (type->isVectorTy()) if (type->isVectorTy())
s1 *= type->getVectorNumElements(); s1 *= llvm::cast<llvm::VectorType>(type)->getNumElements();
if (val->getType()->isVectorTy()) if (val->getType()->isVectorTy())
s2 *= val->getType()->getVectorNumElements(); s2 *= llvm::cast<llvm::VectorType>(val->getType())->getNumElements();
if (s1 != s2) if (s1 != s2)
{ {
@ -120,9 +120,9 @@ std::pair<bool, v128> cpu_translator::get_const_vector<v128>(llvm::Value* c, u32
fmt::throw_exception("[0x%x, %u] Not a vector" HERE, a, b); fmt::throw_exception("[0x%x, %u] Not a vector" HERE, a, b);
} }
if (uint sz = llvm::cast<llvm::VectorType>(t)->getBitWidth() - 128) if (auto v = llvm::cast<llvm::VectorType>(t); v->getScalarSizeInBits() * v->getNumElements() != 128)
{ {
fmt::throw_exception("[0x%x, %u] Bad vector size: %u" HERE, a, b, sz + 128); fmt::throw_exception("[0x%x, %u] Bad vector size: i%ux%u" HERE, a, b, v->getScalarSizeInBits(), v->getNumElements());
} }
const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c); const auto cv = llvm::dyn_cast<llvm::ConstantDataVector>(c);
@ -203,7 +203,8 @@ llvm::Constant* cpu_translator::make_const_vector<v128>(v128 v, llvm::Type* t)
return llvm::ConstantInt::get(t, llvm::APInt(128, llvm::makeArrayRef(reinterpret_cast<const u64*>(v._bytes), 2))); return llvm::ConstantInt::get(t, llvm::APInt(128, llvm::makeArrayRef(reinterpret_cast<const u64*>(v._bytes), 2)));
} }
verify(HERE), t->isVectorTy() && llvm::cast<llvm::VectorType>(t)->getBitWidth() == 128; verify(HERE), t->isVectorTy();
verify(HERE), 128 == t->getScalarSizeInBits() * llvm::cast<llvm::VectorType>(t)->getNumElements();
const auto sct = t->getScalarType(); const auto sct = t->getScalarType();

View file

@ -363,7 +363,7 @@ struct llvm_value_t<T[N]> : llvm_value_t<std::conditional_t<(std::extent_v<T> >
} }
else if constexpr (N > 1) else if constexpr (N > 1)
{ {
return llvm::VectorType::get(base::get_type(context), N); return llvm::VectorType::get(base::get_type(context), N, false);
} }
else else
{ {
@ -2283,9 +2283,11 @@ struct llvm_splat
if (auto i = llvm::dyn_cast_or_null<llvm::ShuffleVectorInst>(value)) if (auto i = llvm::dyn_cast_or_null<llvm::ShuffleVectorInst>(value))
{ {
if (llvm::isa<llvm::ConstantAggregateZero>(i->getOperand(2))) if (llvm::isa<llvm::ConstantAggregateZero>(i->getOperand(1)) || llvm::isa<llvm::UndefValue>(i->getOperand(1)))
{ {
if (auto j = llvm::dyn_cast<llvm::InsertElementInst>(i->getOperand(0))) static constexpr int zero_array[llvm_value_t<U>::is_vector]{};
if (auto j = llvm::dyn_cast<llvm::InsertElementInst>(i->getOperand(0)); j && i->getShuffleMask().equals(zero_array))
{ {
if (llvm::cast<llvm::ConstantInt>(j->getOperand(2))->isZero()) if (llvm::cast<llvm::ConstantInt>(j->getOperand(2))->isZero())
{ {
@ -2311,7 +2313,7 @@ struct llvm_zshuffle
using type = std::remove_extent_t<T>[N]; using type = std::remove_extent_t<T>[N];
llvm_expr_t<A1> a1; llvm_expr_t<A1> a1;
u32 index_array[N]; int index_array[N];
static_assert(llvm_value_t<T>::is_vector, "llvm_zshuffle<>: invalid type"); static_assert(llvm_value_t<T>::is_vector, "llvm_zshuffle<>: invalid type");
@ -2334,7 +2336,7 @@ struct llvm_zshuffle
if (auto z = llvm::dyn_cast<llvm::ConstantAggregateZero>(i->getOperand(1)); z && z->getType() == v1->getType()) if (auto z = llvm::dyn_cast<llvm::ConstantAggregateZero>(i->getOperand(1)); z && z->getType() == v1->getType())
{ {
if (llvm::ConstantDataVector::get(value->getContext(), index_array) == i->getOperand(2)) if (i->getShuffleMask().equals(index_array))
{ {
if (auto r1 = a1.match(v1); v1) if (auto r1 = a1.match(v1); v1)
{ {
@ -2356,7 +2358,7 @@ struct llvm_shuffle2
llvm_expr_t<A1> a1; llvm_expr_t<A1> a1;
llvm_expr_t<A2> a2; llvm_expr_t<A2> a2;
u32 index_array[N]; int index_array[N];
static_assert(llvm_value_t<T>::is_vector, "llvm_shuffle2<>: invalid type"); static_assert(llvm_value_t<T>::is_vector, "llvm_shuffle2<>: invalid type");
@ -2382,7 +2384,7 @@ struct llvm_shuffle2
if (v1->getType() == v2->getType() && v1->getType() == llvm_value_t<T>::get_type(v1->getContext())) if (v1->getType() == v2->getType() && v1->getType() == llvm_value_t<T>::get_type(v1->getContext()))
{ {
if (llvm::ConstantDataVector::get(value->getContext(), index_array) == i->getOperand(2)) if (i->getShuffleMask().equals(index_array))
{ {
if (auto r1 = a1.match(v1); v1) if (auto r1 = a1.match(v1); v1)
{ {
@ -2423,7 +2425,7 @@ protected:
// Allow FMA // Allow FMA
bool m_use_fma = false; bool m_use_fma = false;
// Allow Icelake tier AVX-512 // Allow Icelake tier AVX-512
bool m_use_avx512_icl = false; bool m_use_avx512_icl = false;
// IR builder // IR builder
@ -2665,13 +2667,13 @@ public:
template <typename T, typename... Args, typename = std::enable_if_t<llvm_zshuffle<sizeof...(Args), T>::is_ok>> template <typename T, typename... Args, typename = std::enable_if_t<llvm_zshuffle<sizeof...(Args), T>::is_ok>>
static auto zshuffle(T&& v, Args... indices) static auto zshuffle(T&& v, Args... indices)
{ {
return llvm_zshuffle<sizeof...(Args), T>{std::forward<T>(v), {static_cast<u32>(indices)...}}; return llvm_zshuffle<sizeof...(Args), T>{std::forward<T>(v), {static_cast<int>(indices)...}};
} }
template <typename T, typename U, typename... Args, typename = std::enable_if_t<llvm_shuffle2<sizeof...(Args), T, U>::is_ok>> template <typename T, typename U, typename... Args, typename = std::enable_if_t<llvm_shuffle2<sizeof...(Args), T, U>::is_ok>>
static auto shuffle2(T&& v1, U&& v2, Args... indices) static auto shuffle2(T&& v1, U&& v2, Args... indices)
{ {
return llvm_shuffle2<sizeof...(Args), T, U>{std::forward<T>(v1), std::forward<U>(v2), {static_cast<u32>(indices)...}}; return llvm_shuffle2<sizeof...(Args), T, U>{std::forward<T>(v1), std::forward<U>(v2), {static_cast<int>(indices)...}};
} }
// Average: (a + b + 1) >> 1 // Average: (a + b + 1) >> 1
@ -2685,7 +2687,7 @@ public:
const auto cast_op = result.is_sint ? llvm::Instruction::SExt : llvm::Instruction::ZExt; const auto cast_op = result.is_sint ? llvm::Instruction::SExt : llvm::Instruction::ZExt;
llvm::Type* cast_to = m_ir->getIntNTy(result.esize * 2); llvm::Type* cast_to = m_ir->getIntNTy(result.esize * 2);
if constexpr (result.is_vector != 0) if constexpr (result.is_vector != 0)
cast_to = llvm::VectorType::get(cast_to, result.is_vector); cast_to = llvm::VectorType::get(cast_to, result.is_vector, false);
const auto axt = m_ir->CreateCast(cast_op, a.eval(m_ir), cast_to); const auto axt = m_ir->CreateCast(cast_op, a.eval(m_ir), cast_to);
const auto bxt = m_ir->CreateCast(cast_op, b.eval(m_ir), cast_to); const auto bxt = m_ir->CreateCast(cast_op, b.eval(m_ir), cast_to);
@ -2752,7 +2754,7 @@ public:
{ {
value_t<typename T::type> result; value_t<typename T::type> result;
const auto av = a.eval(m_ir); const auto av = a.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rcp.ps", av->getType(), av->getType()).getCallee(), {av}); result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rcp.ps", av->getType(), av->getType()), {av});
return result; return result;
} }
@ -2761,7 +2763,7 @@ public:
{ {
value_t<typename T::type> result; value_t<typename T::type> result;
const auto av = a.eval(m_ir); const auto av = a.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rsqrt.ps", av->getType(), av->getType()).getCallee(), {av}); result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.rsqrt.ps", av->getType(), av->getType()), {av});
return result; return result;
} }
@ -2771,7 +2773,7 @@ public:
value_t<typename T::type> result; value_t<typename T::type> result;
const auto av = a.eval(m_ir); const auto av = a.eval(m_ir);
const auto bv = b.eval(m_ir); const auto bv = b.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.max.ps", av->getType(), av->getType(), av->getType()).getCallee(), {av, bv}); result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.max.ps", av->getType(), av->getType(), av->getType()), {av, bv});
return result; return result;
} }
@ -2781,7 +2783,7 @@ public:
value_t<typename T::type> result; value_t<typename T::type> result;
const auto av = a.eval(m_ir); const auto av = a.eval(m_ir);
const auto bv = b.eval(m_ir); const auto bv = b.eval(m_ir);
result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.min.ps", av->getType(), av->getType(), av->getType()).getCallee(), {av, bv}); result.value = m_ir->CreateCall(m_module->getOrInsertFunction("llvm.x86.sse.min.ps", av->getType(), av->getType(), av->getType()), {av, bv});
return result; return result;
} }
@ -2930,7 +2932,7 @@ struct fmt_unveil<llvm::TypeSize, void>
template <> template <>
inline llvm::Type* cpu_translator::get_type<__m128i>() inline llvm::Type* cpu_translator::get_type<__m128i>()
{ {
return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16); return llvm::VectorType::get(llvm::Type::getInt8Ty(m_context), 16, false);
} }
#ifndef _MSC_VER #ifndef _MSC_VER

View file

@ -30,6 +30,7 @@
#endif #endif
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Host.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"

View file

@ -237,7 +237,7 @@ Value* PPUTranslator::VecHandleDenormal(Value* val)
const auto type = val->getType(); const auto type = val->getType();
const auto value = bitcast(val, GetType<u32[4]>()); const auto value = bitcast(val, GetType<u32[4]>());
const auto mask = SExt(m_ir->CreateICmpEQ(m_ir->CreateAnd(value, Broadcast(RegLoad(m_jm_mask), 4)), ConstantVector::getSplat(4, m_ir->getInt32(0))), GetType<s32[4]>()); const auto mask = SExt(m_ir->CreateICmpEQ(m_ir->CreateAnd(value, Broadcast(RegLoad(m_jm_mask), 4)), ConstantAggregateZero::get(value->getType())), GetType<s32[4]>());
const auto nz = m_ir->CreateLShr(mask, 1); const auto nz = m_ir->CreateLShr(mask, 1);
const auto result = m_ir->CreateAnd(m_ir->CreateNot(nz), value); const auto result = m_ir->CreateAnd(m_ir->CreateNot(nz), value);
@ -282,7 +282,8 @@ Type* PPUTranslator::ScaleType(Type* type, s32 pow2)
verify(HERE), (scaled != 0); verify(HERE), (scaled != 0);
const auto new_type = m_ir->getIntNTy(scaled); const auto new_type = m_ir->getIntNTy(scaled);
return type->isVectorTy() ? VectorType::get(new_type, type->getVectorNumElements()) : cast<Type>(new_type); const auto vec_type = dyn_cast<VectorType>(type);
return vec_type ? VectorType::get(new_type, vec_type->getNumElements(), false) : cast<Type>(new_type);
} }
Value* PPUTranslator::DuplicateExt(Value* arg) Value* PPUTranslator::DuplicateExt(Value* arg)
@ -308,6 +309,8 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const auto type = FunctionType::get(GetType<void>(), {m_thread_type->getPointerTo()}, false); const auto type = FunctionType::get(GetType<void>(), {m_thread_type->getPointerTo()}, false);
const auto block = m_ir->GetInsertBlock(); const auto block = m_ir->GetInsertBlock();
FunctionCallee callee;
if (!indirect) if (!indirect)
{ {
if ((!m_reloc && target < 0x10000) || target >= u64{} - 0x10000) if ((!m_reloc && target < 0x10000) || target >= u64{} - 0x10000)
@ -316,7 +319,7 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
return; return;
} }
indirect = m_module->getOrInsertFunction(fmt::format("__0x%llx", target), type).getCallee(); callee = m_module->getOrInsertFunction(fmt::format("__0x%llx", target), type);
} }
else else
{ {
@ -333,11 +336,11 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const auto pos = m_ir->CreateLShr(indirect, 2, "", true); const auto pos = m_ir->CreateLShr(indirect, 2, "", true);
const auto ptr = m_ir->CreateGEP(m_ir->CreateLoad(m_call), {m_ir->getInt64(0), pos}); const auto ptr = m_ir->CreateGEP(m_ir->CreateLoad(m_call), {m_ir->getInt64(0), pos});
indirect = m_ir->CreateIntToPtr(m_ir->CreateLoad(ptr), type->getPointerTo()); callee = FunctionCallee(type, m_ir->CreateIntToPtr(m_ir->CreateLoad(ptr), type->getPointerTo()));
} }
m_ir->SetInsertPoint(block); m_ir->SetInsertPoint(block);
m_ir->CreateCall(indirect, {m_thread})->setTailCallKind(llvm::CallInst::TCK_Tail); m_ir->CreateCall(callee, {m_thread})->setTailCallKind(llvm::CallInst::TCK_Tail);
m_ir->CreateRetVoid(); m_ir->CreateRetVoid();
} }
@ -455,7 +458,7 @@ Value* PPUTranslator::Broadcast(Value* value, u32 count)
{ {
if (const auto cv = dyn_cast<Constant>(value)) if (const auto cv = dyn_cast<Constant>(value))
{ {
return ConstantVector::getSplat(count, cv); return ConstantVector::getSplat({count, false}, cv);
} }
return m_ir->CreateVectorSplat(count, value); return m_ir->CreateVectorSplat(count, value);
@ -464,10 +467,10 @@ Value* PPUTranslator::Broadcast(Value* value, u32 count)
std::pair<Value*, Value*> PPUTranslator::Saturate(Value* value, CmpInst::Predicate inst, Value* extreme) std::pair<Value*, Value*> PPUTranslator::Saturate(Value* value, CmpInst::Predicate inst, Value* extreme)
{ {
// Modify args // Modify args
if (value->getType()->isVectorTy() && !extreme->getType()->isVectorTy()) if (auto v = dyn_cast<VectorType>(value->getType()); v && !extreme->getType()->isVectorTy())
extreme = Broadcast(extreme, value->getType()->getVectorNumElements()); extreme = Broadcast(extreme, v->getNumElements());
if (extreme->getType()->isVectorTy() && !value->getType()->isVectorTy()) if (auto e = dyn_cast<VectorType>(extreme->getType()); e && !value->getType()->isVectorTy())
value = Broadcast(value, extreme->getType()->getVectorNumElements()); value = Broadcast(value, e->getNumElements());
// Compare args // Compare args
const auto cmp = m_ir->CreateICmp(inst, value, extreme); const auto cmp = m_ir->CreateICmp(inst, value, extreme);
@ -493,9 +496,9 @@ Value* PPUTranslator::Scale(Value* value, s32 scale)
const auto type = value->getType(); const auto type = value->getType();
const auto power = std::pow(2, scale); const auto power = std::pow(2, scale);
if (type->isVectorTy()) if (auto v = dyn_cast<VectorType>(type))
{ {
return m_ir->CreateFMul(value, ConstantVector::getSplat(type->getVectorNumElements(), ConstantFP::get(type->getVectorElementType(), power))); return m_ir->CreateFMul(value, ConstantVector::getSplat({v->getNumElements(), false}, ConstantFP::get(v->getElementType(), power)));
} }
else else
{ {
@ -519,7 +522,7 @@ Value* PPUTranslator::Shuffle(Value* left, Value* right, std::initializer_list<u
{ {
std::vector<u32> data; data.reserve(indices.size()); std::vector<u32> data; data.reserve(indices.size());
const u32 mask = type->getVectorNumElements() - 1; const u32 mask = cast<VectorType>(type)->getNumElements() - 1;
// Transform indices (works for vectors with size 2^N) // Transform indices (works for vectors with size 2^N)
for (std::size_t i = 0; i < indices.size(); i++) for (std::size_t i = 0; i < indices.size(); i++)
@ -623,7 +626,7 @@ void PPUTranslator::CompilationError(const std::string& error)
void PPUTranslator::MFVSCR(ppu_opcode_t op) void PPUTranslator::MFVSCR(ppu_opcode_t op)
{ {
const auto vscr = m_ir->CreateOr(ZExt(RegLoad(m_sat), GetType<u32>()), m_ir->CreateShl(ZExt(RegLoad(m_nj), GetType<u32>()), 16)); const auto vscr = m_ir->CreateOr(ZExt(RegLoad(m_sat), GetType<u32>()), m_ir->CreateShl(ZExt(RegLoad(m_nj), GetType<u32>()), 16));
SetVr(op.vd, m_ir->CreateInsertElement(ConstantVector::getSplat(4, m_ir->getInt32(0)), vscr, m_ir->getInt32(m_is_be ? 3 : 0))); SetVr(op.vd, m_ir->CreateInsertElement(ConstantAggregateZero::get(GetType<u32[4]>()), vscr, m_ir->getInt32(m_is_be ? 3 : 0)));
} }
void PPUTranslator::MTVSCR(ppu_opcode_t op) void PPUTranslator::MTVSCR(ppu_opcode_t op)
@ -909,12 +912,12 @@ void PPUTranslator::VCTSXS(ppu_opcode_t op)
const auto b = GetVr(op.vb, VrType::vf); const auto b = GetVr(op.vb, VrType::vf);
const auto scaled = Scale(b, op.vuimm); const auto scaled = Scale(b, op.vuimm);
//const auto const0 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 0.0)); //const auto const0 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 0.0));
const auto const1 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), -std::pow(2, 31))); const auto const1 = ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), -std::pow(2, 31)));
//const auto is_nan = m_ir->CreateFCmpUNO(b, const0); // NaN -> 0.0 //const auto is_nan = m_ir->CreateFCmpUNO(b, const0); // NaN -> 0.0
const auto sat_l = m_ir->CreateFCmpOLT(scaled, const1); // TODO ??? const auto sat_l = m_ir->CreateFCmpOLT(scaled, const1); // TODO ???
const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), std::pow(2, 31)))); const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), std::pow(2, 31))));
const auto converted = m_ir->CreateFPToSI(m_ir->CreateSelect(sat_l, const1, scaled), GetType<s32[4]>()); const auto converted = m_ir->CreateFPToSI(m_ir->CreateSelect(sat_l, const1, scaled), GetType<s32[4]>());
SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat(4, m_ir->getInt32(0x7fffffff)), converted)); SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat({4, false}, m_ir->getInt32(0x7fffffff)), converted));
SetSat(IsNotZero(m_ir->CreateOr(sat_l, sat_h))); SetSat(IsNotZero(m_ir->CreateOr(sat_l, sat_h)));
} }
@ -922,12 +925,12 @@ void PPUTranslator::VCTUXS(ppu_opcode_t op)
{ {
const auto b = GetVr(op.vb, VrType::vf); const auto b = GetVr(op.vb, VrType::vf);
const auto scaled = Scale(b, op.vuimm); const auto scaled = Scale(b, op.vuimm);
const auto const0 = ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 0.0)); const auto const0 = ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), 0.0));
//const auto is_nan = m_ir->CreateFCmpUNO(b, const0); // NaN -> 0.0 //const auto is_nan = m_ir->CreateFCmpUNO(b, const0); // NaN -> 0.0
const auto sat_l = m_ir->CreateFCmpOLT(scaled, const0); const auto sat_l = m_ir->CreateFCmpOLT(scaled, const0);
const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), std::pow(2, 32)))); // TODO ??? const auto sat_h = m_ir->CreateFCmpOGE(scaled, ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), std::pow(2, 32)))); // TODO ???
const auto converted = m_ir->CreateFPToUI(m_ir->CreateSelect(sat_l, const0, scaled), GetType<u32[4]>()); const auto converted = m_ir->CreateFPToUI(m_ir->CreateSelect(sat_l, const0, scaled), GetType<u32[4]>());
SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat(4, m_ir->getInt32(0xffffffff)), converted)); SetVr(op.vd, m_ir->CreateSelect(sat_h, ConstantVector::getSplat({4, false}, m_ir->getInt32(0xffffffff)), converted));
SetSat(IsNotZero(m_ir->CreateOr(sat_l, sat_h))); SetSat(IsNotZero(m_ir->CreateOr(sat_l, sat_h)));
} }
@ -1044,7 +1047,7 @@ void PPUTranslator::VMHADDSHS(ppu_opcode_t op)
void PPUTranslator::VMHRADDSHS(ppu_opcode_t op) void PPUTranslator::VMHRADDSHS(ppu_opcode_t op)
{ {
const auto abc = SExt(GetVrs(VrType::vi16, op.va, op.vb, op.vc)); const auto abc = SExt(GetVrs(VrType::vi16, op.va, op.vb, op.vc));
const auto result = m_ir->CreateAdd(m_ir->CreateAShr(m_ir->CreateAdd(m_ir->CreateMul(abc[0], abc[1]), ConstantVector::getSplat(8, m_ir->getInt32(0x4000))), 15), abc[2]); const auto result = m_ir->CreateAdd(m_ir->CreateAShr(m_ir->CreateAdd(m_ir->CreateMul(abc[0], abc[1]), ConstantVector::getSplat({8, false}, m_ir->getInt32(0x4000))), 15), abc[2]);
const auto saturated = SaturateSigned(result, -0x8000, 0x7fff); const auto saturated = SaturateSigned(result, -0x8000, 0x7fff);
SetVr(op.vd, saturated.first); SetVr(op.vd, saturated.first);
SetSat(IsNotZero(saturated.second)); SetSat(IsNotZero(saturated.second));
@ -1309,7 +1312,7 @@ void PPUTranslator::VPERM(ppu_opcode_t op)
const auto a = get_vr<u8[16]>(op.va); const auto a = get_vr<u8[16]>(op.va);
const auto b = get_vr<u8[16]>(op.vb); const auto b = get_vr<u8[16]>(op.vb);
const auto c = get_vr<u8[16]>(op.vc); const auto c = get_vr<u8[16]>(op.vc);
if (m_use_avx512_icl && op.ra != op.rb) if (m_use_avx512_icl && op.ra != op.rb)
{ {
const auto i = eval(~c); const auto i = eval(~c);
@ -1401,7 +1404,7 @@ void PPUTranslator::VPKUWUS(ppu_opcode_t op)
void PPUTranslator::VREFP(ppu_opcode_t op) void PPUTranslator::VREFP(ppu_opcode_t op)
{ {
const auto result = VecHandleResult(m_ir->CreateFDiv(ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 1.0)), GetVr(op.vb, VrType::vf))); const auto result = VecHandleResult(m_ir->CreateFDiv(ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), 1.0)), GetVr(op.vb, VrType::vf)));
SetVr(op.vd, result); SetVr(op.vd, result);
} }
@ -1445,7 +1448,7 @@ void PPUTranslator::VRLW(ppu_opcode_t op)
void PPUTranslator::VRSQRTEFP(ppu_opcode_t op) void PPUTranslator::VRSQRTEFP(ppu_opcode_t op)
{ {
const auto result = m_ir->CreateFDiv(ConstantVector::getSplat(4, ConstantFP::get(GetType<f32>(), 1.0)), Call(GetType<f32[4]>(), "llvm.sqrt.v4f32", GetVr(op.vb, VrType::vf))); const auto result = m_ir->CreateFDiv(ConstantVector::getSplat({4, false}, ConstantFP::get(GetType<f32>(), 1.0)), Call(GetType<f32[4]>(), "llvm.sqrt.v4f32", GetVr(op.vb, VrType::vf)));
SetVr(op.vd, VecHandleResult(result)); SetVr(op.vd, VecHandleResult(result));
} }
@ -1472,7 +1475,7 @@ void PPUTranslator::VSEL(ppu_opcode_t op)
set_vr(op.vd, select(noncast<s32[4]>(c) != 0, get_vr<u32[4]>(op.vb), get_vr<u32[4]>(op.va))); set_vr(op.vd, select(noncast<s32[4]>(c) != 0, get_vr<u32[4]>(op.vb), get_vr<u32[4]>(op.va)));
return; return;
} }
bool sel_16 = true; bool sel_16 = true;
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
{ {
@ -1488,7 +1491,7 @@ void PPUTranslator::VSEL(ppu_opcode_t op)
set_vr(op.vd, select(bitcast<s16[8]>(c) != 0, get_vr<u16[8]>(op.vb), get_vr<u16[8]>(op.va))); set_vr(op.vd, select(bitcast<s16[8]>(c) != 0, get_vr<u16[8]>(op.vb), get_vr<u16[8]>(op.va)));
return; return;
} }
bool sel_8 = true; bool sel_8 = true;
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
@ -1582,17 +1585,17 @@ void PPUTranslator::VSPLTH(ppu_opcode_t op)
void PPUTranslator::VSPLTISB(ppu_opcode_t op) void PPUTranslator::VSPLTISB(ppu_opcode_t op)
{ {
SetVr(op.vd, ConstantVector::getSplat(16, m_ir->getInt8(op.vsimm))); SetVr(op.vd, ConstantVector::getSplat({16, false}, m_ir->getInt8(op.vsimm)));
} }
void PPUTranslator::VSPLTISH(ppu_opcode_t op) void PPUTranslator::VSPLTISH(ppu_opcode_t op)
{ {
SetVr(op.vd, ConstantVector::getSplat(8, m_ir->getInt16(op.vsimm))); SetVr(op.vd, ConstantVector::getSplat({8, false}, m_ir->getInt16(op.vsimm)));
} }
void PPUTranslator::VSPLTISW(ppu_opcode_t op) void PPUTranslator::VSPLTISW(ppu_opcode_t op)
{ {
SetVr(op.vd, ConstantVector::getSplat(4, m_ir->getInt32(op.vsimm))); SetVr(op.vd, ConstantVector::getSplat({4, false}, m_ir->getInt32(op.vsimm)));
} }
void PPUTranslator::VSPLTW(ppu_opcode_t op) void PPUTranslator::VSPLTW(ppu_opcode_t op)
@ -1800,7 +1803,7 @@ void PPUTranslator::VSUM4UBS(ppu_opcode_t op)
const auto e3 = Shuffle(a, nullptr, { 3, 7, 11, 15 }); const auto e3 = Shuffle(a, nullptr, { 3, 7, 11, 15 });
const auto r = Add({ b, e0, e1, e2, e3 }); // Summ, (e0+e1+e2+e3) is small const auto r = Add({ b, e0, e1, e2, e3 }); // Summ, (e0+e1+e2+e3) is small
const auto s = m_ir->CreateICmpULT(r, b); // Carry (saturation) const auto s = m_ir->CreateICmpULT(r, b); // Carry (saturation)
SetVr(op.vd, m_ir->CreateSelect(s, ConstantVector::getSplat(4, m_ir->getInt32(0xffffffff)), r)); SetVr(op.vd, m_ir->CreateSelect(s, ConstantVector::getSplat({4, false}, m_ir->getInt32(0xffffffff)), r));
SetSat(IsNotZero(s)); SetSat(IsNotZero(s));
} }
@ -1843,7 +1846,7 @@ void PPUTranslator::VXOR(ppu_opcode_t op)
if (op.va == op.vb) if (op.va == op.vb)
{ {
// Assign zero, break dependencies // Assign zero, break dependencies
SetVr(op.vd, ConstantVector::getSplat(4, m_ir->getInt32(0))); SetVr(op.vd, ConstantAggregateZero::get(GetType<u32[4]>()));
return; return;
} }

View file

@ -317,7 +317,7 @@ public:
llvm::CallInst* Call(llvm::Type* ret, llvm::AttributeList attr, llvm::StringRef name, Args... args) llvm::CallInst* Call(llvm::Type* ret, llvm::AttributeList attr, llvm::StringRef name, Args... args)
{ {
// Call the function // Call the function
return m_ir->CreateCall(m_module->getOrInsertFunction(name, attr, ret, args->getType()...).getCallee(), {args...}); return m_ir->CreateCall(m_module->getOrInsertFunction(name, attr, ret, args->getType()...), {args...});
} }
// Call a function // Call a function

View file

@ -3418,14 +3418,14 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
} }
// Create tail call to the function chunk (non-tail calls are just out of question) // Create tail call to the function chunk (non-tail calls are just out of question)
void tail_chunk(llvm::Value* chunk, llvm::Value* base_pc = nullptr) void tail_chunk(llvm::FunctionCallee callee, llvm::Value* base_pc = nullptr)
{ {
if (!chunk && !g_cfg.core.spu_verification) if (!callee && !g_cfg.core.spu_verification)
{ {
// Disable patchpoints if verification is disabled // Disable patchpoints if verification is disabled
chunk = m_dispatch; callee = m_dispatch;
} }
else if (!chunk) else if (!callee)
{ {
// Create branch patchpoint if chunk == nullptr // Create branch patchpoint if chunk == nullptr
verify(HERE), m_finfo, !m_finfo->fn || m_function == m_finfo->chunk; verify(HERE), m_finfo, !m_finfo->fn || m_function == m_finfo->chunk;
@ -3444,12 +3444,13 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
return; return;
} }
chunk = ppfunc; callee = ppfunc;
base_pc = m_ir->getInt32(0); base_pc = m_ir->getInt32(0);
} }
auto call = m_ir->CreateCall(chunk, {m_thread, m_lsptr, base_pc ? base_pc : m_base_pc}); verify(HERE), callee;
auto func = m_finfo ? m_finfo->chunk : llvm::cast<llvm::Function>(chunk); auto call = m_ir->CreateCall(callee, {m_thread, m_lsptr, base_pc ? base_pc : m_base_pc});
auto func = m_finfo ? m_finfo->chunk : llvm::dyn_cast<llvm::Function>(callee.getCallee());
call->setCallingConv(func->getCallingConv()); call->setCallingConv(func->getCallingConv());
call->setTailCall(); call->setTailCall();
@ -4341,7 +4342,7 @@ public:
for (u32 j = starta; j < end; j += 32) for (u32 j = starta; j < end; j += 32)
{ {
u32 indices[8]; int indices[8];
bool holes = false; bool holes = false;
bool data = false; bool data = false;
@ -4373,7 +4374,7 @@ public:
// Mask if necessary // Mask if necessary
if (holes) if (holes)
{ {
vls = m_ir->CreateShuffleVector(vls, ConstantVector::getSplat(8, m_ir->getInt32(0)), indices); vls = m_ir->CreateShuffleVector(vls, ConstantAggregateZero::get(vls->getType()), indices);
} }
// Perform bitwise comparison and accumulate // Perform bitwise comparison and accumulate
@ -4419,7 +4420,8 @@ public:
// Proceed to the next code // Proceed to the next code
if (entry_chunk->chunk->getReturnType() != get_type<void>()) if (entry_chunk->chunk->getReturnType() != get_type<void>())
{ {
const auto next_call = m_ir->CreateCall(m_ir->CreateBitCast(entry_call, main_func->getType()), {m_thread, m_lsptr, m_ir->getInt64(0)}); const auto f_ptr = m_ir->CreateBitCast(entry_call, main_func->getType());
const auto next_call = m_ir->CreateCall({main_func->getFunctionType(), f_ptr}, {m_thread, m_lsptr, m_ir->getInt64(0)});
next_call->setCallingConv(main_func->getCallingConv()); next_call->setCallingConv(main_func->getCallingConv());
next_call->setTailCall(); next_call->setTailCall();
} }
@ -4456,7 +4458,8 @@ public:
if (entry_chunk->chunk->getReturnType() == get_type<void>()) if (entry_chunk->chunk->getReturnType() == get_type<void>())
{ {
const auto next_call = m_ir->CreateCall(m_ir->CreateBitCast(dispatcher, main_func->getType()), {m_thread, m_lsptr, m_ir->getInt64(0)}); const auto f_ptr = m_ir->CreateBitCast(dispatcher, main_func->getType());
const auto next_call = m_ir->CreateCall({main_func->getFunctionType(), f_ptr}, {m_thread, m_lsptr, m_ir->getInt64(0)});
next_call->setCallingConv(main_func->getCallingConv()); next_call->setCallingConv(main_func->getCallingConv());
next_call->setTailCall(); next_call->setTailCall();
m_ir->CreateRetVoid(); m_ir->CreateRetVoid();
@ -4911,7 +4914,7 @@ public:
// Decode (shift) and load function pointer // Decode (shift) and load function pointer
const auto first = m_ir->CreateLoad(m_ir->CreateGEP(m_ir->CreateBitCast(m_interp_table, if_pptr), m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn))); const auto first = m_ir->CreateLoad(m_ir->CreateGEP(m_ir->CreateBitCast(m_interp_table, if_pptr), m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn)));
const auto call0 = m_ir->CreateCall(first, {m_lsptr, m_thread, m_interp_pc, m_interp_op, m_interp_table, m_interp_7f0, m_interp_regs}); const auto call0 = m_ir->CreateCall({if_type, first}, {m_lsptr, m_thread, m_interp_pc, m_interp_op, m_interp_table, m_interp_7f0, m_interp_regs});
call0->setCallingConv(CallingConv::GHC); call0->setCallingConv(CallingConv::GHC);
m_ir->CreateRetVoid(); m_ir->CreateRetVoid();
@ -5125,7 +5128,7 @@ public:
} }
const auto arg3 = UndefValue::get(get_type<u32>()); const auto arg3 = UndefValue::get(get_type<u32>());
const auto _ret = m_ir->CreateCall(fret, {m_lsptr, m_thread, m_interp_pc, arg3, m_interp_table, m_interp_7f0, m_interp_regs}); const auto _ret = m_ir->CreateCall({if_type, fret}, {m_lsptr, m_thread, m_interp_pc, arg3, m_interp_table, m_interp_7f0, m_interp_regs});
_ret->setCallingConv(CallingConv::GHC); _ret->setCallingConv(CallingConv::GHC);
_ret->setTailCall(); _ret->setTailCall();
m_ir->CreateRetVoid(); m_ir->CreateRetVoid();
@ -5149,7 +5152,7 @@ public:
m_interp_regs = _ptr(m_thread, get_reg_offset(0)); m_interp_regs = _ptr(m_thread, get_reg_offset(0));
} }
const auto ncall = m_ir->CreateCall(next_if, {m_lsptr, m_thread, m_interp_pc, next_op, m_interp_table, m_interp_7f0, m_interp_regs}); const auto ncall = m_ir->CreateCall({if_type, next_if}, {m_lsptr, m_thread, m_interp_pc, next_op, m_interp_table, m_interp_7f0, m_interp_regs});
ncall->setCallingConv(CallingConv::GHC); ncall->setCallingConv(CallingConv::GHC);
ncall->setTailCall(); ncall->setTailCall();
m_ir->CreateRetVoid(); m_ir->CreateRetVoid();
@ -8405,7 +8408,9 @@ public:
// Clear stack mirror and return by tail call to the provided return address // Clear stack mirror and return by tail call to the provided return address
m_ir->CreateStore(splat<u64[2]>(-1).eval(m_ir), m_ir->CreateBitCast(m_ir->CreateGEP(m_thread, stack0.value), get_type<u64(*)[2]>())); m_ir->CreateStore(splat<u64[2]>(-1).eval(m_ir), m_ir->CreateBitCast(m_ir->CreateGEP(m_thread, stack0.value), get_type<u64(*)[2]>()));
const auto targ = m_ir->CreateAdd(m_ir->CreateLShr(_ret, 32), get_segment_base()); const auto targ = m_ir->CreateAdd(m_ir->CreateLShr(_ret, 32), get_segment_base());
tail_chunk(m_ir->CreateIntToPtr(targ, m_finfo->chunk->getFunctionType()->getPointerTo()), m_ir->CreateTrunc(m_ir->CreateLShr(link, 32), get_type<u32>())); const auto type = m_finfo->chunk->getFunctionType();
const auto fval = m_ir->CreateIntToPtr(targ, type->getPointerTo());
tail_chunk({type, fval}, m_ir->CreateTrunc(m_ir->CreateLShr(link, 32), get_type<u32>()));
m_ir->SetInsertPoint(fail); m_ir->SetInsertPoint(fail);
} }
@ -8420,7 +8425,7 @@ public:
const auto ad64 = m_ir->CreateZExt(ad32, get_type<u64>()); const auto ad64 = m_ir->CreateZExt(ad32, get_type<u64>());
const auto pptr = m_ir->CreateGEP(m_function_table, {m_ir->getInt64(0), m_ir->CreateLShr(ad64, 2, "", true)}); const auto pptr = m_ir->CreateGEP(m_function_table, {m_ir->getInt64(0), m_ir->CreateLShr(ad64, 2, "", true)});
tail_chunk(m_ir->CreateLoad(pptr)); tail_chunk({m_dispatch->getFunctionType(), m_ir->CreateLoad(pptr)});
m_ir->SetInsertPoint(fail); m_ir->SetInsertPoint(fail);
} }

View file

@ -521,3 +521,55 @@ int main(int argc, char** argv)
// run event loop (maybe only needed for the gui application) // run event loop (maybe only needed for the gui application)
return app->exec(); return app->exec();
} }
// Temporarily, this is code from std for prebuilt LLVM. I don't understand why this is necessary.
// From the same MSVC 19.27.29112.0, LLVM libs depend on these, but RPCS3 gets linker errors.
#ifdef _WIN32
extern "C"
{
int __stdcall __std_init_once_begin_initialize(void** ppinit, ulong f, int* fp, void** lpc) noexcept
{
return InitOnceBeginInitialize(reinterpret_cast<LPINIT_ONCE>(ppinit), f, fp, lpc);
}
int __stdcall __std_init_once_complete(void** ppinit, ulong f, void* lpc) noexcept
{
return InitOnceComplete(reinterpret_cast<LPINIT_ONCE>(ppinit), f, lpc);
}
size_t __stdcall __std_get_string_size_without_trailing_whitespace(const char* str, size_t size) noexcept
{
while (size)
{
switch (str[size - 1])
{
case 0:
case ' ':
case '\n':
case '\r':
case '\t':
{
size--;
continue;
}
}
break;
}
return size;
}
size_t __stdcall __std_system_error_allocate_message(const unsigned long msg_id, char** ptr_str) noexcept
{
return __std_get_string_size_without_trailing_whitespace(*ptr_str, FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, msg_id, 0, reinterpret_cast<char*>(ptr_str), 0, nullptr));
}
void __stdcall __std_system_error_deallocate_message(char* s) noexcept
{
LocalFree(s);
}
}
#endif

View file

@ -10,7 +10,53 @@
<Link> <Link>
<AdditionalLibraryDirectories Condition="'$(Configuration)'=='Debug - LLVM'">%(AdditionalLibraryDirectories);..\llvm_build\Debug\lib</AdditionalLibraryDirectories> <AdditionalLibraryDirectories Condition="'$(Configuration)'=='Debug - LLVM'">%(AdditionalLibraryDirectories);..\llvm_build\Debug\lib</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories Condition="'$(Configuration)'=='Release - LLVM'">%(AdditionalLibraryDirectories);..\llvm_build\Release\lib</AdditionalLibraryDirectories> <AdditionalLibraryDirectories Condition="'$(Configuration)'=='Release - LLVM'">%(AdditionalLibraryDirectories);..\llvm_build\Release\lib</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies);LLVMProfileData.lib;LLVMDebugInfoCodeView.lib;LLVMDebugInfoMSF.lib;LLVMInstrumentation.lib;LLVMMCJIT.lib;LLVMRuntimeDyld.lib;LLVMVectorize.lib;LLVMX86CodeGen.lib;LLVMGlobalISel.lib;LLVMX86Disassembler.lib;LLVMExecutionEngine.lib;LLVMAsmPrinter.lib;LLVMSelectionDAG.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMTarget.lib;LLVMX86Desc.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMCore.lib;LLVMX86Utils.lib;LLVMMC.lib;LLVMX86Info.lib;LLVMSupport.lib;LLVMMCDisassembler.lib;LLVMipo.lib;LLVMBinaryFormat.lib;LLVMPasses.lib;LLVMIRReader.lib;LLVMLinker.lib;LLVMAsmParser.lib;LLVMX86AsmParser.lib;LLVMDemangle.lib;LLVMDebugInfoDWARF.lib;LLVMRemarks.lib;LLVMBitstreamReader.lib;LLVMTextAPI.lib;LLVMCFGuard.lib</AdditionalDependencies> <AdditionalDependencies>%(AdditionalDependencies);
LLVMProfileData.lib;
LLVMDebugInfoCodeView.lib;
LLVMDebugInfoMSF.lib;
LLVMInstrumentation.lib;
LLVMMCJIT.lib;
LLVMRuntimeDyld.lib;
LLVMVectorize.lib;
LLVMX86CodeGen.lib;
LLVMGlobalISel.lib;
LLVMX86Disassembler.lib;
LLVMExecutionEngine.lib;
LLVMAsmPrinter.lib;
LLVMSelectionDAG.lib;
LLVMCodeGen.lib;
LLVMScalarOpts.lib;
LLVMInstCombine.lib;
LLVMTransformUtils.lib;
LLVMAnalysis.lib;
LLVMTarget.lib;
LLVMX86Desc.lib;
LLVMObject.lib;
LLVMMCParser.lib;
LLVMBitReader.lib;
LLVMCore.lib;
LLVMMC.lib;
LLVMX86Info.lib;
LLVMSupport.lib;
LLVMMCDisassembler.lib;
LLVMipo.lib;
LLVMBinaryFormat.lib;
LLVMPasses.lib;
LLVMIRReader.lib;
LLVMLinker.lib;
LLVMAsmParser.lib;
LLVMX86AsmParser.lib;
LLVMDemangle.lib;
LLVMDebugInfoDWARF.lib;
LLVMRemarks.lib;
LLVMBitstreamReader.lib;
LLVMTextAPI.lib;
LLVMCFGuard.lib;
LLVMAggressiveInstCombine.lib;
LLVMBitWriter.lib;
LLVMCoroutines.lib;
LLVMObjCARCOpts.lib;
</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup /> <ItemGroup />