Commit 99e57199 by Ben Clayton

LLVMReactor: Fix atomic loads and stores of non-scalar types.

The documentation and verifier both say the pointee needs to be a integer, pointer, or floating point type. It looks like invalid atomic stores may be lowered to __atomic_load / __atomic_store via the AtomicExpandPass, but this comes much later in the transform pipeline, and before the verifier. Bug: b/131914569 Bug: b/127472316 Change-Id: Ieae5527ca5d65c890251c802baeaca6c5a9eacbb Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30568 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent d5ed0a31
...@@ -1273,11 +1273,36 @@ namespace rr ...@@ -1273,11 +1273,36 @@ namespace rr
// Fallthrough to non-emulated case. // Fallthrough to non-emulated case.
case Type_LLVM: case Type_LLVM:
{ {
ASSERT(V(ptr)->getType()->getContainedType(0) == T(type)); auto elTy = T(type);
auto load = new llvm::LoadInst(V(ptr), "", isVolatile, alignment); ASSERT(V(ptr)->getType()->getContainedType(0) == elTy);
load->setAtomic(atomicOrdering(atomic, memoryOrder)); if (atomic && !(elTy->isIntegerTy() || elTy->isPointerTy() || elTy->isFloatTy()))
{
return V(::builder->Insert(load)); // atomic load operand must have integer, pointer, or floating point type
// Fall back to using:
// void __atomic_load(size_t size, void *ptr, void *ret, int ordering)
auto sizetTy = ::llvm::IntegerType::get(*::context, sizeof(size_t) * 8);
auto intTy = ::llvm::IntegerType::get(*::context, sizeof(int) * 8);
auto i8Ty = ::llvm::Type::getInt8Ty(*::context);
auto i8PtrTy = i8Ty->getPointerTo();
auto voidTy = ::llvm::Type::getVoidTy(*::context);
auto funcTy = ::llvm::FunctionType::get(voidTy, {sizetTy, i8PtrTy, i8PtrTy, intTy}, false);
auto func = ::module->getOrInsertFunction("__atomic_load", funcTy);
auto size = ::module->getDataLayout().getTypeStoreSize(elTy);
auto out = allocateStackVariable(type);
::builder->CreateCall(func, {
::llvm::ConstantInt::get(sizetTy, size),
::builder->CreatePointerCast(V(ptr), i8PtrTy),
::builder->CreatePointerCast(V(out), i8PtrTy),
::llvm::ConstantInt::get(intTy, uint64_t(atomicOrdering(true, memoryOrder))),
});
return V(::builder->CreateLoad(V(out)));
}
else
{
auto load = new llvm::LoadInst(V(ptr), "", isVolatile, alignment);
load->setAtomic(atomicOrdering(atomic, memoryOrder));
return V(::builder->Insert(load));
}
} }
default: default:
UNREACHABLE("asInternalType(type): %d", int(asInternalType(type))); UNREACHABLE("asInternalType(type): %d", int(asInternalType(type)));
...@@ -1313,9 +1338,35 @@ namespace rr ...@@ -1313,9 +1338,35 @@ namespace rr
// Fallthrough to non-emulated case. // Fallthrough to non-emulated case.
case Type_LLVM: case Type_LLVM:
{ {
ASSERT(V(ptr)->getType()->getContainedType(0) == T(type)); auto elTy = T(type);
auto store = ::builder->Insert(new llvm::StoreInst(V(value), V(ptr), isVolatile, alignment)); ASSERT(V(ptr)->getType()->getContainedType(0) == elTy);
store->setAtomic(atomicOrdering(atomic, memoryOrder)); if (atomic && !(elTy->isIntegerTy() || elTy->isPointerTy() || elTy->isFloatTy()))
{
// atomic store operand must have integer, pointer, or floating point type
// Fall back to using:
// void __atomic_store(size_t size, void *ptr, void *val, int ordering)
auto sizetTy = ::llvm::IntegerType::get(*::context, sizeof(size_t) * 8);
auto intTy = ::llvm::IntegerType::get(*::context, sizeof(int) * 8);
auto i8Ty = ::llvm::Type::getInt8Ty(*::context);
auto i8PtrTy = i8Ty->getPointerTo();
auto voidTy = ::llvm::Type::getVoidTy(*::context);
auto funcTy = ::llvm::FunctionType::get(voidTy, {sizetTy, i8PtrTy, i8PtrTy, intTy}, false);
auto func = ::module->getOrInsertFunction("__atomic_store", funcTy);
auto size = ::module->getDataLayout().getTypeStoreSize(elTy);
auto copy = allocateStackVariable(type);
::builder->CreateStore(V(value), V(copy));
::builder->CreateCall(func, {
::llvm::ConstantInt::get(sizetTy, size),
::builder->CreatePointerCast(V(ptr), i8PtrTy),
::builder->CreatePointerCast(V(copy), i8PtrTy),
::llvm::ConstantInt::get(intTy, uint64_t(atomicOrdering(true, memoryOrder))),
});
}
else
{
auto store = ::builder->Insert(new llvm::StoreInst(V(value), V(ptr), isVolatile, alignment));
store->setAtomic(atomicOrdering(atomic, memoryOrder));
}
return value; return value;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment