From cd7f01b63a52eaaad00088524801e502bcb0f168 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 17 Jun 2020 13:08:27 -0700 Subject: Generate dynamic C++ code for the minimal test case. (#1391) * Add IR pass to lower generics into ordinary functions. * Fix project files * Emit dynamic C++ code for simple generics and witness tables. Fixes #1386. * Remove -dump-ir flag. * Fixups. --- source/slang/slang-emit-c-like.cpp | 95 +++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 16 deletions(-) (limited to 'source/slang/slang-emit-c-like.cpp') diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 911928e2a..eae3bdedc 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -217,8 +217,42 @@ void CLikeSourceEmitter::emitSimpleType(IRType* type) outNumThreads[i] = decor ? Int(getIntVal(decor->getOperand(i))) : 1; } return decor; -} - +} + +List CLikeSourceEmitter::getSortedWitnessTableEntries(IRWitnessTable* witnessTable) +{ + List sortedWitnessTableEntries; + auto interfaceType = cast(witnessTable->getOperand(0)); + auto witnessTableItems = witnessTable->getChildren(); + // Build a dictionary of witness table entries for fast lookup. + Dictionary witnessTableEntryDictionary; + for (auto item : witnessTableItems) + { + if (auto entry = as(item)) + { + witnessTableEntryDictionary[entry->getRequirementKey()] = entry; + } + } + // Get a sorted list of entries using RequirementKeys defined in `interfaceType`. + for (UInt i = 0; i < interfaceType->getOperandCount(); i++) + { + auto reqKey = cast(interfaceType->getOperand(i)); + bool matchingEntryFound = false; + IRWitnessTableEntry* entry = nullptr; + if (witnessTableEntryDictionary.TryGetValue(reqKey, entry)) + { + if (entry->requirementKey.get() == reqKey) + { + matchingEntryFound = true; + sortedWitnessTableEntries.add(entry); + break; + } + } + SLANG_ASSERT(matchingEntryFound); + } + return sortedWitnessTableEntries; +} + void CLikeSourceEmitter::_emitArrayType(IRArrayType* arrayType, EDeclarator* declarator) { EDeclarator arrayDeclarator; @@ -271,6 +305,12 @@ void CLikeSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable) SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "Unimplemented emit: IROpWitnessTable."); } +void CLikeSourceEmitter::emitInterface(IRInterfaceType* interfaceType) +{ + SLANG_UNUSED(interfaceType); + SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "Unimplemented emit: IROpInterfaceType."); +} + void CLikeSourceEmitter::emitTypeImpl(IRType* type, const StringSliceLoc* nameAndLoc) { if (nameAndLoc) @@ -890,6 +930,7 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst) case kIROp_FieldAddress: case kIROp_getElementPtr: case kIROp_Specialize: + case kIROp_lookup_interface_method: return true; } @@ -1849,6 +1890,31 @@ void CLikeSourceEmitter::emitIntrinsicCallExprImpl( } } +void CLikeSourceEmitter::_emitCallArgList(IRCall* inst) +{ + bool isFirstArg = true; + m_writer->emit("("); + UInt argCount = inst->getOperandCount(); + for (UInt aa = 1; aa < argCount; ++aa) + { + auto operand = inst->getOperand(aa); + if (as(operand->getDataType())) + continue; + + // TODO: [generate dynamic dispatch code for generics] + // Pass RTTI object here. Ignore type argument for now. + if (as(operand)) + continue; + + if (!isFirstArg) + m_writer->emit(", "); + else + isFirstArg = false; + emitOperand(inst->getOperand(aa), getInfo(EmitOp::General)); + } + m_writer->emit(")"); +} + void CLikeSourceEmitter::emitCallExpr(IRCall* inst, EmitOpInfo outerPrec) { auto funcValue = inst->getOperand(0); @@ -1868,18 +1934,7 @@ void CLikeSourceEmitter::emitCallExpr(IRCall* inst, EmitOpInfo outerPrec) bool needClose = maybeEmitParens(outerPrec, prec); emitOperand(funcValue, leftSide(outerPrec, prec)); - m_writer->emit("("); - UInt argCount = inst->getOperandCount(); - for( UInt aa = 1; aa < argCount; ++aa ) - { - auto operand = inst->getOperand(aa); - if (as(operand->getDataType())) - continue; - if(aa != 1) m_writer->emit(", "); - emitOperand(inst->getOperand(aa), getInfo(EmitOp::General)); - } - m_writer->emit(")"); - + _emitCallArgList(inst); maybeCloseParens(needClose); } } @@ -3522,6 +3577,10 @@ void CLikeSourceEmitter::emitGlobalInst(IRInst* inst) emitStruct(cast(inst)); break; + case kIROp_InterfaceType: + emitInterface(cast(inst)); + break; + case kIROp_WitnessTable: emitWitnessTable(cast(inst)); break; @@ -3576,11 +3635,15 @@ void CLikeSourceEmitter::ensureInstOperandsRec(ComputeEmitActionsContext* ctx, I void CLikeSourceEmitter::ensureGlobalInst(ComputeEmitActionsContext* ctx, IRInst* inst, EmitAction::Level requiredLevel) { - // Skip certain instructions, since they - // don't affect output. + // Skip certain instructions that don't affect output. switch(inst->op) { case kIROp_WitnessTable: + // Only skip witness tables when we are generating + // static code. + if (!m_compileRequest->allowDynamicCode) + return; + break; case kIROp_Generic: return; -- cgit v1.2.3