summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-06-19 14:42:18 -0700
committerGitHub <noreply@github.com>2017-06-19 14:42:18 -0700
commit5b85b51686bafe969c4d1c75b59aa17bc014367a (patch)
treef097eadefa23fb2127ceb0ebdcec9712ae394c1b /source
parent110b0b396dd086222e43fa80090d2fd415b2b0a9 (diff)
parent947cb6ae2d78c724a36ab004061dc99cd911969b (diff)
Merge pull request #32 from tfoleyNV/line-directives
Line directives
Diffstat (limited to 'source')
-rw-r--r--source/slang/emit.cpp168
1 files changed, 150 insertions, 18 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index ef5df830f..21704f6ff 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -19,6 +19,8 @@ struct EmitContext
// Current source position for tracking purposes...
CodePosition loc;
+ CodePosition nextSourceLocation;
+ bool needToUpdateSourceLocation;
// The target language we want to generate code for
CodeGenTarget target;
@@ -39,12 +41,26 @@ struct EmitContext
static void EmitDecl(EmitContext* context, RefPtr<Decl> decl);
static void EmitDecl(EmitContext* context, RefPtr<DeclBase> declBase);
static void EmitDeclUsingLayout(EmitContext* context, RefPtr<Decl> decl, RefPtr<VarLayout> layout);
+
+static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, Token const& nameToken);
static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, String const& name);
static void EmitType(EmitContext* context, RefPtr<ExpressionType> type);
+
+static void EmitType(EmitContext* context, TypeExp const& typeExp, Token const& nameToken);
+static void EmitType(EmitContext* context, TypeExp const& typeExp, String const& name);
+static void EmitType(EmitContext* context, TypeExp const& typeExp);
+
static void EmitExpr(EmitContext* context, RefPtr<ExpressionSyntaxNode> expr);
static void EmitStmt(EmitContext* context, RefPtr<StatementSyntaxNode> stmt);
static void EmitDeclRef(EmitContext* context, DeclRef<Decl> declRef);
+static void advanceToSourceLocation(
+ EmitContext* context,
+ CodePosition const& sourceLocation);
+
+static void flushSourceLocationChange(
+ EmitContext* context);
+
// Low-level emit logic
static void emitRawTextSpan(EmitContext* context, char const* textBegin, char const* textEnd)
@@ -62,6 +78,10 @@ static void emitRawText(EmitContext* context, char const* text)
static void emitTextSpan(EmitContext* context, char const* textBegin, char const* textEnd)
{
+ // If the source location has changed in a way that required update,
+ // do it now!
+ flushSourceLocationChange(context);
+
// Emit the raw text
emitRawTextSpan(context, textBegin, textEnd);
@@ -116,7 +136,10 @@ static bool isReservedWord(EmitContext* context, String const& name)
return context->reservedWords.TryGetValue(name) != nullptr;
}
-static void emitName(EmitContext* context, String const& inName)
+static void emitName(
+ EmitContext* context,
+ String const& inName,
+ CodePosition const& loc)
{
String name = inName;
@@ -149,9 +172,20 @@ static void emitName(EmitContext* context, String const& inName)
name = name + "_";
}
+ advanceToSourceLocation(context, loc);
emit(context, name);
}
+static void emitName(EmitContext* context, Token const& nameToken)
+{
+ emitName(context, nameToken.Content, nameToken.Position);
+}
+
+static void emitName(EmitContext* context, String const& name)
+{
+ emitName(context, name, CodePosition());
+}
+
static void Emit(EmitContext* context, UInt value)
{
char buffer[32];
@@ -796,6 +830,10 @@ static void EmitExprWithPrecedence(EmitContext* context, RefPtr<ExpressionSyntax
{
needClose = MaybeEmitParens(context, outerPrec, kPrecedence_Atomic);
+ // TODO: This won't be valid if we had to generate a qualified
+ // reference for some reason.
+ advanceToSourceLocation(context, varExpr->Position);
+
// Because of the "rewriter" use case, it is possible that we will
// be trying to emit an expression that hasn't been wired up to
// any associated declaration. In that case, we will just emit
@@ -917,6 +955,7 @@ struct EDeclarator
// Used for `Flavor::Name`
String name;
+ CodePosition loc;
// Used for `Flavor::Array`
IntVal* elementCount;
@@ -931,7 +970,7 @@ static void EmitDeclarator(EmitContext* context, EDeclarator* declarator)
switch (declarator->flavor)
{
case EDeclarator::Flavor::Name:
- emitName(context, declarator->name);
+ emitName(context, declarator->name, declarator->loc);
break;
case EDeclarator::Flavor::Array:
@@ -1040,7 +1079,7 @@ static void emitHLSLTextureType(
}
Emit(context, "<");
EmitType(context, texType->elementType);
- Emit(context, ">");
+ Emit(context, " >");
}
static void emitGLSLTextureOrTextureSamplerType(
@@ -1196,7 +1235,6 @@ static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, EDeclara
break;
}
- Emit(context, " ");
EmitDeclarator(context, declarator);
return;
}
@@ -1234,28 +1272,24 @@ static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, EDeclara
break;
}
- Emit(context, " ");
EmitDeclarator(context, declarator);
return;
}
else if (auto texType = type->As<TextureType>())
{
emitTextureType(context, texType);
- Emit(context, " ");
EmitDeclarator(context, declarator);
return;
}
else if (auto textureSamplerType = type->As<TextureSamplerType>())
{
emitTextureSamplerType(context, textureSamplerType);
- Emit(context, " ");
EmitDeclarator(context, declarator);
return;
}
else if (auto imageType = type->As<GLSLImageType>())
{
emitImageType(context, imageType);
- Emit(context, " ");
EmitDeclarator(context, declarator);
return;
}
@@ -1314,19 +1348,56 @@ static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, EDeclara
throw "unimplemented";
}
-static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, String const& name)
+static void EmitType(
+ EmitContext* context,
+ RefPtr<ExpressionType> type,
+ CodePosition const& typeLoc,
+ String const& name,
+ CodePosition const& nameLoc)
{
+ advanceToSourceLocation(context, typeLoc);
+
EDeclarator nameDeclarator;
nameDeclarator.flavor = EDeclarator::Flavor::Name;
nameDeclarator.name = name;
+ nameDeclarator.loc = nameLoc;
EmitType(context, type, &nameDeclarator);
}
+
+static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, Token const& nameToken)
+{
+ EmitType(context, type, CodePosition(), nameToken.Content, nameToken.Position);
+}
+
+
+static void EmitType(EmitContext* context, RefPtr<ExpressionType> type, String const& name)
+{
+ EmitType(context, type, CodePosition(), name, CodePosition());
+}
+
static void EmitType(EmitContext* context, RefPtr<ExpressionType> type)
{
EmitType(context, type, nullptr);
}
+static void EmitType(EmitContext* context, TypeExp const& typeExp, Token const& nameToken)
+{
+ EmitType(context, typeExp.type, typeExp.exp->Position, nameToken.Content, nameToken.Position);
+}
+
+static void EmitType(EmitContext* context, TypeExp const& typeExp, String const& name)
+{
+ EmitType(context, typeExp.type, typeExp.exp->Position, name, CodePosition());
+}
+
+static void EmitType(EmitContext* context, TypeExp const& typeExp)
+{
+ advanceToSourceLocation(context, typeExp.exp->Position);
+ EmitType(context, typeExp.type, nullptr);
+}
+
+
// Statements
// Emit a statement as a `{}`-enclosed block statement, but avoid adding redundant
@@ -1424,6 +1495,9 @@ static void emitLineDirective(
emitRawText(context, charBuffer);
break;
+ // The incoming file path might use `/` and/or `\\` as
+ // a directory separator. We want to canonicalize this.
+ //
// TODO: should probably canonicalize paths to not use backslash somewhere else
// in the compilation pipeline...
case '\\':
@@ -1451,10 +1525,14 @@ static void emitLineDirectiveAndUpdateSourceLocation(
context->loc.Col = 1;
}
-static void advanceToSourceLocation(
+static void emitLineDirectiveIfNeeded(
EmitContext* context,
CodePosition const& sourceLocation)
{
+ // Ignore invalid source locations
+ if(sourceLocation.Line <= 0)
+ return;
+
// If we are currently emitting code at a source location with
// a differnet file or line, *or* if the source location is
// somehow later on the line than what we want to emit,
@@ -1463,7 +1541,26 @@ static void advanceToSourceLocation(
|| sourceLocation.Line != context->loc.Line
|| sourceLocation.Col < context->loc.Col)
{
- emitLineDirectiveAndUpdateSourceLocation(context, sourceLocation);
+ // Special case: if we are in the same file, and within a small number
+ // of lines of the target location, then go ahead and output newlines
+ // to get us caught up.
+ enum { kSmallLineCount = 3 };
+ auto lineDiff = sourceLocation.Line - context->loc.Line;
+ if(sourceLocation.FileName == context->loc.FileName
+ && sourceLocation.Line > context->loc.Line
+ && lineDiff <= kSmallLineCount)
+ {
+ for(int ii = 0; ii < lineDiff; ++ii )
+ {
+ Emit(context, "\n");
+ }
+ assert(sourceLocation.Line == context->loc.Line);
+ }
+ else
+ {
+ // Go ahead and output a `#line` directive to get us caught up
+ emitLineDirectiveAndUpdateSourceLocation(context, sourceLocation);
+ }
}
// Now indent up to the appropriate column, so that error messages
@@ -1484,6 +1581,32 @@ static void advanceToSourceLocation(
}
}
+static void advanceToSourceLocation(
+ EmitContext* context,
+ CodePosition const& sourceLocation)
+{
+ // Skip invalid locations
+ if(sourceLocation.Line <= 0)
+ return;
+
+ context->needToUpdateSourceLocation = true;
+ context->nextSourceLocation = sourceLocation;
+}
+
+static void flushSourceLocationChange(
+ EmitContext* context)
+{
+ if(!context->needToUpdateSourceLocation)
+ return;
+
+ // Note: the order matters here, because trying to update
+ // the source location may involve outputting text that
+ // advances the location, and outputting text is what
+ // triggers this flush operation.
+ context->needToUpdateSourceLocation = false;
+ emitLineDirectiveIfNeeded(context, context->nextSourceLocation);
+}
+
static void emitTokenWithLocation(EmitContext* context, Token const& token)
{
if( token.Position.FileName.Length() != 0 )
@@ -1520,6 +1643,9 @@ static void EmitUnparsedStmt(EmitContext* context, RefPtr<UnparsedStmt> stmt)
static void EmitStmt(EmitContext* context, RefPtr<StatementSyntaxNode> stmt)
{
+ // Try to ensure that debugging can find the right location
+ advanceToSourceLocation(context, stmt->Position);
+
if (auto blockStmt = stmt.As<BlockStatementSyntaxNode>())
{
EmitBlockStmt(context, blockStmt);
@@ -1681,7 +1807,7 @@ static void EmitDeclRef(EmitContext* context, DeclRef<Decl> declRef)
if (aa != 0) Emit(context, ",");
EmitVal(context, subst->args[aa]);
}
- Emit(context, ">");
+ Emit(context, " >");
}
}
@@ -1719,6 +1845,8 @@ static void EmitModifiers(EmitContext* context, RefPtr<Decl> decl)
for (auto mod = decl->modifiers.first; mod; mod = mod->next)
{
+ advanceToSourceLocation(context, mod->Position);
+
if (0) {}
#define CASE(TYPE, KEYWORD) \
@@ -1909,7 +2037,7 @@ static void EmitStructDecl(EmitContext* context, RefPtr<StructSyntaxNode> decl)
return;
Emit(context, "struct ");
- emitName(context, decl->Name.Content);
+ emitName(context, decl->Name);
Emit(context, "\n{\n");
// TODO(tfoley): Need to hoist members functions, etc. out to global scope
@@ -1923,7 +2051,7 @@ static void EmitVarDeclCommon(EmitContext* context, DeclRef<VarDeclBase> declRef
{
EmitModifiers(context, declRef.getDecl());
- EmitType(context, GetType(declRef), declRef.GetName());
+ EmitType(context, GetType(declRef), declRef.getDecl()->getNameToken());
EmitSemantics(context, declRef.getDecl());
@@ -2073,7 +2201,7 @@ static void emitHLSLParameterBlockDecl(
if( auto reflectionNameModifier = varDecl->FindModifier<ParameterBlockReflectionName>() )
{
Emit(context, " ");
- emitName(context, reflectionNameModifier->nameToken.Content);
+ emitName(context, reflectionNameModifier->nameToken);
}
EmitSemantics(context, varDecl, kESemanticMask_None);
@@ -2243,7 +2371,7 @@ static void emitGLSLParameterBlockDecl(
if( auto reflectionNameModifier = varDecl->FindModifier<ParameterBlockReflectionName>() )
{
Emit(context, " ");
- emitName(context, reflectionNameModifier->nameToken.Content);
+ emitName(context, reflectionNameModifier->nameToken);
}
Emit(context, "\n{\n");
@@ -2269,7 +2397,7 @@ static void emitGLSLParameterBlockDecl(
if( varDecl->Name.Type != TokenType::Unknown )
{
Emit(context, " ");
- emitName(context, varDecl->Name.Content);
+ emitName(context, varDecl->Name);
}
Emit(context, ";\n");
@@ -2338,7 +2466,7 @@ static void EmitFuncDecl(EmitContext* context, RefPtr<FunctionSyntaxNode> decl)
// isn't allowed by declarator syntax and/or language rules, we could
// hypothetically wrap things in a `typedef` and work around it.
- EmitType(context, decl->ReturnType, decl->Name.Content);
+ EmitType(context, decl->ReturnType, decl->Name);
Emit(context, "(");
bool first = true;
@@ -2495,6 +2623,10 @@ static void EmitDeclImpl(EmitContext* context, RefPtr<Decl> decl, RefPtr<VarLayo
if (decl->HasModifier<FromStdLibModifier>())
return;
+
+ // Try to ensure that debugging can find the right location
+ advanceToSourceLocation(context, decl->Position);
+
if (auto typeDefDecl = decl.As<TypeDefDecl>())
{
EmitTypeDefDecl(context, typeDefDecl);