diff options
| -rw-r--r-- | source/slang/check.cpp | 6 | ||||
| -rw-r--r-- | source/slang/compiler.cpp | 16 | ||||
| -rw-r--r-- | source/slang/diagnostics.cpp | 30 | ||||
| -rw-r--r-- | source/slang/diagnostics.h | 6 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 74 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 80 | ||||
| -rw-r--r-- | source/slang/modifier-defs.h | 17 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 11 | ||||
| -rw-r--r-- | source/slang/slang-stdlib.cpp | 12 |
9 files changed, 236 insertions, 16 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index b87f7c6bc..b175b7f86 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -2540,7 +2540,11 @@ namespace Slang if (!type.IsLeftValue) { - if (!isRewriteMode()) + if (type->As<ErrorType>()) + { + // Don't report an l-value issue on an errorneous expression + } + else if (!isRewriteMode()) { getSink()->diagnose(expr, Diagnostics::assignNonLValue); } diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 7df978707..284bb200a 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -236,15 +236,14 @@ namespace Slang // TODO(tfoley): need a better policy for how we translate diagnostics // back into the Slang world (although we should always try to generate // HLSL that doesn't produce any diagnostics...) - String diagnostics = (char const*) diagnosticsBlob->GetBufferPointer(); - fprintf(stderr, "%s", diagnostics.begin()); - OutputDebugStringA(diagnostics.begin()); + entryPoint->compileRequest->mSink.diagnoseRaw( + FAILED(hr) ? Severity::Error : Severity::Warning, + (char const*) diagnosticsBlob->GetBufferPointer()); diagnosticsBlob->Release(); } if (FAILED(hr)) { - // TODO(tfoley): What to do on failure? - exit(1); + return List<uint8_t>(); } return data; } @@ -376,9 +375,10 @@ namespace Slang if (err) { - OutputDebugStringA(diagnosticOutput.Buffer()); - fprintf(stderr, "%s", diagnosticOutput.Buffer()); - exit(1); + entryPoint->compileRequest->mSink.diagnoseRaw( + Severity::Error, + diagnosticOutput.begin()); + return err; } return 0; diff --git a/source/slang/diagnostics.cpp b/source/slang/diagnostics.cpp index 0c55a94bd..870e6d172 100644 --- a/source/slang/diagnostics.cpp +++ b/source/slang/diagnostics.cpp @@ -194,6 +194,36 @@ void DiagnosticSink::diagnoseImpl(CodePosition const& pos, DiagnosticInfo const& } } +void DiagnosticSink::diagnoseRaw( + Severity severity, + char const* message) +{ + if (severity >= Severity::Error) + { + errorCount++; + } + + // Did the client supply a callback for us to use? + if( callback ) + { + // If so, pass the error string along to them + callback(message, callbackUserData); + } + else + { + // If the user doesn't have a callback, then just + // collect our diagnostic messages into a buffer + outputBuffer.append(message); + } + + if (severity >= Severity::Fatal) + { + // TODO: figure out a better policy for aborting compilation + throw InvalidOperationException(); + } +} + + namespace Diagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, messageFormat }; diff --git a/source/slang/diagnostics.h b/source/slang/diagnostics.h index 8834f1a6e..6957fc763 100644 --- a/source/slang/diagnostics.h +++ b/source/slang/diagnostics.h @@ -185,6 +185,12 @@ namespace Slang } void diagnoseImpl(CodePosition const& pos, DiagnosticInfo const& info, int argCount, DiagnosticArg const* const* args); + + // Add a diagnostic with raw text + // (used when we get errors from a downstream compiler) + void diagnoseRaw( + Severity severity, + char const* message); }; namespace Diagnostics diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 03cc7d8aa..6905a8a76 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -52,6 +52,10 @@ struct SharedEmitContext ProgramSyntaxNode* program; bool needHackSamplerForTexelFetch = false; + + // Record the GLSL extnsions we have already emitted a `#extension` for + HashSet<String> glslExtensionsRequired; + StringBuilder glslExtensionRequireLines; }; struct EmitContext @@ -450,7 +454,17 @@ struct EmitVisitor emitRawText(" "); - if(context->shared->target == CodeGenTarget::GLSL) + bool shouldUseGLSLStyleLineDirective = false; + + // Let's not do this +#if 0 + if (context->shared->target == CodeGenTarget::GLSL) + { + shouldUseGLSLStyleLineDirective = true; + } +#endif + + if(shouldUseGLSLStyleLineDirective) { auto path = sourceLocation.FileName; @@ -1584,6 +1598,19 @@ struct EmitVisitor } } + void requireGLSLExtension(String const& name) + { + if (context->shared->glslExtensionsRequired.Contains(name)) + return; + + StringBuilder& sb = context->shared->glslExtensionRequireLines; + + sb.append("#extension "); + sb.append(name); + sb.append(" : require\n"); + + context->shared->glslExtensionsRequired.Add(name); + } void visitInvokeExpressionSyntaxNode( RefPtr<InvokeExpressionSyntaxNode> callExpr, @@ -1698,6 +1725,17 @@ struct EmitVisitor } else if(auto targetIntrinsicModifier = findTargetIntrinsicModifier(funcDecl)) { + if (context->shared->target == CodeGenTarget::GLSL) + { + // Does this intrinsic requie a particular GLSL extension that wouldn't be available by default? + if (auto requiredGLSLExtensionModifier = funcDecl->FindModifier<RequiredGLSLExtensionModifier>()) + { + // If so, we had better request the extension. + requireGLSLExtension(requiredGLSLExtensionModifier->extensionNameToken.Content); + } + } + + if(targetIntrinsicModifier->definitionToken.Type != TokenType::Unknown) { auto name = getStringOrIdentifierTokenValue(targetIntrinsicModifier->definitionToken); @@ -2546,6 +2584,35 @@ struct EmitVisitor Emit(";\n"); } + bool shouldSkipModifierForDecl( + Modifier* modifier, + Decl* decl) + { + switch(context->shared->target) + { + default: + break; + + case CodeGenTarget::GLSL: + { + // Don't emit interpolation mode modifiers on `struct` fields + // (only allowed on global or block `in`/`out`) + if (auto interpolationMod = dynamic_cast<InterpolationModeModifier*>(modifier)) + { + if (auto fieldDecl = dynamic_cast<StructField*>(decl)) + { + return true; + } + } + + } + break; + } + + + return false; + } + // Emit any modifiers that should go in front of a declaration void EmitModifiers(RefPtr<Decl> decl) { @@ -2577,6 +2644,9 @@ struct EmitVisitor for (auto mod = decl->modifiers.first; mod; mod = mod->next) { + if (shouldSkipModifierForDecl(mod, decl)) + continue; + advanceToSourceLocation(mod->Position); if (0) {} @@ -3508,6 +3578,8 @@ String emitEntryPoint( StringBuilder finalResultBuilder; finalResultBuilder << prefix; + finalResultBuilder << sharedContext.glslExtensionRequireLines.ProduceString(); + if (sharedContext.needHackSamplerForTexelFetch) { finalResultBuilder << "layout(set = 0, binding = 0) uniform sampler SLANG_hack_samplerForTexelFetch;\n"; diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 02da47ccb..c7278201a 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -631,6 +631,69 @@ struct LoweringVisitor return loweredExpr; } + RefPtr<ExpressionSyntaxNode> createAssignExpr( + RefPtr<ExpressionSyntaxNode> leftExpr, + RefPtr<ExpressionSyntaxNode> rightExpr) + { + auto leftTuple = leftExpr.As<TupleExpr>(); + auto rightTuple = rightExpr.As<TupleExpr>(); + if (leftTuple && rightTuple) + { + RefPtr<TupleExpr> resultTuple = new TupleExpr(); + resultTuple->Type = leftExpr->Type; + + if (leftTuple->primaryExpr) + { + assert(rightTuple->primaryExpr); + + resultTuple->primaryExpr = createAssignExpr( + leftTuple->primaryExpr, + rightTuple->primaryExpr); + } + + auto elementCount = leftTuple->tupleElements.Count(); + assert(elementCount == rightTuple->tupleElements.Count()); + for (UInt ee = 0; ee < elementCount; ++ee) + { + auto leftElement = leftTuple->tupleElements[ee]; + auto rightElement = rightTuple->tupleElements[ee]; + + TupleExpr::Element resultElement; + + resultElement.tupleFieldDeclRef = leftElement.tupleFieldDeclRef; + resultElement.expr = createAssignExpr( + leftElement.expr, + rightElement.expr); + + resultTuple->tupleElements.Add(resultElement); + } + + return resultTuple; + } + else + { + assert(!leftTuple && !rightTuple); + } + + + RefPtr<AssignExpr> loweredExpr = new AssignExpr(); + loweredExpr->Type = leftExpr->Type; + loweredExpr->left = leftExpr; + loweredExpr->right = rightExpr; + return loweredExpr; + } + + RefPtr<ExpressionSyntaxNode> visitAssignExpr( + AssignExpr* expr) + { + auto leftExpr = lowerExpr(expr->left); + auto rightExpr = lowerExpr(expr->right); + + auto loweredExpr = createAssignExpr(leftExpr, rightExpr); + lowerExprCommon(loweredExpr, expr); + return loweredExpr; + } + void addArgs( InvokeExpressionSyntaxNode* callExpr, RefPtr<ExpressionSyntaxNode> argExpr) @@ -917,8 +980,21 @@ struct LoweringVisitor void addExprStmt( RefPtr<ExpressionSyntaxNode> expr) { - // TODO: handle cases where the `expr` cannot be directly - // represented as a single statement + // Desugar tuples in statement position + if (auto tupleExpr = expr.As<TupleExpr>()) + { + if (tupleExpr->primaryExpr) + { + addExprStmt(tupleExpr->primaryExpr); + } + for (auto ee : tupleExpr->tupleElements) + { + addExprStmt(ee.expr); + } + return; + } + + // TODO: could also desugar "operator comma" here RefPtr<ExpressionStatementSyntaxNode> stmt = new ExpressionStatementSyntaxNode(); stmt->Expression = expr; diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h index c401b3353..9806a12a5 100644 --- a/source/slang/modifier-defs.h +++ b/source/slang/modifier-defs.h @@ -53,6 +53,12 @@ SYNTAX_CLASS(TargetIntrinsicModifier, IntrinsicModifierBase) FIELD(Token, definitionToken) END_SYNTAX_CLASS() +// A modifier to tag something as an intrinsic that requires +// a certain GLSL extension to be enabled when used +SYNTAX_CLASS(RequiredGLSLExtensionModifier, Modifier) + FIELD(Token, extensionNameToken) +END_SYNTAX_CLASS() + SIMPLE_SYNTAX_CLASS(InOutModifier, OutModifier) // This is a special sentinel modifier that gets added @@ -208,17 +214,20 @@ SIMPLE_SYNTAX_CLASS(GLSLColumnMajorLayoutModifier, RowMajorLayoutModifier) // More HLSL Keyword +ABSTRACT_SYNTAX_CLASS(InterpolationModeModifier, Modifier) +END_SYNTAX_CLASS() + // HLSL `nointerpolation` modifier -SIMPLE_SYNTAX_CLASS(HLSLNoInterpolationModifier, Modifier) +SIMPLE_SYNTAX_CLASS(HLSLNoInterpolationModifier, InterpolationModeModifier) // HLSL `linear` modifier -SIMPLE_SYNTAX_CLASS(HLSLLinearModifier, Modifier) +SIMPLE_SYNTAX_CLASS(HLSLLinearModifier, InterpolationModeModifier) // HLSL `sample` modifier -SIMPLE_SYNTAX_CLASS(HLSLSampleModifier, Modifier) +SIMPLE_SYNTAX_CLASS(HLSLSampleModifier, InterpolationModeModifier) // HLSL `centroid` modifier -SIMPLE_SYNTAX_CLASS(HLSLCentroidModifier, Modifier) +SIMPLE_SYNTAX_CLASS(HLSLCentroidModifier, InterpolationModeModifier) // HLSL `precise` modifier SIMPLE_SYNTAX_CLASS(HLSLPreciseModifier, Modifier) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index de63793b1..8314b0930 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -717,6 +717,17 @@ namespace Slang AddModifier(&modifierLink, modifier); } + else if (AdvanceIf(parser, "__glsl_extension")) + { + auto modifier = new RequiredGLSLExtensionModifier(); + modifier->Position = loc; + + parser->ReadToken(TokenType::LParent); + modifier->extensionNameToken = parser->ReadToken(TokenType::Identifier); + parser->ReadToken(TokenType::RParent); + + AddModifier(&modifierLink, modifier); + } else if (AdvanceIf(parser, "layout")) { diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index bcc87b201..563f5a015 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -413,27 +413,33 @@ __intrinsic matrix<T,N,M> ddx(matrix<T,N,M> x); __generic<T : __BuiltinFloatingPointType> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdxCoarse) __intrinsic T ddx_coarse(T x); __generic<T : __BuiltinFloatingPointType, let N : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdxCoarse) __intrinsic vector<T,N> ddx_coarse(vector<T,N> x); __generic<T : __BuiltinFloatingPointType, let N : int, let M : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdxCoarse) __intrinsic matrix<T,N,M> ddx_coarse(matrix<T,N,M> x); __generic<T : __BuiltinFloatingPointType> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdxFine) __intrinsic T ddx_fine(T x); __generic<T : __BuiltinFloatingPointType, let N : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdxFine) __intrinsic vector<T,N> ddx_fine(vector<T,N> x); __generic<T : __BuiltinFloatingPointType, let N : int, let M : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdxFine) __intrinsic matrix<T,N,M> ddx_fine(matrix<T,N,M> x); @@ -452,27 +458,33 @@ __intrinsic matrix<T,N,M> ddy(matrix<T,N,M> x); __generic<T : __BuiltinFloatingPointType> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdyCoarse) __intrinsic T ddy_coarse(T x); __generic<T : __BuiltinFloatingPointType, let N : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdyCoarse) __intrinsic vector<T,N> ddy_coarse(vector<T,N> x); __generic<T : __BuiltinFloatingPointType, let N : int, let M : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdyCoarse) __intrinsic matrix<T,N,M> ddy_coarse(matrix<T,N,M> x); __generic<T : __BuiltinFloatingPointType> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdyFine) __intrinsic T ddy_fine(T x); __generic<T : __BuiltinFloatingPointType, let N : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdyFine) __intrinsic vector<T,N> ddy_fine(vector<T,N> x); __generic<T : __BuiltinFloatingPointType, let N : int, let M : int> +__glsl_extension(GL_ARB_derivative_control) __intrinsic(glsl, dFdyFine) __intrinsic matrix<T,N,M> ddy_fine(matrix<T,N,M> x); |
