diff options
| author | Yong He <yonghe@outlook.com> | 2020-06-17 22:41:56 -0700 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2020-06-17 23:47:11 -0700 |
| commit | 8c6e02bd094bbc0c9afb141265be9675f99ddb61 (patch) | |
| tree | 1c81d73c1b1eddcc3e00fe1ff28816d6dec0c032 /source/slang/slang-emit-cpp.cpp | |
| parent | d1a8cd23d15d0001131b6f01b0c9bc461279f760 (diff) | |
Dynamic dipatch non-static functions.
Diffstat (limited to 'source/slang/slang-emit-cpp.cpp')
| -rw-r--r-- | source/slang/slang-emit-cpp.cpp | 147 |
1 files changed, 144 insertions, 3 deletions
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index c31ef3bc7..cf6a5af49 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -1446,6 +1446,24 @@ UnownedStringSlice CPPSourceEmitter::_getFuncName(const HLSLIntrinsic* specOp) return m_slicePool.getSlice(handle); } +UnownedStringSlice CPPSourceEmitter::_getWitnessTableWrapperFuncName(IRFunc* func) +{ + StringSlicePool::Handle handle = StringSlicePool::kNullHandle; + if (m_witnessTableWrapperFuncNameMap.TryGetValue(func, handle)) + { + return m_slicePool.getSlice(handle); + } + + StringBuilder builder; + builder << getName(func) << "_wtwrapper"; + + handle = m_slicePool.add(builder); + m_witnessTableWrapperFuncNameMap.Add(func, handle); + + SLANG_ASSERT(handle != StringSlicePool::kNullHandle); + return m_slicePool.getSlice(handle); +} + SlangResult CPPSourceEmitter::calcFuncName(const HLSLIntrinsic* specOp, StringBuilder& outBuilder) { typedef HLSLIntrinsic::Op Op; @@ -1591,6 +1609,83 @@ void CPPSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable) pendingWitnessTableDefinitions.add(witnessTable); } +void CPPSourceEmitter::_emitWitnessTableWrappers() +{ + for (auto witnessTable : pendingWitnessTableDefinitions) + { + for (auto child : witnessTable->getChildren()) + { + if (auto entry = as<IRWitnessTableEntry>(child)) + { + if (auto funcVal = as<IRFunc>(entry->getSatisfyingVal())) + { + emitType(funcVal->getResultType()); + m_writer->emit(" "); + m_writer->emit(_getWitnessTableWrapperFuncName(funcVal)); + m_writer->emit("("); + // Emit parameter list. + { + bool isFirst = true; + for (auto param : funcVal->getParams()) + { + if (as<IRTypeType>(param->getFullType())) + continue; + + if (isFirst) + isFirst = false; + else + m_writer->emit(","); + + if (param->findDecoration<IRThisPointerDecoration>()) + { + m_writer->emit("void* "); + m_writer->emit(getName(param)); + continue; + } + emitSimpleFuncParamImpl(param); + } + } + m_writer->emit(")\n{\n"); + m_writer->indent(); + m_writer->emit("return "); + m_writer->emit(getName(funcVal)); + m_writer->emit("("); + // Emit argument list. + { + bool isFirst = true; + for (auto param : funcVal->getParams()) + { + if (as<IRTypeType>(param->getFullType())) + continue; + + if (isFirst) + isFirst = false; + else + m_writer->emit(", "); + + if (param->findDecoration<IRThisPointerDecoration>()) + { + m_writer->emit("*static_cast<"); + emitType(param->getFullType()); + m_writer->emit("*>("); + m_writer->emit(getName(param)); + m_writer->emit(")"); + } + else + { + m_writer->emit(getName(param)); + } + } + } + m_writer->emit(");\n"); + m_writer->dedent(); + m_writer->emit("}\n"); + } + } + } + } +} + void CPPSourceEmitter::_emitWitnessTableDefinitions() { for (auto witnessTable : pendingWitnessTableDefinitions) @@ -1613,7 +1708,7 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions() else isFirstEntry = false; m_writer->emit("&Context::"); - m_writer->emit(getName(funcVal)); + m_writer->emit(_getWitnessTableWrapperFuncName(funcVal)); } else { @@ -1671,7 +1766,13 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition( m_writer->emit(", "); else isFirstParam = false; - emitParamType(param->getFullType(), getName(param)); + if (param->findDecoration<IRThisPointerDecoration>()) + { + m_writer->emit("void* "); + m_writer->emit(getName(param)); + continue; + } + emitSimpleFuncParamImpl(param); } m_writer->emit(");\n"); } @@ -1681,7 +1782,7 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition( } } m_writer->dedent(); - m_writer->emit("\n};\n"); + m_writer->emit("};\n"); } bool CPPSourceEmitter::tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType) @@ -1877,6 +1978,31 @@ void CPPSourceEmitter::emitSimpleValueImpl(IRInst* inst) } } +static bool isVoidPtrType(IRType* type) +{ + auto ptrType = as<IRPtrType>(type); + if (!ptrType) return false; + return ptrType->getValueType()->op == kIROp_VoidType; +} + +void CPPSourceEmitter::emitSimpleFuncParamImpl(IRParam* param) +{ + // Polymorphic types are already translated to void* type in + // lower-generics pass. However, the current emitting logic will + // emit "void&" instead of "void*" for pointer types. + // In the future, we will handle pointer types more properly, + // and this override logic will not be necessary. + // For now we special-case this scenario. + if (param->findDecoration<IRPolymorphicDecoration>() && + isVoidPtrType(param->getDataType())) + { + m_writer->emit("void* "); + m_writer->emit(getName(param)); + return; + } + CLikeSourceEmitter::emitSimpleFuncParamImpl(param); +} + void CPPSourceEmitter::emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount) { emitSimpleType(m_typeSet.addVectorType(elementType, int(elementCount))); @@ -2102,6 +2228,16 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut m_writer->emit(")"); return true; } + case kIROp_getAddr: + { + // Once we clean up the pointer emitting logic, we can + // just use GetElementAddress instruction in place of + // getAddr instruction, and this case can be removed. + m_writer->emit("(&("); + emitInstExpr(inst->getOperand(0), EmitOpInfo::get(EmitOp::General)); + m_writer->emit("))"); + return true; + } } } @@ -2658,6 +2794,11 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module) } } + // Emit wrapper functions for each witness table entry. + // These wrapper functions takes an abstract type parameter (void*) + // in the place of `this` parameter. + _emitWitnessTableWrappers(); + m_writer->dedent(); m_writer->emit("};\n\n"); } |
