Implement rr::Print support for Subzero
Factored out most of the rr::Print code in LLVMReactor.cpp to
Reactor.cpp, and rewritten in terms of Nucleus. Added a couple of new
Nucleus functions to support this.
Bug: b/149477527
Change-Id: I0a28626f1aa6133a37f9e75abc08544f3de15a45
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/41188
Presubmit-Ready: Antonio Maiorano <amaiorano@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index f2dbdef..29aa1c8 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -14,6 +14,7 @@
#include "Debug.hpp"
#include "EmulatedReactor.hpp"
+#include "Print.hpp"
#include "Reactor.hpp"
#include "ExecutableMemory.hpp"
@@ -143,11 +144,8 @@
}
// Wrapper for calls on C functions with Ice types
-template<typename Return, typename... CArgs, typename... RArgs>
-Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(CArgs...), RArgs &&... args)
+Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Type retTy, void const *fptr, const std::vector<Ice::Operand *> &iceArgs)
{
- Ice::Type retTy = T(rr::CToReactorT<Return>::getType());
-
// Subzero doesn't support boolean return values. Replace with an i32.
if(retTy == Ice::IceType_i1)
{
@@ -160,9 +158,7 @@
ret = function->makeVariable(retTy);
}
- std::array<Ice::Variable *, sizeof...(args)> iceArgs{ { std::forward<RArgs>(args)... } };
-
- auto call = Ice::InstCall::create(function, iceArgs.size(), ret, getConstantPointer(function->getContext(), reinterpret_cast<void const *>(fptr)), false);
+ auto call = Ice::InstCall::create(function, iceArgs.size(), ret, getConstantPointer(function->getContext(), fptr), false);
for(auto arg : iceArgs)
{
call->addArg(arg);
@@ -172,6 +168,15 @@
return ret;
}
+// Wrapper for calls on C functions with Ice types
+template<typename Return, typename... CArgs, typename... RArgs>
+Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(CArgs...), RArgs &&... args)
+{
+ Ice::Type retTy = T(rr::CToReactorT<Return>::getType());
+ std::vector<Ice::Operand *> iceArgs{ std::forward<RArgs>(args)... };
+ return Call(function, basicBlock, retTy, reinterpret_cast<void const *>(fptr), iceArgs);
+}
+
// Returns a non-const variable copy of const v
Ice::Variable *createUnconstCast(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Constant *v)
{
@@ -414,6 +419,17 @@
return reinterpret_cast<Ice::Operand *>(v);
}
+std::vector<Ice::Operand *> V(const std::vector<Value *> &values)
+{
+ std::vector<Ice::Operand *> result;
+ result.reserve(values.size());
+ for(auto &v : values)
+ {
+ result.push_back(V(v));
+ }
+ return result;
+}
+
BasicBlock *B(Ice::CfgNode *b)
{
return reinterpret_cast<BasicBlock *>(b);
@@ -798,6 +814,13 @@
std::vector<std::unique_ptr<uint8_t[]>> constantData;
};
+#ifdef ENABLE_RR_PRINT
+void VPrintf(const std::vector<Value *> &vals)
+{
+ sz::Call(::function, ::basicBlock, Ice::IceType_i32, reinterpret_cast<const void *>(::printf), V(vals));
+}
+#endif // ENABLE_RR_PRINT
+
Nucleus::Nucleus()
{
::codegenMutex.lock(); // Reactor is currently not thread safe
@@ -1701,7 +1724,7 @@
Value *Nucleus::createExtractElement(Value *vector, Type *type, int index)
{
auto result = ::function->makeVariable(T(type));
- auto extract = Ice::InstExtractElement::create(::function, result, vector, ::context->getConstantInt32(index));
+ auto extract = Ice::InstExtractElement::create(::function, result, V(vector), ::context->getConstantInt32(index));
::basicBlock->appendInst(extract);
return V(result);
@@ -1764,11 +1787,58 @@
::basicBlock->appendInst(unreachable);
}
+Type *Nucleus::getType(Value *value)
+{
+ return T(V(value)->getType());
+}
+
+Type *Nucleus::getContainedType(Type *vectorType)
+{
+ Ice::Type vecTy = T(vectorType);
+ switch(vecTy)
+ {
+ case Ice::IceType_v4i1: return T(Ice::IceType_i1);
+ case Ice::IceType_v8i1: return T(Ice::IceType_i1);
+ case Ice::IceType_v16i1: return T(Ice::IceType_i1);
+ case Ice::IceType_v16i8: return T(Ice::IceType_i8);
+ case Ice::IceType_v8i16: return T(Ice::IceType_i16);
+ case Ice::IceType_v4i32: return T(Ice::IceType_i32);
+ case Ice::IceType_v4f32: return T(Ice::IceType_f32);
+ default:
+ ASSERT_MSG(false, "getContainedType: input type is not a vector type");
+ return {};
+ }
+}
+
Type *Nucleus::getPointerType(Type *ElementType)
{
return T(sz::getPointerType(T(ElementType)));
}
+static constexpr Ice::Type getNaturalIntType()
+{
+ constexpr size_t intSize = sizeof(int);
+ static_assert(intSize == 4 || intSize == 8, "");
+ return intSize == 4 ? Ice::IceType_i32 : Ice::IceType_i64;
+}
+
+Type *Nucleus::getPrintfStorageType(Type *valueType)
+{
+ Ice::Type valueTy = T(valueType);
+ switch(valueTy)
+ {
+ case Ice::IceType_i32:
+ return T(getNaturalIntType());
+
+ case Ice::IceType_f32:
+ return T(Ice::IceType_f64);
+
+ default:
+ UNIMPLEMENTED_NO_BUG("getPrintfStorageType: add more cases as needed");
+ return {};
+ }
+}
+
Value *Nucleus::createNullValue(Type *Ty)
{
if(Ice::isVectorType(T(Ty)))
@@ -1933,6 +2003,11 @@
return createConstantVector((const int64_t *)constants, type);
}
+Value *Nucleus::createConstantString(const char *v)
+{
+ return V(IceConstantData(v, strlen(v) + 1));
+}
+
Type *Void::getType()
{
return T(Ice::IceType_void);