Commit 62427e0e by Antonio Maiorano

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: 's avatarAntonio Maiorano <amaiorano@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com>
parent b3d9a2ad
...@@ -543,9 +543,8 @@ else() ...@@ -543,9 +543,8 @@ else()
endif() endif()
endif() endif()
if((${REACTOR_BACKEND} STREQUAL "Subzero") AND (REACTOR_ENABLE_PRINT OR REACTOR_EMIT_PRINT_LOCATION OR REACTOR_EMIT_DEBUG_INFO)) if((${REACTOR_BACKEND} STREQUAL "Subzero") AND (REACTOR_EMIT_PRINT_LOCATION OR REACTOR_EMIT_DEBUG_INFO))
message(WARNING "REACTOR_ENABLE_PRINT, REACTOR_EMIT_PRINT_LOCATION, and REACTOR_EMIT_DEBUG_INFO are not supported by Subzero, disabling.") message(WARNING "REACTOR_ENABLE_PRINT, REACTOR_EMIT_PRINT_LOCATION, and REACTOR_EMIT_DEBUG_INFO are not supported by Subzero, disabling.")
set(REACTOR_ENABLE_PRINT "Off")
set(REACTOR_EMIT_PRINT_LOCATION "Off") set(REACTOR_EMIT_PRINT_LOCATION "Off")
set(REACTOR_EMIT_DEBUG_INFO "Off") set(REACTOR_EMIT_DEBUG_INFO "Off")
endif() endif()
......
...@@ -77,19 +77,6 @@ rr::Config &defaultConfig() ...@@ -77,19 +77,6 @@ rr::Config &defaultConfig()
return config; return config;
} }
#ifdef ENABLE_RR_PRINT
std::string replace(std::string str, const std::string &substr, const std::string &replacement)
{
size_t pos = 0;
while((pos = str.find(substr, pos)) != std::string::npos)
{
str.replace(pos, substr.length(), replacement);
pos += replacement.length();
}
return str;
}
#endif // ENABLE_RR_PRINT
llvm::Value *lowerPAVG(llvm::Value *x, llvm::Value *y) llvm::Value *lowerPAVG(llvm::Value *x, llvm::Value *y)
{ {
llvm::VectorType *ty = llvm::cast<llvm::VectorType>(x->getType()); llvm::VectorType *ty = llvm::cast<llvm::VectorType>(x->getType());
...@@ -1567,11 +1554,42 @@ void Nucleus::createUnreachable() ...@@ -1567,11 +1554,42 @@ void Nucleus::createUnreachable()
jit->builder->CreateUnreachable(); jit->builder->CreateUnreachable();
} }
Type *Nucleus::getType(Value *value)
{
return T(V(value)->getType());
}
Type *Nucleus::getContainedType(Type *vectorType)
{
return T(T(vectorType)->getContainedType(0));
}
Type *Nucleus::getPointerType(Type *ElementType) Type *Nucleus::getPointerType(Type *ElementType)
{ {
return T(llvm::PointerType::get(T(ElementType), 0)); return T(llvm::PointerType::get(T(ElementType), 0));
} }
static ::llvm::Type *getNaturalIntType()
{
return ::llvm::Type::getIntNTy(jit->context, sizeof(int) * 8);
}
Type *Nucleus::getPrintfStorageType(Type *valueType)
{
llvm::Type *valueTy = T(valueType);
if(valueTy->isIntegerTy())
{
return T(getNaturalIntType());
}
if(valueTy->isFloatTy())
{
return T(llvm::Type::getDoubleTy(jit->context));
}
UNIMPLEMENTED_NO_BUG("getPrintfStorageType: add more cases as needed");
return {};
}
Value *Nucleus::createNullValue(Type *Ty) Value *Nucleus::createNullValue(Type *Ty)
{ {
RR_DEBUG_INFO_UPDATE_LOC(); RR_DEBUG_INFO_UPDATE_LOC();
...@@ -1670,6 +1688,12 @@ Value *Nucleus::createConstantVector(const double *constants, Type *type) ...@@ -1670,6 +1688,12 @@ Value *Nucleus::createConstantVector(const double *constants, Type *type)
return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant *>(constantVector, numElements))); return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant *>(constantVector, numElements)));
} }
Value *Nucleus::createConstantString(const char *v)
{
auto ptr = jit->builder->CreateGlobalStringPtr(v);
return V(ptr);
}
Type *Void::getType() Type *Void::getType()
{ {
return T(llvm::Type::getVoidTy(jit->context)); return T(llvm::Type::getVoidTy(jit->context));
...@@ -3827,189 +3851,13 @@ RValue<Int4> pmovsxwd(RValue<Short8> x) ...@@ -3827,189 +3851,13 @@ RValue<Int4> pmovsxwd(RValue<Short8> x)
#endif // defined(__i386__) || defined(__x86_64__) #endif // defined(__i386__) || defined(__x86_64__)
#ifdef ENABLE_RR_PRINT #ifdef ENABLE_RR_PRINT
// extractAll returns a vector containing the extracted n scalar value of void VPrintf(const std::vector<Value *> &vals)
// the vector vec.
static std::vector<Value *> extractAll(Value *vec, int n)
{
std::vector<Value *> elements;
elements.reserve(n);
for(int i = 0; i < n; i++)
{
auto el = V(jit->builder->CreateExtractElement(V(vec), i));
elements.push_back(el);
}
return elements;
}
// toInt returns all the integer values in vals extended to a native width
// integer.
static std::vector<Value *> toInt(const std::vector<Value *> &vals, bool isSigned)
{ {
auto intTy = ::llvm::Type::getIntNTy(jit->context, sizeof(int) * 8); // Natural integer width.
std::vector<Value *> elements;
elements.reserve(vals.size());
for(auto v : vals)
{
if(isSigned)
{
elements.push_back(V(jit->builder->CreateSExt(V(v), intTy)));
}
else
{
elements.push_back(V(jit->builder->CreateZExt(V(v), intTy)));
}
}
return elements;
}
// toDouble returns all the float values in vals extended to doubles.
static std::vector<Value *> toDouble(const std::vector<Value *> &vals)
{
auto doubleTy = ::llvm::Type::getDoubleTy(jit->context);
std::vector<Value *> elements;
elements.reserve(vals.size());
for(auto v : vals)
{
elements.push_back(V(jit->builder->CreateFPExt(V(v), doubleTy)));
}
return elements;
}
std::vector<Value *> PrintValue::Ty<Bool>::val(const RValue<Bool> &v)
{
auto t = jit->builder->CreateGlobalStringPtr("true");
auto f = jit->builder->CreateGlobalStringPtr("false");
return { V(jit->builder->CreateSelect(V(v.value), t, f)) };
}
std::vector<Value *> PrintValue::Ty<Byte>::val(const RValue<Byte> &v)
{
return toInt({ v.value }, false);
}
std::vector<Value *> PrintValue::Ty<Byte4>::val(const RValue<Byte4> &v)
{
return toInt(extractAll(v.value, 4), false);
}
std::vector<Value *> PrintValue::Ty<Int>::val(const RValue<Int> &v)
{
return toInt({ v.value }, true);
}
std::vector<Value *> PrintValue::Ty<Int2>::val(const RValue<Int2> &v)
{
return toInt(extractAll(v.value, 2), true);
}
std::vector<Value *> PrintValue::Ty<Int4>::val(const RValue<Int4> &v)
{
return toInt(extractAll(v.value, 4), true);
}
std::vector<Value *> PrintValue::Ty<UInt>::val(const RValue<UInt> &v)
{
return toInt({ v.value }, false);
}
std::vector<Value *> PrintValue::Ty<UInt2>::val(const RValue<UInt2> &v)
{
return toInt(extractAll(v.value, 2), false);
}
std::vector<Value *> PrintValue::Ty<UInt4>::val(const RValue<UInt4> &v)
{
return toInt(extractAll(v.value, 4), false);
}
std::vector<Value *> PrintValue::Ty<Short>::val(const RValue<Short> &v)
{
return toInt({ v.value }, true);
}
std::vector<Value *> PrintValue::Ty<Short4>::val(const RValue<Short4> &v)
{
return toInt(extractAll(v.value, 4), true);
}
std::vector<Value *> PrintValue::Ty<UShort>::val(const RValue<UShort> &v)
{
return toInt({ v.value }, false);
}
std::vector<Value *> PrintValue::Ty<UShort4>::val(const RValue<UShort4> &v)
{
return toInt(extractAll(v.value, 4), false);
}
std::vector<Value *> PrintValue::Ty<Float>::val(const RValue<Float> &v)
{
return toDouble({ v.value });
}
std::vector<Value *> PrintValue::Ty<Float4>::val(const RValue<Float4> &v)
{
return toDouble(extractAll(v.value, 4));
}
std::vector<Value *> PrintValue::Ty<const char *>::val(const char *v)
{
return { V(jit->builder->CreateGlobalStringPtr(v)) };
}
void Printv(const char *function, const char *file, int line, const char *fmt, std::initializer_list<PrintValue> args)
{
// LLVM types used below.
auto i32Ty = ::llvm::Type::getInt32Ty(jit->context); auto i32Ty = ::llvm::Type::getInt32Ty(jit->context);
auto intTy = ::llvm::Type::getIntNTy(jit->context, sizeof(int) * 8); // Natural integer width.
auto i8PtrTy = ::llvm::Type::getInt8PtrTy(jit->context); auto i8PtrTy = ::llvm::Type::getInt8PtrTy(jit->context);
auto funcTy = ::llvm::FunctionType::get(i32Ty, { i8PtrTy }, true); auto funcTy = ::llvm::FunctionType::get(i32Ty, { i8PtrTy }, true);
auto func = jit->module->getOrInsertFunction("printf", funcTy); auto func = jit->module->getOrInsertFunction("printf", funcTy);
jit->builder->CreateCall(func, V(vals));
// Build the printf format message string.
std::string str;
if(file != nullptr) { str += (line > 0) ? "%s:%d " : "%s "; }
if(function != nullptr) { str += "%s "; }
str += fmt;
// Perform substitution on all '{n}' bracketed indices in the format
// message.
int i = 0;
for(const PrintValue &arg : args)
{
str = replace(str, "{" + std::to_string(i++) + "}", arg.format);
}
::llvm::SmallVector<::llvm::Value *, 8> vals;
// The format message is always the first argument.
vals.push_back(jit->builder->CreateGlobalStringPtr(str));
// Add optional file, line and function info if provided.
if(file != nullptr)
{
vals.push_back(jit->builder->CreateGlobalStringPtr(file));
if(line > 0)
{
vals.push_back(::llvm::ConstantInt::get(intTy, line));
}
}
if(function != nullptr)
{
vals.push_back(jit->builder->CreateGlobalStringPtr(function));
}
// Add all format arguments.
for(const PrintValue &arg : args)
{
for(auto val : arg.values)
{
vals.push_back(V(val));
}
}
jit->builder->CreateCall(func, vals);
} }
#endif // ENABLE_RR_PRINT #endif // ENABLE_RR_PRINT
......
...@@ -65,6 +65,17 @@ inline Value *V(llvm::Value *t) ...@@ -65,6 +65,17 @@ inline Value *V(llvm::Value *t)
return reinterpret_cast<Value *>(t); return reinterpret_cast<Value *>(t);
} }
inline std::vector<llvm::Value *> V(const std::vector<Value *> &values)
{
std::vector<llvm::Value *> result;
result.reserve(values.size());
for(auto &v : values)
{
result.push_back(V(v));
}
return result;
}
// Emits a no-op instruction that will not be optimized away. // Emits a no-op instruction that will not be optimized away.
// Useful for emitting something that can have a source location without // Useful for emitting something that can have a source location without
// effect. // effect.
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#ifdef None #ifdef None
...@@ -326,8 +327,13 @@ public: ...@@ -326,8 +327,13 @@ public:
static Value *createNullPointer(Type *type); static Value *createNullPointer(Type *type);
static Value *createConstantVector(const int64_t *constants, Type *type); static Value *createConstantVector(const int64_t *constants, Type *type);
static Value *createConstantVector(const double *constants, Type *type); static Value *createConstantVector(const double *constants, Type *type);
static Value *createConstantString(const char *v);
static Value *createConstantString(const std::string &v) { return createConstantString(v.c_str()); }
static Type *getType(Value *value);
static Type *getContainedType(Type *vectorType);
static Type *getPointerType(Type *elementType); static Type *getPointerType(Type *elementType);
static Type *getPrintfStorageType(Type *valueType);
}; };
} // namespace rr } // namespace rr
......
...@@ -337,6 +337,10 @@ struct PrintValue::Ty<RValue<T>> ...@@ -337,6 +337,10 @@ struct PrintValue::Ty<RValue<T>>
static std::vector<Value *> val(const RValue<T> &v) { return PrintValue::Ty<T>::val(v); } static std::vector<Value *> val(const RValue<T> &v) { return PrintValue::Ty<T>::val(v); }
}; };
// VPrintf emits a call to printf() using vals[0] as the format string,
// and vals[1..n] as the args.
void VPrintf(const std::vector<Value *> &vals);
// Printv emits a call to printf() using the function, file and line, // Printv emits a call to printf() using the function, file and line,
// message and optional values. // message and optional values.
// See Printv below. // See Printv below.
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "Reactor.hpp" #include "Reactor.hpp"
#include "Debug.hpp" #include "Debug.hpp"
#include "Print.hpp"
#include <cmath> #include <cmath>
...@@ -4596,4 +4597,197 @@ Float4 CToReactor<float[4]>::cast(float v[4]) ...@@ -4596,4 +4597,197 @@ Float4 CToReactor<float[4]>::cast(float v[4])
// TODO: Long has no constructor that takes a uint64_t // TODO: Long has no constructor that takes a uint64_t
// Long CToReactor<uint64_t>::cast(uint64_t v) { return type(v); } // Long CToReactor<uint64_t>::cast(uint64_t v) { return type(v); }
#ifdef ENABLE_RR_PRINT
static std::string replaceAll(std::string str, const std::string &substr, const std::string &replacement)
{
size_t pos = 0;
while((pos = str.find(substr, pos)) != std::string::npos)
{
str.replace(pos, substr.length(), replacement);
pos += replacement.length();
}
return str;
}
// extractAll returns a vector containing the extracted n scalar value of
// the vector vec.
// TODO: Move to Reactor.cpp (LLVMReactor can use this too)
static std::vector<Value *> extractAll(Value *vec, int n)
{
Type *elemTy = Nucleus::getContainedType(Nucleus::getType(vec));
std::vector<Value *> elements;
elements.reserve(n);
for(int i = 0; i < n; i++)
{
auto el = Nucleus::createExtractElement(vec, elemTy, i);
elements.push_back(el);
}
return elements;
}
// toInt returns all the integer values in vals extended to a printf-required storage value
static std::vector<Value *> toInt(const std::vector<Value *> &vals, bool isSigned)
{
auto storageTy = Nucleus::getPrintfStorageType(Int::getType());
std::vector<Value *> elements;
elements.reserve(vals.size());
for(auto v : vals)
{
if(isSigned)
{
elements.push_back(Nucleus::createSExt(v, storageTy));
}
else
{
elements.push_back(Nucleus::createZExt(v, storageTy));
}
}
return elements;
}
// toFloat returns all the float values in vals extended to extended to a printf-required storage value
static std::vector<Value *> toFloat(const std::vector<Value *> &vals)
{
auto storageTy = Nucleus::getPrintfStorageType(Float::getType());
std::vector<Value *> elements;
elements.reserve(vals.size());
for(auto v : vals)
{
elements.push_back(Nucleus::createFPExt(v, storageTy));
}
return elements;
}
std::vector<Value *> PrintValue::Ty<Bool>::val(const RValue<Bool> &v)
{
auto t = Nucleus::createConstantString("true");
auto f = Nucleus::createConstantString("false");
return { Nucleus::createSelect(v.value, t, f) };
}
std::vector<Value *> PrintValue::Ty<Byte>::val(const RValue<Byte> &v)
{
return toInt({ v.value }, false);
}
std::vector<Value *> PrintValue::Ty<Byte4>::val(const RValue<Byte4> &v)
{
return toInt(extractAll(v.value, 4), false);
}
std::vector<Value *> PrintValue::Ty<Int>::val(const RValue<Int> &v)
{
return toInt({ v.value }, true);
}
std::vector<Value *> PrintValue::Ty<Int2>::val(const RValue<Int2> &v)
{
return toInt(extractAll(v.value, 2), true);
}
std::vector<Value *> PrintValue::Ty<Int4>::val(const RValue<Int4> &v)
{
return toInt(extractAll(v.value, 4), true);
}
std::vector<Value *> PrintValue::Ty<UInt>::val(const RValue<UInt> &v)
{
return toInt({ v.value }, false);
}
std::vector<Value *> PrintValue::Ty<UInt2>::val(const RValue<UInt2> &v)
{
return toInt(extractAll(v.value, 2), false);
}
std::vector<Value *> PrintValue::Ty<UInt4>::val(const RValue<UInt4> &v)
{
return toInt(extractAll(v.value, 4), false);
}
std::vector<Value *> PrintValue::Ty<Short>::val(const RValue<Short> &v)
{
return toInt({ v.value }, true);
}
std::vector<Value *> PrintValue::Ty<Short4>::val(const RValue<Short4> &v)
{
return toInt(extractAll(v.value, 4), true);
}
std::vector<Value *> PrintValue::Ty<UShort>::val(const RValue<UShort> &v)
{
return toInt({ v.value }, false);
}
std::vector<Value *> PrintValue::Ty<UShort4>::val(const RValue<UShort4> &v)
{
return toInt(extractAll(v.value, 4), false);
}
std::vector<Value *> PrintValue::Ty<Float>::val(const RValue<Float> &v)
{
return toFloat({ v.value });
}
std::vector<Value *> PrintValue::Ty<Float4>::val(const RValue<Float4> &v)
{
return toFloat(extractAll(v.value, 4));
}
std::vector<Value *> PrintValue::Ty<const char *>::val(const char *v)
{
return { Nucleus::createConstantString(v) };
}
void Printv(const char *function, const char *file, int line, const char *fmt, std::initializer_list<PrintValue> args)
{
// Build the printf format message string.
std::string str;
if(file != nullptr) { str += (line > 0) ? "%s:%d " : "%s "; }
if(function != nullptr) { str += "%s "; }
str += fmt;
// Perform substitution on all '{n}' bracketed indices in the format
// message.
int i = 0;
for(const PrintValue &arg : args)
{
str = replaceAll(str, "{" + std::to_string(i++) + "}", arg.format);
}
std::vector<Value *> vals;
vals.reserve(8);
// The format message is always the first argument.
vals.push_back(Nucleus::createConstantString(str));
// Add optional file, line and function info if provided.
if(file != nullptr)
{
vals.push_back(Nucleus::createConstantString(file));
if(line > 0)
{
vals.push_back(Nucleus::createConstantInt(line));
}
}
if(function != nullptr)
{
vals.push_back(Nucleus::createConstantString(function));
}
// Add all format arguments.
for(const PrintValue &arg : args)
{
for(auto val : arg.values)
{
vals.push_back(val);
}
}
// This call is implemented by each backend
VPrintf(vals);
}
#endif // ENABLE_RR_PRINT
} // namespace rr } // namespace rr
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "Debug.hpp" #include "Debug.hpp"
#include "EmulatedReactor.hpp" #include "EmulatedReactor.hpp"
#include "Print.hpp"
#include "Reactor.hpp" #include "Reactor.hpp"
#include "ExecutableMemory.hpp" #include "ExecutableMemory.hpp"
...@@ -143,11 +144,8 @@ Ice::Constant *getConstantPointer(Ice::GlobalContext *context, void const *ptr) ...@@ -143,11 +144,8 @@ Ice::Constant *getConstantPointer(Ice::GlobalContext *context, void const *ptr)
} }
// Wrapper for calls on C functions with Ice types // 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, Ice::Type retTy, void const *fptr, const std::vector<Ice::Operand *> &iceArgs)
Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(CArgs...), RArgs &&... args)
{ {
Ice::Type retTy = T(rr::CToReactorT<Return>::getType());
// Subzero doesn't support boolean return values. Replace with an i32. // Subzero doesn't support boolean return values. Replace with an i32.
if(retTy == Ice::IceType_i1) if(retTy == Ice::IceType_i1)
{ {
...@@ -160,9 +158,7 @@ Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(C ...@@ -160,9 +158,7 @@ Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(C
ret = function->makeVariable(retTy); 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(), fptr), false);
auto call = Ice::InstCall::create(function, iceArgs.size(), ret, getConstantPointer(function->getContext(), reinterpret_cast<void const *>(fptr)), false);
for(auto arg : iceArgs) for(auto arg : iceArgs)
{ {
call->addArg(arg); call->addArg(arg);
...@@ -172,6 +168,15 @@ Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(C ...@@ -172,6 +168,15 @@ Ice::Variable *Call(Ice::Cfg *function, Ice::CfgNode *basicBlock, Return(fptr)(C
return ret; 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 // Returns a non-const variable copy of const v
Ice::Variable *createUnconstCast(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Constant *v) Ice::Variable *createUnconstCast(Ice::Cfg *function, Ice::CfgNode *basicBlock, Ice::Constant *v)
{ {
...@@ -414,6 +419,17 @@ Ice::Operand *V(Value *v) ...@@ -414,6 +419,17 @@ Ice::Operand *V(Value *v)
return reinterpret_cast<Ice::Operand *>(v); 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) BasicBlock *B(Ice::CfgNode *b)
{ {
return reinterpret_cast<BasicBlock *>(b); return reinterpret_cast<BasicBlock *>(b);
...@@ -798,6 +814,13 @@ private: ...@@ -798,6 +814,13 @@ private:
std::vector<std::unique_ptr<uint8_t[]>> constantData; 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() Nucleus::Nucleus()
{ {
::codegenMutex.lock(); // Reactor is currently not thread safe ::codegenMutex.lock(); // Reactor is currently not thread safe
...@@ -1701,7 +1724,7 @@ Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs) ...@@ -1701,7 +1724,7 @@ Value *Nucleus::createFCmpUNE(Value *lhs, Value *rhs)
Value *Nucleus::createExtractElement(Value *vector, Type *type, int index) Value *Nucleus::createExtractElement(Value *vector, Type *type, int index)
{ {
auto result = ::function->makeVariable(T(type)); 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); ::basicBlock->appendInst(extract);
return V(result); return V(result);
...@@ -1764,11 +1787,58 @@ void Nucleus::createUnreachable() ...@@ -1764,11 +1787,58 @@ void Nucleus::createUnreachable()
::basicBlock->appendInst(unreachable); ::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) Type *Nucleus::getPointerType(Type *ElementType)
{ {
return T(sz::getPointerType(T(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) Value *Nucleus::createNullValue(Type *Ty)
{ {
if(Ice::isVectorType(T(Ty))) if(Ice::isVectorType(T(Ty)))
...@@ -1933,6 +2003,11 @@ Value *Nucleus::createConstantVector(const double *constants, Type *type) ...@@ -1933,6 +2003,11 @@ Value *Nucleus::createConstantVector(const double *constants, Type *type)
return createConstantVector((const int64_t *)constants, type); return createConstantVector((const int64_t *)constants, type);
} }
Value *Nucleus::createConstantString(const char *v)
{
return V(IceConstantData(v, strlen(v) + 1));
}
Type *Void::getType() Type *Void::getType()
{ {
return T(Ice::IceType_void); return T(Ice::IceType_void);
......
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