diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-05-29 11:39:55 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-05-29 11:39:55 -0700 |
| commit | e7a83323bfc4dd698ef491375a37c65c83915951 (patch) | |
| tree | 4dc8d7ac5c192817a6d3fa680b731723ff9eba27 /source/slang/lower-to-ir.cpp | |
| parent | ace9a8dc7e4353b1cf8e846abe2b8dc53ecdbc59 (diff) | |
Fix global atomic functions (#582)
Fixes #581
This change adds a new parameter passing mode `__ref` to exist alongisde `in`, `out`, and `inout`.
The `__ref` modifier indicates true by-reference parameter passing (whereas `inout` is copy-in-copy-out).
This is not intended to be something that users interact with directly, but rather a low-level feature that lets us provide a correct signature for the `Interlocked*()` operations in the standard library.
Most of the support for passing what are logically addresses around already exists in the IR, so the majority of the work here is just in introducing the new type `Ref<T>` and then using it appropriately when lowering `__ref` parameters/arguments to the IR.
Diffstat (limited to 'source/slang/lower-to-ir.cpp')
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 81520abf5..96b28a15b 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -922,6 +922,11 @@ void assign( LoweredValInfo const& left, LoweredValInfo const& right); +IRInst* getAddress( + IRGenContext* context, + LoweredValInfo const& inVal, + SourceLoc diagnosticLocation); + void lowerStmt( IRGenContext* context, Stmt* stmt); @@ -1668,7 +1673,24 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo> // make a conscious decision at some point. } - if (paramDecl->HasModifier<OutModifier>() + if(paramDecl->HasModifier<RefModifier>()) + { + // A `ref` qualified parameter must be implemented with by-reference + // parameter passing, so the argument value should be lowered as + // an l-value. + // + LoweredValInfo loweredArg = lowerLValueExpr(context, argExpr); + + // According to our "calling convention" we need to + // pass a pointer into the callee. Unlike the case for + // `out` and `inout` below, it is never valid to do + // copy-in/copy-out for a `ref` parameter, so we just + // pass in the actual pointer. + // + IRInst* argPtr = getAddress(context, loweredArg, argExpr->loc); + (*ioArgs).Add(argPtr); + } + else if (paramDecl->HasModifier<OutModifier>() || paramDecl->HasModifier<InOutModifier>()) { // This is a `out` or `inout` parameter, and so @@ -2930,6 +2952,26 @@ static LoweredValInfo maybeMoveMutableTemp( } } +IRInst* getAddress( + IRGenContext* context, + LoweredValInfo const& inVal, + SourceLoc diagnosticLocation) +{ + LoweredValInfo val = inVal; + switch(val.flavor) + { + case LoweredValInfo::Flavor::Ptr: + return val.val; + + // TODO: are there other cases we need to handle here (e.g., + // turning a bound subscript/property into an address) + + default: + context->getSink()->diagnose(diagnosticLocation, Diagnostics::invalidLValueForRefParameter); + return nullptr; + } +} + void assign( IRGenContext* context, LoweredValInfo const& inLeft, @@ -3831,9 +3873,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // enum ParameterDirection { - kParameterDirection_In, - kParameterDirection_Out, - kParameterDirection_InOut, + kParameterDirection_In, ///< Copy in + kParameterDirection_Out, ///< Copy out + kParameterDirection_InOut, ///< Copy in, copy out + kParameterDirection_Ref, ///< By-reference }; struct ParameterInfo { @@ -3856,6 +3899,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // ParameterDirection getParameterDirection(VarDeclBase* paramDecl) { + if( paramDecl->HasModifier<RefModifier>() ) + { + // The AST specified `ref`: + return kParameterDirection_Ref; + } if( paramDecl->HasModifier<InOutModifier>() ) { // The AST specified `inout`: @@ -4350,6 +4398,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> case kParameterDirection_InOut: irParamType = subBuilder->getInOutType(irParamType); break; + case kParameterDirection_Ref: + irParamType = subBuilder->getRefType(irParamType); + break; default: SLANG_UNEXPECTED("unknown parameter direction"); |
