From 9f0e9d6ba431d8deb000b4fe6ff03c879d662f45 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 19 Dec 2019 16:40:33 -0500 Subject: Split out IRTypeSet (#1158) * CPPCompiler -> DownstreamCompiler * Added DownstreamCompileResult to start abstraction such that we don't need files. * * Split out slang-blob.cpp * Made CompileResult hold a DownstreamCompileResult - for access to binary or ISlangSharedLibrary * Keep temporary files in scope. * Add a hash to the hex dump stream. * Move all file tracking into DownstreamCompiler. * WIP support for nvrtc. * WIP: Adding support for nvrtc compiler. Adding enum types, wiring up the nvrtc into slang. * Fix remaining CPPCompiler references. * Fix order issue on target string matching. * Use ISlangSharedLibrary for nvrtc. * Use DownstreamCompiler for nvrtc. * WIP first pass at compilation win nvrtc. * Added testing if file is on file system into CommandLineDownstreamCompiler. Added sourceContentsPath. * Make test cuda-compile.cu work by just compiling not comparing output. * Genearlize DownstreamCompiler usage. * Fix warning on clang. * Remove CompilerType from DownstreamCompiler. * Use DownstreamCompiler interface for all compilers. NOTE for FXC, DXC and GLSLANG this doesn't mean using 'compile' - it's still extracting functions from shared library. * Replace DownstreamCompiler::SourceType -> SlangSourceLanguage * Replace _canCompile with something data driven. * Fix compiling on gcc/clang for DownstreamCompiler. * Moved some text conversions into DownstreamCompiler. * Fix problem on non-vc builds with not having return on locateCompilers for VS. * Change so no warning for code not reachable on locateCompilers for vs. * WIP: CUDA code generation - currently just using CPU layout and HLSL. * emitXXXForEntryPoint -> emitEntryPointSource emitSourceForEntryPoint -> emitEntryPointSourceFromIR Fix up generating cuda to get PTX. * WIP emitting cuda for IR. * Small improvements to CUDA ouput. * Disable the CUDA emit test, as output not currently compilable. * Split out IRTypeSet to simplify CPPSourceEmitter and other Emitters that rely on determining unique use of type and/or need to generate types in order to output code. --- source/slang/slang-ir-type-set.cpp | 229 +++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 source/slang/slang-ir-type-set.cpp (limited to 'source/slang/slang-ir-type-set.cpp') diff --git a/source/slang/slang-ir-type-set.cpp b/source/slang/slang-ir-type-set.cpp new file mode 100644 index 000000000..7beeaced4 --- /dev/null +++ b/source/slang/slang-ir-type-set.cpp @@ -0,0 +1,229 @@ +// slang-ir-type-set.cpp +#include "slang-ir-type-set.h" + +#include "slang-ir.h" +#include "slang-ir-insts.h" + +namespace Slang +{ + +IRTypeSet::IRTypeSet(Session* session) +{ + m_sharedBuilder.module = nullptr; + m_sharedBuilder.session = session; + + m_builder.sharedBuilder = &m_sharedBuilder; + + m_module = m_builder.createModule(); + + m_sharedBuilder.module = m_module; + + m_builder.setInsertInto(m_module->getModuleInst()); +} + +IRTypeSet::~IRTypeSet() +{ + List types; + getTypes(types); + + for (auto type : types) + { + // We need to destroy references to instructions in other modules + if (type->getModule() == m_module) + { + // We want to remove arguments because an argument *could* be an instruction in another module, + // and we don't want to those modules insts to have uses, in this module which is being destroyed + type->removeArguments(); + } + } +} + +IRInst* IRTypeSet::cloneInst(IRInst* inst) +{ + if (inst == nullptr) + { + return nullptr; + } + + // See if it's already cloned + if (IRInst*const* newInstPtr = m_cloneMap.TryGetValue(inst)) + { + return *newInstPtr; + } + + IRModule* module = inst->getModule(); + // All inst's must belong to a module + SLANG_ASSERT(module); + + // If it's in this module then we don't need to clone + if (module == m_module) + { + return inst; + } + + if (isNominalOp(inst->op)) + { + // We can clone without any definition, and add the linkage + + // TODO(JS) + // This is arguably problematic - I'm adding an instruction from another module to the map, to be it's self. + // I did have code which created a copy of the nominal instruction and name hint, but because nominality means + // 'same address' other code would generate a different name for that instruction (say as compared to being a member in + // the original instruction) + // + // Because I use findOrAddInst which doesn't hoist instructions, the hoisting doesn't rely on parenting, that would + // break. + + // If nominal, we just use the original inst + m_cloneMap.Add(inst, inst); + return inst; + } + + // It would be nice if I could use ir-clone.cpp to do this -> but it doesn't clone + // operands. We wouldn't want to clone decorations, and it can't clone IRConstant(!) so + // it's no use + + IRInst* clone = nullptr; + switch (inst->op) + { + case kIROp_IntLit: + { + auto intLit = static_cast(inst); + IRType* clonedType = cloneType(intLit->getDataType()); + clone = m_builder.getIntValue(clonedType, intLit->value.intVal); + break; + } + case kIROp_StringLit: + { + auto stringLit = static_cast(inst); + clone = m_builder.getStringValue(stringLit->getStringSlice()); + break; + } + default: + { + if (IRBasicType::isaImpl(inst->op)) + { + clone = m_builder.getType(inst->op); + } + else + { + IRType* irType = dynamicCast(inst); + if (irType) + { + auto clonedType = cloneType(inst->getFullType()); + Index operandCount = Index(inst->getOperandCount()); + + List cloneOperands; + cloneOperands.setCount(operandCount); + + for (Index i = 0; i < operandCount; ++i) + { + cloneOperands[i] = cloneInst(inst->getOperand(i)); + } + + //clone = m_irBuilder.findOrEmitHoistableInst(cloneType, inst->op, operandCount, cloneOperands.getBuffer()); + + UInt operandCounts[1] = { UInt(operandCount) }; + IRInst*const* listOperands[1] = { cloneOperands.getBuffer() }; + + clone = m_builder.findOrAddInst(clonedType, inst->op, 1, operandCounts, listOperands); + } + else + { + // This cloning style only works on insts that are not unique + auto clonedType = cloneType(inst->getFullType()); + + Index operandCount = Index(inst->getOperandCount()); + clone = m_builder.emitIntrinsicInst(clonedType, inst->op, operandCount, nullptr); + for (Index i = 0; i < operandCount; ++i) + { + auto cloneOperand = cloneInst(inst->getOperand(i)); + clone->getOperands()[i].init(clone, cloneOperand); + } + } + } + break; + } + } + + m_cloneMap.Add(inst, clone); + return clone; +} + +IRType* IRTypeSet::add(IRType* irType) +{ + if (irType->getModule() == m_module) + { + return irType; + } + // We need to clone the type + return cloneType(irType); +} + +void IRTypeSet::getTypes(List& outTypes) const +{ + outTypes.clear(); + for (auto inst : m_module->getModuleInst()->getChildren()) + { + if (IRType* type = as(inst)) + { + outTypes.add(type); + } + } +} + +void IRTypeSet::getTypes(Kind kind, List& outTypes) const +{ + outTypes.clear(); + + for (auto inst : m_module->getModuleInst()->getChildren()) + { + IRType* type = nullptr; + + switch (kind) + { + case Kind::Scalar: + { + type = as(inst); + break; + } + case Kind::Vector: + { + type = as(inst); + break; + } + case Kind::Matrix: + { + type = as(inst); + break; + } + default: break; + } + + if (type) + { + outTypes.add(type); + } + } +} + +IRType* IRTypeSet::addVectorType(IRType* inElementType, int colsCount) +{ + IRType* elementType = cloneType(inElementType); + return m_builder.getVectorType(elementType, m_builder.getIntValue(m_builder.getIntType(), colsCount)); +} + +void IRTypeSet::addVectorForMatrixTypes() +{ + // Make a copy so we can alter m_types dictionary + List types; + getTypes(Kind::Matrix, types); + for (IRType* type : types) + { + SLANG_ASSERT(as(type)); + IRMatrixType* matType = static_cast(type); + m_builder.getVectorType(matType->getElementType(), matType->getColumnCount()); + } +} + +} -- cgit v1.2.3