diff options
| author | Yong He <yonghe@outlook.com> | 2022-06-21 14:55:59 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-21 14:55:59 -0700 |
| commit | e5a75563a1ba2e378353af8b937b8b7bb0fe2c2b (patch) | |
| tree | 0f31040b408a66f49dc5cd2354c8424e5ff2e279 /source/slang/slang-ir-marshal-native-call.cpp | |
| parent | ea3800e115d4ad1ce06ec07689152616f47a0e3d (diff) | |
Lower throwing COM interface method. (#2282)
* Lower throwing COM interface method.
* Fix.
* Fix warnings.
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-ir-marshal-native-call.cpp')
| -rw-r--r-- | source/slang/slang-ir-marshal-native-call.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/source/slang/slang-ir-marshal-native-call.cpp b/source/slang/slang-ir-marshal-native-call.cpp new file mode 100644 index 000000000..b8e2edb2f --- /dev/null +++ b/source/slang/slang-ir-marshal-native-call.cpp @@ -0,0 +1,149 @@ +// slang-ir-marshal-native-call.h +#include "slang-ir-marshal-native-call.h" +#include "slang-ir.h" +#include "slang-ir-insts.h" + +namespace Slang +{ + + IRType* NativeCallMarshallingContext::getNativeType(IRBuilder& builder, IRType* type) + { + switch (type->getOp()) + { + case kIROp_StringType: + return builder.getNativeStringType(); + default: + return type; + } + } + + IRFuncType* NativeCallMarshallingContext::getNativeFuncType( + IRBuilder& builder, IRFuncType* declaredFuncType) + { + List<IRInst*> nativeParamTypes; + assert(declaredFuncType->getOp() == kIROp_FuncType); + for (UInt i = 0; i < declaredFuncType->getParamCount(); ++i) + { + auto paramType = declaredFuncType->getParamType(i); + nativeParamTypes.add(getNativeType(builder, as<IRType>(paramType))); + } + IRType* returnType = declaredFuncType->getResultType(); + if (auto resultType = as<IRResultType>(declaredFuncType->getResultType())) + { + nativeParamTypes.add(builder.getPtrType(resultType->getValueType())); + returnType = resultType->getErrorType(); + } + getNativeType(builder, declaredFuncType->getResultType()); + auto funcType = builder.getFuncType( + nativeParamTypes.getCount(), (IRType**)nativeParamTypes.getBuffer(), returnType); + + return funcType; + } + + void NativeCallMarshallingContext::marshalRefManagedValueToNativeValue( + IRBuilder& builder, IRInst* originalArg, List<IRInst*>& args) + { + SLANG_UNUSED(builder); + SLANG_UNUSED(originalArg); + args.add(originalArg); + } + + void NativeCallMarshallingContext::marshalManagedValueToNativeValue( + IRBuilder& builder, IRInst* originalArg, List<IRInst*>& args) + { + switch (originalArg->getDataType()->getOp()) + { + case kIROp_InOutType: + case kIROp_RefType: + return marshalRefManagedValueToNativeValue( + builder, originalArg, args); + case kIROp_StringType: + { + auto nativeStr = builder.emitGetNativeString(originalArg); + args.add(nativeStr); + } + break; + default: + args.add(originalArg); + break; + } + } + + IRInst* NativeCallMarshallingContext::marshalNativeValueToManagedValue( + IRBuilder& builder, IRInst* nativeVal) + { + switch (nativeVal->getDataType()->getOp()) + { + case kIROp_NativeStringType: + { + return builder.emitMakeString(nativeVal); + } + break; + default: + return nativeVal; + break; + } + } + + IRInst* NativeCallMarshallingContext::marshalNativeCall( + IRBuilder& builder, + IRFuncType* originalFuncType, + IRFuncType* nativeFuncType, + IRInst* nativeFunc, + Int argCount, + IRInst*const* originalArgs) + { + // Marshal parameters to arguments into native func. + List<IRInst*> args; + for (Int i = 0; i < argCount; i++) + { + marshalManagedValueToNativeValue(builder, originalArgs[i], args); + } + IRType* originalReturnType = originalFuncType->getResultType(); + + IRVar* resultVar = nullptr; + if (auto resultType = as<IRResultType>(originalReturnType)) + { + // Declare a local variable to receive result. + resultVar = builder.emitVar(getNativeType(builder, resultType->getValueType())); + args.add(resultVar); + } + + // Insert call. + IRInst* call = builder.emitCallInst(nativeFuncType->getResultType(), nativeFunc, args); + + // TODO: marshal output/ref args back to original args. + + IRInst* returnValue = call; + + // Marshal result and out arguments back to managed values. + if (auto resultType = as<IRResultType>(originalReturnType)) + { + auto val = builder.emitLoad(resultVar); + auto err = call; + val = marshalNativeValueToManagedValue(builder, val); + auto intErr = err; + if (err->getDataType()->getOp() != kIROp_IntType) + { + intErr = builder.emitConstructorInst(builder.getIntType(), 1, &err); + } + auto errIsError = builder.emitLess(intErr, builder.getIntValue(builder.getIntType(), 0)); + IRBlock *trueBlock, *falseBlock, *afterBlock; + builder.emitIfElseWithBlocks(errIsError, trueBlock, falseBlock, afterBlock); + builder.setInsertInto(trueBlock); + returnValue = builder.emitMakeResultError(resultType, err); + builder.emitBranch(afterBlock, 1, &returnValue); + builder.setInsertInto(falseBlock); + returnValue = builder.emitMakeResultValue(resultType, val); + builder.emitBranch(afterBlock, 1, &returnValue); + builder.setInsertInto(afterBlock); + returnValue = builder.emitParam(resultType); + } + else + { + returnValue = marshalNativeValueToManagedValue(builder, call); + } + return returnValue; + } + +} // namespace Slang |
