summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-10-10 13:56:25 -0400
committerGitHub <noreply@github.com>2018-10-10 13:56:25 -0400
commit879ec1b385d290a4375682ec613a9e7a1967fc7d (patch)
tree0d5f32d83d45458db54cce281c0c6331a677cdff
parent60a91d63afab47a172690974c8b566af74072932 (diff)
Feature/source loc refactor (#668)
* * Remove the need for IRHighLevelDecoration in Emit * Use the IRLayoutDecoration for GeometryShaderPrimitiveTypeModifier * Initial look at at variable byte encoding, and simple unit test. * Fixing problems with comparison due to naming differences with slang/fxc. * * More tests and perf improvements for byte encoding. * Mechanism to detect processor and processor features in main slang header. * Split out cpu based defines into slang-cpu-defines.h so do not polute slang.h * Support for variable byte encoding on serialization. * Removed unused flag. * Fix warning. * Fix calcMsByte32 for 0 values without using intrinsic. * Fix a mistake in calculating maximum instruction size. * Introduced the idea of SourceUnit. * Small improvements around naming. Add more functionality - including getting the HumaneLoc. * Add support for #line default * Compiling with new SourceLoc handling. * Fix off by one on #line directives. * Can use 32bits for SourceLoc. Fix serialize to use that. * Small fixes and comment on usage. * Premake run. * Fix signed warning. * Fix typo on StringSlicePool::has found in review.
-rw-r--r--slang.sln164
-rw-r--r--source/core/core.vcxproj5
-rw-r--r--source/core/core.vcxproj.filters27
-rw-r--r--source/core/slang-string-slice-pool.cpp43
-rw-r--r--source/core/slang-string-slice-pool.h50
-rw-r--r--source/slang/diagnostics.cpp3
-rw-r--r--source/slang/ir-serialize.cpp21
-rw-r--r--source/slang/ir-serialize.h2
-rw-r--r--source/slang/lexer.cpp30
-rw-r--r--source/slang/lexer.h19
-rw-r--r--source/slang/preprocessor.cpp74
-rw-r--r--source/slang/slang.cpp21
-rw-r--r--source/slang/slang.vcxproj10
-rw-r--r--source/slang/slang.vcxproj.filters24
-rw-r--r--source/slang/source-loc.cpp530
-rw-r--r--source/slang/source-loc.h185
-rw-r--r--tools/slang-test/slang-test.vcxproj2
-rw-r--r--tools/slang-test/slang-test.vcxproj.filters8
18 files changed, 728 insertions, 490 deletions
diff --git a/slang.sln b/slang.sln
index 8adbb3822..fcce05cf9 100644
--- a/slang.sln
+++ b/slang.sln
@@ -1,36 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "source\core\core.vcxproj", "{F9BE7957-8399-899E-0C49-E714FDDD4B65}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello-world", "examples\hello-world\hello-world.vcxproj", "{5CF41E7B-4883-A844-F1A1-BC3FDD0FB9EA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "model-viewer", "examples\model-viewer\model-viewer.vcxproj", "{639B13F2-CF07-CFEC-98FB-664A0427F154}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "source\core\core.vcxproj", "{F9BE7957-8399-899E-0C49-E714FDDD4B65}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{FD47AE19-69FD-260F-F2F1-20E65EA61D13}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang", "source\slang\slang.vcxproj", "{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}"
+ ProjectSection(ProjectDependencies) = postProject
+ {66174227-8541-41FC-A6DF-4764FC66F78E} = {66174227-8541-41FC-A6DF-4764FC66F78E}
+ EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-generate", "tools\slang-generate\slang-generate.vcxproj", "{66174227-8541-41FC-A6DF-4764FC66F78E}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-glslang", "source\slang-glslang\slang-glslang.vcxproj", "{C495878A-832C-485B-B347-0998A90CC936}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-test", "tools\slang-test\slang-test.vcxproj", "{0C768A18-1D25-4000-9F37-DA5FE99E3B64}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slangc", "source\slangc\slangc.vcxproj", "{D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-reflection-test", "tools\slang-reflection-test\slang-reflection-test.vcxproj", "{22C45F4F-FB6B-4535-BED1-D3F5D0C71047}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{FD47AE19-69FD-260F-F2F1-20E65EA61D13}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-eval-test", "tools\slang-eval-test\slang-eval-test.vcxproj", "{205FCAB9-A13F-4980-86FA-F6221A7095EE}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gfx", "tools\gfx\gfx.vcxproj", "{222F7498-B40C-4F3F-A704-DDEB91A4484A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "render-test", "tools\render-test\render-test.vcxproj", "{96610759-07B9-4EEB-A974-5C634A2E742B}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gfx", "tools\gfx\gfx.vcxproj", "{222F7498-B40C-4F3F-A704-DDEB91A4484A}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-eval-test", "tools\slang-eval-test\slang-eval-test.vcxproj", "{205FCAB9-A13F-4980-86FA-F6221A7095EE}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slangc", "source\slangc\slangc.vcxproj", "{D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-generate", "tools\slang-generate\slang-generate.vcxproj", "{66174227-8541-41FC-A6DF-4764FC66F78E}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang", "source\slang\slang.vcxproj", "{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}"
- ProjectSection(ProjectDependencies) = postProject
- {66174227-8541-41FC-A6DF-4764FC66F78E} = {66174227-8541-41FC-A6DF-4764FC66F78E}
- EndProjectSection
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-reflection-test", "tools\slang-reflection-test\slang-reflection-test.vcxproj", "{22C45F4F-FB6B-4535-BED1-D3F5D0C71047}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-glslang", "source\slang-glslang\slang-glslang.vcxproj", "{C495878A-832C-485B-B347-0998A90CC936}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-test", "tools\slang-test\slang-test.vcxproj", "{0C768A18-1D25-4000-9F37-DA5FE99E3B64}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -40,6 +40,14 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|Win32.Build.0 = Debug|Win32
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|x64.ActiveCfg = Debug|x64
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|x64.Build.0 = Debug|x64
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|Win32.ActiveCfg = Release|Win32
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|Win32.Build.0 = Release|Win32
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|x64.ActiveCfg = Release|x64
+ {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|x64.Build.0 = Release|x64
{5CF41E7B-4883-A844-F1A1-BC3FDD0FB9EA}.Debug|Win32.ActiveCfg = Debug|Win32
{5CF41E7B-4883-A844-F1A1-BC3FDD0FB9EA}.Debug|Win32.Build.0 = Debug|Win32
{5CF41E7B-4883-A844-F1A1-BC3FDD0FB9EA}.Debug|x64.ActiveCfg = Debug|x64
@@ -56,70 +64,6 @@ Global
{639B13F2-CF07-CFEC-98FB-664A0427F154}.Release|Win32.Build.0 = Release|Win32
{639B13F2-CF07-CFEC-98FB-664A0427F154}.Release|x64.ActiveCfg = Release|x64
{639B13F2-CF07-CFEC-98FB-664A0427F154}.Release|x64.Build.0 = Release|x64
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|Win32.ActiveCfg = Debug|Win32
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|Win32.Build.0 = Debug|Win32
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|x64.ActiveCfg = Debug|x64
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Debug|x64.Build.0 = Debug|x64
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|Win32.ActiveCfg = Release|Win32
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|Win32.Build.0 = Release|Win32
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|x64.ActiveCfg = Release|x64
- {F9BE7957-8399-899E-0C49-E714FDDD4B65}.Release|x64.Build.0 = Release|x64
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|Win32.ActiveCfg = Debug|Win32
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|Win32.Build.0 = Debug|Win32
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|x64.ActiveCfg = Debug|x64
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|x64.Build.0 = Debug|x64
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|Win32.ActiveCfg = Release|Win32
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|Win32.Build.0 = Release|Win32
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|x64.ActiveCfg = Release|x64
- {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|x64.Build.0 = Release|x64
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|Win32.ActiveCfg = Debug|Win32
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|Win32.Build.0 = Debug|Win32
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|x64.ActiveCfg = Debug|x64
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|x64.Build.0 = Debug|x64
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|Win32.ActiveCfg = Release|Win32
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|Win32.Build.0 = Release|Win32
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|x64.ActiveCfg = Release|x64
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|x64.Build.0 = Release|x64
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|Win32.ActiveCfg = Debug|Win32
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|Win32.Build.0 = Debug|Win32
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|x64.ActiveCfg = Debug|x64
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|x64.Build.0 = Debug|x64
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|Win32.ActiveCfg = Release|Win32
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|Win32.Build.0 = Release|Win32
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|x64.ActiveCfg = Release|x64
- {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|x64.Build.0 = Release|x64
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|Win32.ActiveCfg = Debug|Win32
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|Win32.Build.0 = Debug|Win32
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|x64.ActiveCfg = Debug|x64
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|x64.Build.0 = Debug|x64
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|Win32.ActiveCfg = Release|Win32
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|Win32.Build.0 = Release|Win32
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|x64.ActiveCfg = Release|x64
- {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|x64.Build.0 = Release|x64
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|Win32.ActiveCfg = Debug|Win32
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|Win32.Build.0 = Debug|Win32
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|x64.ActiveCfg = Debug|x64
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|x64.Build.0 = Debug|x64
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|Win32.ActiveCfg = Release|Win32
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|Win32.Build.0 = Release|Win32
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|x64.ActiveCfg = Release|x64
- {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|x64.Build.0 = Release|x64
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|Win32.ActiveCfg = Debug|Win32
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|Win32.Build.0 = Debug|Win32
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|x64.ActiveCfg = Debug|x64
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|x64.Build.0 = Debug|x64
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|Win32.ActiveCfg = Release|Win32
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|Win32.Build.0 = Release|Win32
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|x64.ActiveCfg = Release|x64
- {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|x64.Build.0 = Release|x64
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|Win32.ActiveCfg = Debug|Win32
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|Win32.Build.0 = Debug|Win32
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|x64.ActiveCfg = Debug|x64
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|x64.Build.0 = Debug|x64
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|Win32.ActiveCfg = Release|Win32
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|Win32.Build.0 = Release|Win32
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|x64.ActiveCfg = Release|x64
- {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|x64.Build.0 = Release|x64
{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}.Debug|Win32.ActiveCfg = Debug|Win32
{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}.Debug|Win32.Build.0 = Debug|Win32
{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}.Debug|x64.ActiveCfg = Debug|x64
@@ -136,6 +80,62 @@ Global
{C495878A-832C-485B-B347-0998A90CC936}.Release|Win32.Build.0 = Release|Win32
{C495878A-832C-485B-B347-0998A90CC936}.Release|x64.ActiveCfg = Release|x64
{C495878A-832C-485B-B347-0998A90CC936}.Release|x64.Build.0 = Release|x64
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|Win32.Build.0 = Debug|Win32
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|x64.ActiveCfg = Debug|x64
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Debug|x64.Build.0 = Debug|x64
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|Win32.ActiveCfg = Release|Win32
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|Win32.Build.0 = Release|Win32
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|x64.ActiveCfg = Release|x64
+ {D56CBCEB-1EB5-4CA8-AEC4-48EA35ED61C7}.Release|x64.Build.0 = Release|x64
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|Win32.Build.0 = Debug|Win32
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|x64.ActiveCfg = Debug|x64
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Debug|x64.Build.0 = Debug|x64
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|Win32.ActiveCfg = Release|Win32
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|Win32.Build.0 = Release|Win32
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|x64.ActiveCfg = Release|x64
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A}.Release|x64.Build.0 = Release|x64
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|Win32.Build.0 = Debug|Win32
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|x64.ActiveCfg = Debug|x64
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Debug|x64.Build.0 = Debug|x64
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|Win32.ActiveCfg = Release|Win32
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|Win32.Build.0 = Release|Win32
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|x64.ActiveCfg = Release|x64
+ {96610759-07B9-4EEB-A974-5C634A2E742B}.Release|x64.Build.0 = Release|x64
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|Win32.Build.0 = Debug|Win32
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|x64.ActiveCfg = Debug|x64
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Debug|x64.Build.0 = Debug|x64
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|Win32.ActiveCfg = Release|Win32
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|Win32.Build.0 = Release|Win32
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|x64.ActiveCfg = Release|x64
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE}.Release|x64.Build.0 = Release|x64
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|Win32.Build.0 = Debug|Win32
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|x64.ActiveCfg = Debug|x64
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Debug|x64.Build.0 = Debug|x64
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|Win32.ActiveCfg = Release|Win32
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|Win32.Build.0 = Release|Win32
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|x64.ActiveCfg = Release|x64
+ {66174227-8541-41FC-A6DF-4764FC66F78E}.Release|x64.Build.0 = Release|x64
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|Win32.ActiveCfg = Debug|Win32
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|Win32.Build.0 = Debug|Win32
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|x64.ActiveCfg = Debug|x64
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Debug|x64.Build.0 = Debug|x64
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|Win32.ActiveCfg = Release|Win32
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|Win32.Build.0 = Release|Win32
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|x64.ActiveCfg = Release|x64
+ {22C45F4F-FB6B-4535-BED1-D3F5D0C71047}.Release|x64.Build.0 = Release|x64
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|Win32.Build.0 = Debug|Win32
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|x64.ActiveCfg = Debug|x64
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Debug|x64.Build.0 = Debug|x64
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|Win32.ActiveCfg = Release|Win32
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|Win32.Build.0 = Release|Win32
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|x64.ActiveCfg = Release|x64
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -143,11 +143,11 @@ Global
GlobalSection(NestedProjects) = preSolution
{5CF41E7B-4883-A844-F1A1-BC3FDD0FB9EA} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{639B13F2-CF07-CFEC-98FB-664A0427F154} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
+ {222F7498-B40C-4F3F-A704-DDEB91A4484A} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
+ {96610759-07B9-4EEB-A974-5C634A2E742B} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
+ {205FCAB9-A13F-4980-86FA-F6221A7095EE} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
{66174227-8541-41FC-A6DF-4764FC66F78E} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
- {0C768A18-1D25-4000-9F37-DA5FE99E3B64} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
{22C45F4F-FB6B-4535-BED1-D3F5D0C71047} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
- {205FCAB9-A13F-4980-86FA-F6221A7095EE} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
- {96610759-07B9-4EEB-A974-5C634A2E742B} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
- {222F7498-B40C-4F3F-A704-DDEB91A4484A} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
+ {0C768A18-1D25-4000-9F37-DA5FE99E3B64} = {FD47AE19-69FD-260F-F2F1-20E65EA61D13}
EndGlobalSection
EndGlobal
diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj
index ec6195940..d1ed4715f 100644
--- a/source/core/core.vcxproj
+++ b/source/core/core.vcxproj
@@ -183,11 +183,13 @@
<ClInclude Include="platform.h" />
<ClInclude Include="secure-crt.h" />
<ClInclude Include="slang-byte-encode-util.h" />
+ <ClInclude Include="slang-cpu-defines.h" />
<ClInclude Include="slang-free-list.h" />
<ClInclude Include="slang-io.h" />
<ClInclude Include="slang-math.h" />
<ClInclude Include="slang-memory-arena.h" />
<ClInclude Include="slang-random-generator.h" />
+ <ClInclude Include="slang-string-slice-pool.h" />
<ClInclude Include="slang-string-util.h" />
<ClInclude Include="slang-string.h" />
<ClInclude Include="smart-pointer.h" />
@@ -203,6 +205,7 @@
<ClCompile Include="slang-io.cpp" />
<ClCompile Include="slang-memory-arena.cpp" />
<ClCompile Include="slang-random-generator.cpp" />
+ <ClCompile Include="slang-string-slice-pool.cpp" />
<ClCompile Include="slang-string-util.cpp" />
<ClCompile Include="slang-string.cpp" />
<ClCompile Include="stream.cpp" />
@@ -210,7 +213,7 @@
<ClCompile Include="token-reader.cpp" />
</ItemGroup>
<ItemGroup>
- <None Include="core.natvis" />
+ <Natvis Include="core.natvis" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters
index f9eeef43a..7936ca11b 100644
--- a/source/core/core.vcxproj.filters
+++ b/source/core/core.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
@@ -45,6 +45,12 @@
<ClInclude Include="secure-crt.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-byte-encode-util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="slang-cpu-defines.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-free-list.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -60,6 +66,9 @@
<ClInclude Include="slang-random-generator.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-string-slice-pool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-string-util.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -81,14 +90,14 @@
<ClInclude Include="type-traits.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-byte-encode-util.h">
- <Filter>Header Files</Filter>
- </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="platform.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-byte-encode-util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-free-list.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -101,6 +110,9 @@
<ClCompile Include="slang-random-generator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-string-slice-pool.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-string-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -116,13 +128,10 @@
<ClCompile Include="token-reader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="slang-byte-encode-util.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
- <None Include="core.natvis">
+ <Natvis Include="core.natvis">
<Filter>Source Files</Filter>
- </None>
+ </Natvis>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/source/core/slang-string-slice-pool.cpp b/source/core/slang-string-slice-pool.cpp
new file mode 100644
index 000000000..88963d68f
--- /dev/null
+++ b/source/core/slang-string-slice-pool.cpp
@@ -0,0 +1,43 @@
+#include "slang-string-slice-pool.h"
+
+namespace Slang {
+
+StringSlicePool::StringSlicePool() :
+ m_arena(1024)
+{
+ clear();
+}
+
+void StringSlicePool::clear()
+{
+ m_slices.SetSize(1);
+ m_slices[0] = UnownedStringSlice::fromLiteral("");
+
+ m_map.Clear();
+}
+
+StringSlicePool::Handle StringSlicePool::add(const Slice& slice)
+{
+ const int* indexPtr = m_map.TryGetValue(slice);
+ if (indexPtr)
+ {
+ return Handle(*indexPtr);
+ }
+
+ // Create a scoped copy
+ UnownedStringSlice scopePath(m_arena.allocateString(slice.begin(), slice.size()), slice.size());
+
+ const int index = int(m_slices.Count());
+
+ m_slices.Add(scopePath);
+ m_map.Add(scopePath, index);
+ return Handle(index);
+}
+
+int StringSlicePool::findIndex(const Slice& slice) const
+{
+ const int* index = m_map.TryGetValue(slice);
+ return index ? *index : -1;
+
+}
+} // namespace Slang
diff --git a/source/core/slang-string-slice-pool.h b/source/core/slang-string-slice-pool.h
new file mode 100644
index 000000000..e6846b3dd
--- /dev/null
+++ b/source/core/slang-string-slice-pool.h
@@ -0,0 +1,50 @@
+#ifndef SLANG_STRING_SLICE_POOL_H
+#define SLANG_STRING_SLICE_POOL_H
+
+#include "slang-string.h"
+
+#include "list.h"
+#include "slang-memory-arena.h"
+#include "dictionary.h"
+
+namespace Slang {
+
+class StringSlicePool
+{
+public:
+ /// Handle of 0 is null. If accessed will be returned as the empty string
+ enum class Handle : uint32_t;
+ typedef UnownedStringSlice Slice;
+
+ /// Returns the index of a slice, if contained, or -1 if not found
+ int findIndex(const Slice& slice) const;
+
+ /// True if has the slice
+ bool has(const Slice& slice) { return findIndex(slice) >= 0; }
+ /// Add a slice
+ Handle add(const Slice& slice);
+
+ /// Empty contents
+ void clear();
+
+ /// Get the slice from the handle
+ const UnownedStringSlice& getSlice(Handle handle) const { return m_slices[UInt(handle)]; }
+
+ /// Get all the slices
+ const List<UnownedStringSlice>& getSlices() const { return m_slices; }
+
+ /// Convert a handle to and index. (A handle is just an index!)
+ static int asIndex(Handle handle) { return int(handle); }
+
+ /// Ctor
+ StringSlicePool();
+
+protected:
+ List<UnownedStringSlice> m_slices;
+ Dictionary<UnownedStringSlice, int> m_map;
+ MemoryArena m_arena;
+};
+
+} // namespace Slang
+
+#endif // SLANG_STRING_SLICE_POOL_H
diff --git a/source/slang/diagnostics.cpp b/source/slang/diagnostics.cpp
index 77473b95f..24019e4aa 100644
--- a/source/slang/diagnostics.cpp
+++ b/source/slang/diagnostics.cpp
@@ -169,8 +169,7 @@ static void formatDiagnostic(
{
auto sourceManager = sink->sourceManager;
- auto expandedLoc = sourceManager->expandSourceLoc(diagnostic.loc);
- auto humaneLoc = getHumaneLoc(expandedLoc);
+ auto humaneLoc = sourceManager->getHumaneLoc(diagnostic.loc);
sb << humaneLoc.getPath();
sb << "(";
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp
index c02ef7ee5..d82641168 100644
--- a/source/slang/ir-serialize.cpp
+++ b/source/slang/ir-serialize.cpp
@@ -976,11 +976,8 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
SLANG_RETURN_ON_FAIL(_writeArrayChunk(compressionType, Bin::kExternalOperandsFourCc, data.m_externalOperands, stream));
SLANG_RETURN_ON_FAIL(_writeArrayChunk(Bin::CompressionType::None, Bin::kStringFourCc, data.m_strings, stream));
- {
- uint32_t fourCc = sizeof(IRSerialData::RawSourceLoc) == 4 ? Bin::kUInt32SourceLocFourCc : Bin::kUInt64SourceLocFourCc;
- SLANG_RETURN_ON_FAIL(_writeArrayChunk(Bin::CompressionType::None, fourCc, data.m_rawSourceLocs, stream));
- }
-
+ SLANG_RETURN_ON_FAIL(_writeArrayChunk(Bin::CompressionType::None, Bin::kUInt32SourceLocFourCc, data.m_rawSourceLocs, stream));
+
return SLANG_OK;
}
@@ -1337,18 +1334,10 @@ int64_t _calcChunkTotalSize(const IRSerialBinary::Chunk& chunk)
break;
}
case Bin::kUInt32SourceLocFourCc:
- case Bin::kUInt64SourceLocFourCc:
{
- if ((sizeof(IRSerialData::RawSourceLoc) == 4 && chunk.m_type == Bin::kUInt32SourceLocFourCc) ||
- (sizeof(IRSerialData::RawSourceLoc) == 8 && chunk.m_type == Bin::kUInt64SourceLocFourCc))
- {
- SLANG_RETURN_ON_FAIL(_readArrayUncompressedChunk(slangHeader, chunk, stream, &bytesRead, dataOut->m_rawSourceLocs));
- remainingBytes -= _calcChunkTotalSize(chunk);
- }
- else
- {
- SLANG_RETURN_ON_FAIL(_skip(chunk, stream, &remainingBytes));
- }
+
+ SLANG_RETURN_ON_FAIL(_readArrayUncompressedChunk(slangHeader, chunk, stream, &bytesRead, dataOut->m_rawSourceLocs));
+ remainingBytes -= _calcChunkTotalSize(chunk);
break;
}
default:
diff --git a/source/slang/ir-serialize.h b/source/slang/ir-serialize.h
index 28f90303e..0146765a0 100644
--- a/source/slang/ir-serialize.h
+++ b/source/slang/ir-serialize.h
@@ -256,8 +256,6 @@ struct IRSerialBinary
static const uint32_t kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');
/// 4 bytes per entry
static const uint32_t kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4');
- /// 8 bytes per entry
- static const uint32_t kUInt64SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '8');
struct SlangHeader
{
diff --git a/source/slang/lexer.cpp b/source/slang/lexer.cpp
index 9ea86cc82..339d98d49 100644
--- a/source/slang/lexer.cpp
+++ b/source/slang/lexer.cpp
@@ -84,22 +84,22 @@ namespace Slang
// Lexer
void Lexer::initialize(
- SourceFile* inSourceFile,
+ SourceUnit* inSourceUnit,
DiagnosticSink* inSink,
NamePool* inNamePool)
{
- sourceFile = inSourceFile;
+ sourceUnit = inSourceUnit;
sink = inSink;
namePool = inNamePool;
- auto content = inSourceFile->content;
+ auto content = inSourceUnit->getSourceFile()->content;
begin = content.begin();
cursor = content.begin();
end = content.end();
- spellingStartLoc = inSourceFile->sourceRange.begin;
- presumedStartLoc = spellingStartLoc;
+ // Set the start location
+ startLoc = inSourceUnit->getRange().begin;
tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace;
lexerFlags = 0;
@@ -227,7 +227,7 @@ namespace Slang
lexer->tokenFlags |= TokenFlag::ScrubbingNeeded;
// Now try again, looking at the character after the
- // escaped nmewline.
+ // escaped newline.
continue;
default:
@@ -333,23 +333,7 @@ namespace Slang
static SourceLoc getSourceLoc(Lexer* lexer)
{
- return lexer->presumedStartLoc + (lexer->cursor - lexer->begin);
- }
-
- // Begin overriding the reported locations of tokens,
- // based on a `#line` directives
- void Lexer::startOverridingSourceLocations(
- SourceLoc loc)
- {
- if(loc.isValid())
- {
- presumedStartLoc = loc;
- }
- }
-
- void Lexer::stopOverridingSourceLocations()
- {
- presumedStartLoc = spellingStartLoc;
+ return lexer->startLoc + (lexer->cursor - lexer->begin);
}
static void lexDigits(Lexer* lexer, int base)
diff --git a/source/slang/lexer.h b/source/slang/lexer.h
index 1f2954d27..46d2aa227 100644
--- a/source/slang/lexer.h
+++ b/source/slang/lexer.h
@@ -73,7 +73,7 @@ namespace Slang
struct Lexer
{
void initialize(
- SourceFile* sourceFile,
+ SourceUnit* sourceUnit,
DiagnosticSink* sink,
NamePool* namePool);
@@ -83,15 +83,7 @@ namespace Slang
TokenList lexAllTokens();
- // Begin overriding the reported locations of tokens,
- // based on a `#line` directives
- void startOverridingSourceLocations(SourceLoc loc);
-
- // Stop overriding source locations, and go back
- // to reporting source locations in the original file
- void stopOverridingSourceLocations();
-
- SourceFile* sourceFile;
+ SourceUnit* sourceUnit;
DiagnosticSink* sink;
NamePool* namePool;
@@ -100,13 +92,16 @@ namespace Slang
char const* begin;
char const* end;
+ /// The starting sourceLoc (same as first location of SourceUnit)
+ SourceLoc startLoc;
+
// The starting source location for the code as written,
// which cannot be overridden.
- SourceLoc spellingStartLoc;
+ //SourceLoc spellingStartLoc;
// The nominal starting location for the file, taking
// any active `#line` directive into account.
- SourceLoc presumedStartLoc;
+ //SourceLoc presumedStartLoc;
TokenFlags tokenFlags;
LexerFlags lexerFlags;
diff --git a/source/slang/preprocessor.cpp b/source/slang/preprocessor.cpp
index d652d07bb..2986b275b 100644
--- a/source/slang/preprocessor.cpp
+++ b/source/slang/preprocessor.cpp
@@ -265,13 +265,13 @@ static NamePool* getNamePool(Preprocessor* preprocessor)
// TODO(tfoley): pre-tokenizing files isn't going to work in the long run.
static PreprocessorInputStream* CreateInputStreamForSource(
Preprocessor* preprocessor,
- SourceFile* sourceFile)
+ SourceUnit* sourceUnit)
{
PrimaryInputStream* inputStream = new PrimaryInputStream();
initializePrimaryInputStream(preprocessor, inputStream);
// initialize the embedded lexer so that it can generate a token stream
- inputStream->lexer.initialize(sourceFile, GetSink(preprocessor), getNamePool(preprocessor));
+ inputStream->lexer.initialize(sourceUnit, GetSink(preprocessor), getNamePool(preprocessor));
inputStream->token = inputStream->lexer.lexToken();
return inputStream;
@@ -835,11 +835,15 @@ top:
// Now re-lex the input
+ SourceManager* sourceManager = preprocessor->getCompileRequest()->getSourceManager();
+
// We create a dummy file to represent the token-paste operation
- SourceFile* sourceFile = preprocessor->getCompileRequest()->getSourceManager()->allocateSourceFile("token paste", sb.ProduceString());
+ SourceFile* sourceFile = sourceManager->newSourceFile("token paste", sb.ProduceString());
+
+ SourceUnit* sourceUnit = sourceManager->newSourceUnit(sourceFile);
Lexer lexer;
- lexer.initialize(sourceFile, GetSink(preprocessor), getNamePool(preprocessor));
+ lexer.initialize(sourceUnit, GetSink(preprocessor), getNamePool(preprocessor));
SimpleTokenInputStream* inputStream = new SimpleTokenInputStream();
initializeInputStream(preprocessor, inputStream);
@@ -1584,8 +1588,8 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
String path = getFileNameTokenValue(pathToken);
auto directiveLoc = GetDirectiveLoc(context);
- auto expandedDirectiveLoc = context->preprocessor->translationUnit->compileRequest->getSourceManager()->expandSourceLoc(directiveLoc);
- String pathIncludedFrom = expandedDirectiveLoc.getSpellingPath();
+
+ String pathIncludedFrom = context->preprocessor->translationUnit->compileRequest->getSourceManager()->getPath(directiveLoc, SourceLocType::Original);
String foundPath;
ComPtr<ISlangBlob> foundSourceBlob;
@@ -1622,10 +1626,21 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context)
// Push the new file onto our stack of input streams
// TODO(tfoley): check if we have made our include stack too deep
+ auto sourceManager = context->preprocessor->getCompileRequest()->getSourceManager();
+
+ // See if this an already loaded source file
+ SourceFile* sourceFile = sourceManager->findSourceFile(foundPath);
+ // If not create a new one, and add to the list of known source files
+ if (!sourceFile)
+ {
+ sourceFile = sourceManager->newSourceFile(foundPath, foundSourceBlob);
+ sourceManager->addSourceFile(foundPath, sourceFile);
+ }
- SourceFile* sourceFile = context->preprocessor->getCompileRequest()->getSourceManager()->allocateSourceFile(foundPath, foundSourceBlob);
+ // This is a new parse (even if it's a pre-existing source file), so create a new SourceUnit
+ SourceUnit* sourceUnit = sourceManager->newSourceUnit(sourceFile);
- PreprocessorInputStream* inputStream = CreateInputStreamForSource(context->preprocessor, sourceFile);
+ PreprocessorInputStream* inputStream = CreateInputStreamForSource(context->preprocessor, sourceUnit);
inputStream->parent = context->preprocessor->inputStream;
context->preprocessor->inputStream = inputStream;
}
@@ -1771,6 +1786,8 @@ static void HandleLineDirective(PreprocessorDirectiveContext* context)
int line = 0;
+ SourceLoc directiveLoc = GetDirectiveLoc(context);
+
// `#line <integer-literal> ...`
if (PeekTokenType(context) == TokenType::IntegerLiteral)
{
@@ -1785,8 +1802,9 @@ static void HandleLineDirective(PreprocessorDirectiveContext* context)
{
AdvanceToken(context);
- // Stop overiding soure locations.
- inputStream->primaryStream->lexer.stopOverridingSourceLocations();
+ // Stop overriding source locations.
+ auto sourceUnit = inputStream->primaryStream->lexer.sourceUnit;
+ sourceUnit->addDefaultLineDirective(directiveLoc);
return;
}
else
@@ -1799,15 +1817,12 @@ static void HandleLineDirective(PreprocessorDirectiveContext* context)
return;
}
- SourceLoc directiveLoc = GetDirectiveLoc(context);
-
auto sourceManager = context->preprocessor->translationUnit->compileRequest->getSourceManager();
- auto expandedDirectiveLoc = sourceManager->expandSourceLoc(directiveLoc);
-
+
String file;
if (PeekTokenType(context) == TokenType::EndOfDirective)
{
- file = expandedDirectiveLoc.getPath();
+ file = sourceManager->getPath(directiveLoc);
}
else if (PeekTokenType(context) == TokenType::StringLiteral)
{
@@ -1825,9 +1840,8 @@ static void HandleLineDirective(PreprocessorDirectiveContext* context)
return;
}
- SourceLoc newLoc = sourceManager->allocateSourceFileForLineDirective(expandedDirectiveLoc, file, line);
-
- inputStream->primaryStream->lexer.startOverridingSourceLocations(newLoc);
+ auto sourceUnit = inputStream->primaryStream->lexer.sourceUnit;
+ sourceUnit->addLineDirective(directiveLoc, file, line);
}
#define SLANG_PRAGMA_DIRECTIVE_CALLBACK(NAME) \
@@ -1861,8 +1875,7 @@ SLANG_PRAGMA_DIRECTIVE_CALLBACK(handlePragmaOnceDirective)
// trivial cases of the "same" path.
//
auto directiveLoc = GetDirectiveLoc(context);
- auto expandedDirectiveLoc = context->preprocessor->translationUnit->compileRequest->getSourceManager()->expandSourceLoc(directiveLoc);
- String pathIssuedFrom = expandedDirectiveLoc.getSpellingPath();
+ auto pathIssuedFrom = context->preprocessor->translationUnit->compileRequest->getSourceManager()->getPath(directiveLoc, SourceLocType::Original);
context->preprocessor->pragmaOncePaths.Add(pathIssuedFrom);
}
@@ -2233,19 +2246,24 @@ static void DefineMacro(
String fileName = "command line";
PreprocessorMacro* macro = CreateMacro(preprocessor);
- SourceFile* keyFile = preprocessor->translationUnit->compileRequest->getSourceManager()->allocateSourceFile(fileName, key);
- SourceFile* valueFile = preprocessor->translationUnit->compileRequest->getSourceManager()->allocateSourceFile(fileName, value);
+ auto sourceManager = preprocessor->translationUnit->compileRequest->getSourceManager();
+
+ SourceFile* keyFile = sourceManager->newSourceFile(fileName, key);
+ SourceFile* valueFile = sourceManager->newSourceFile(fileName, value);
+
+ SourceUnit* keyUnit = sourceManager->newSourceUnit(keyFile);
+ SourceUnit* valueUnit = sourceManager->newSourceUnit(valueFile);
// Use existing `Lexer` to generate a token stream.
Lexer lexer;
- lexer.initialize(valueFile, GetSink(preprocessor), getNamePool(preprocessor));
+ lexer.initialize(valueUnit, GetSink(preprocessor), getNamePool(preprocessor));
macro->tokens = lexer.lexAllTokens();
Name* keyName = preprocessor->translationUnit->compileRequest->getNamePool()->getName(key);
macro->nameAndLoc.name = keyName;
- macro->nameAndLoc.loc = keyFile->sourceRange.begin;
-
+ macro->nameAndLoc.loc = keyUnit->getRange().begin;
+
PreprocessorMacro* oldMacro = NULL;
if (preprocessor->globalEnv.macros.TryGetValue(keyName, oldMacro))
{
@@ -2291,8 +2309,12 @@ TokenList preprocessSource(
DefineMacro(&preprocessor, p.Key, p.Value);
}
+ SourceManager* sourceManager = translationUnit->compileRequest->getSourceManager();
+
+ SourceUnit* sourceUnit = sourceManager->newSourceUnit(file);
+
// create an initial input stream based on the provided buffer
- preprocessor.inputStream = CreateInputStreamForSource(&preprocessor, file);
+ preprocessor.inputStream = CreateInputStreamForSource(&preprocessor, sourceUnit);
TokenList tokens = ReadAllTokens(&preprocessor);
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index e3b675cd7..eab9401b4 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -372,12 +372,12 @@ SlangResult CompileRequest::loadFile(String const& path, ISlangBlob** outBlob)
RefPtr<Expr> CompileRequest::parseTypeString(TranslationUnitRequest * translationUnit, String typeStr, RefPtr<Scope> scope)
{
- Slang::SourceFile srcFile;
- srcFile.content = UnownedStringSlice(typeStr.begin(), typeStr.end());
+ Slang::RefPtr<Slang::SourceFile> srcFile = sourceManager->newSourceFile(String("type string"), typeStr);
+
DiagnosticSink sink;
sink.sourceManager = sourceManager;
auto tokens = preprocessSource(
- &srcFile,
+ srcFile,
&sink,
nullptr,
Dictionary<String,String>(),
@@ -675,7 +675,7 @@ void CompileRequest::addTranslationUnitSourceBlob(
String const& path,
ISlangBlob* sourceBlob)
{
- RefPtr<SourceFile> sourceFile = getSourceManager()->allocateSourceFile(path, sourceBlob);
+ RefPtr<SourceFile> sourceFile = getSourceManager()->newSourceFile(path, sourceBlob);
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
@@ -685,7 +685,7 @@ void CompileRequest::addTranslationUnitSourceString(
String const& path,
String const& source)
{
- RefPtr<SourceFile> sourceFile = getSourceManager()->allocateSourceFile(path, source);
+ RefPtr<SourceFile> sourceFile = getSourceManager()->newSourceFile(path, source);
addTranslationUnitSourceFile(translationUnitIndex, sourceFile);
}
@@ -804,7 +804,7 @@ RefPtr<ModuleDecl> CompileRequest::loadModule(
// TODO: decide which options, if any, should be inherited.
translationUnit->compileFlags = 0;
- RefPtr<SourceFile> sourceFile = getSourceManager()->allocateSourceFile(path, sourceBlob);
+ RefPtr<SourceFile> sourceFile = getSourceManager()->newSourceFile(path, sourceBlob);
translationUnit->sourceFiles.Add(sourceFile);
@@ -883,10 +883,9 @@ RefPtr<ModuleDecl> CompileRequest::findOrImportModule(
IncludeHandlerImpl includeHandler;
includeHandler.request = this;
- auto expandedLoc = getSourceManager()->expandSourceLoc(loc);
-
- String pathIncludedFrom = expandedLoc.getSpellingPath();
-
+ // Get the original path
+ String pathIncludedFrom= getSourceManager()->getPath(loc, SourceLocType::Original);
+
String foundPath;
ComPtr<ISlangBlob> foundSourceBlob;
IncludeResult includeResult = includeHandler.TryToFindIncludeFile(fileName, pathIncludedFrom, &foundPath, foundSourceBlob.writeRef());
@@ -971,8 +970,6 @@ void Session::addBuiltinSource(
auto translationUnitIndex = compileRequest->addTranslationUnit(SourceLanguage::Slang, path);
- RefPtr<SourceFile> sourceFile = builtinSourceManager.allocateSourceFile(path, source);
-
compileRequest->addTranslationUnitSourceString(
translationUnitIndex,
path,
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index 441bbea51..ba8aabaf5 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -259,16 +259,13 @@
<ClCompile Include="vm.cpp" />
</ItemGroup>
<ItemGroup>
- <None Include="slang.natvis" />
- </ItemGroup>
- <ItemGroup>
<CustomBuild Include="core.meta.slang">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"../../bin/windows-x86/debug/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-generate" %(Identity)</Command>
- <Outputs>%(Identity).h</Outputs>
+ <Outputs>../../core.meta.slang.h</Outputs>
<Message>slang-generate %(Identity)</Message>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../bin/windows-x86/debug/slang-generate.exe</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../bin/windows-x64/debug/slang-generate.exe</AdditionalInputs>
@@ -281,7 +278,7 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-generate" %(Identity)</Command>
- <Outputs>%(Identity).h</Outputs>
+ <Outputs>../../hlsl.meta.slang.h</Outputs>
<Message>slang-generate %(Identity)</Message>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../bin/windows-x86/debug/slang-generate.exe</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../bin/windows-x64/debug/slang-generate.exe</AdditionalInputs>
@@ -290,6 +287,9 @@
</CustomBuild>
</ItemGroup>
<ItemGroup>
+ <Natvis Include="slang.natvis" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="..\core\core.vcxproj">
<Project>{F9BE7957-8399-899E-0C49-E714FDDD4B65}</Project>
</ProjectReference>
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index 4c47cd0f0..c45e7f0ee 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
@@ -60,6 +60,9 @@
<ClInclude Include="ir-restructure.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="ir-serialize.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="ir-ssa.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -156,9 +159,6 @@
<ClInclude Include="vm.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="ir-serialize.h">
- <Filter>Header Files</Filter>
- </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="bytecode.cpp">
@@ -194,6 +194,9 @@
<ClCompile Include="ir-restructure.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="ir-serialize.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="ir-ssa.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -263,14 +266,6 @@
<ClCompile Include="vm.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="ir-serialize.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <None Include="slang.natvis">
- <Filter>Source Files</Filter>
- </None>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="core.meta.slang">
@@ -280,4 +275,9 @@
<Filter>Source Files</Filter>
</CustomBuild>
</ItemGroup>
+ <ItemGroup>
+ <Natvis Include="slang.natvis">
+ <Filter>Source Files</Filter>
+ </Natvis>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/source/slang/source-loc.cpp b/source/slang/source-loc.cpp
index 3042c3bd4..eef7b1ecd 100644
--- a/source/slang/source-loc.cpp
+++ b/source/slang/source-loc.cpp
@@ -5,30 +5,261 @@
namespace Slang {
-String ExpandedSourceLoc::getPath() const
+/* !!!!!!!!!!!!!!!!!!!!!!!!! SourceUnit !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+int SourceUnit::findEntryIndex(SourceLoc sourceLoc) const
{
- if(!sourceManager)
- return String();
+ if (!m_range.contains(sourceLoc))
+ {
+ return -1;
+ }
+
+ const auto rawValue = sourceLoc.getRaw();
+
+ int hi = int(m_entries.Count());
+ // If there are no entries, or it is in front of the first entry, then there is no associated entry
+ if (hi == 0 ||
+ m_entries[0].m_startLoc.getRaw() > sourceLoc.getRaw())
+ {
+ return -1;
+ }
+
+ int lo = 0;
+ while (lo + 1 < hi)
+ {
+ int mid = (hi + lo) >> 1;
+
+ const Entry& midEntry = m_entries[mid];
+ SourceLoc::RawValue midValue = midEntry.m_startLoc.getRaw();
- return sourceManager->sourceFiles[entryIndex].path;
+ if (midValue <= rawValue)
+ {
+ // The location we seek is at or after this entry
+ lo = mid;
+ }
+ else
+ {
+ // The location we seek is before this entry
+ hi = mid;
+ }
+ }
+
+ return lo;
}
-String ExpandedSourceLoc::getSpellingPath() const
+void SourceUnit::addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line)
{
- if(!sourceManager)
- return String();
+ SLANG_ASSERT(pathHandle != StringSlicePool::Handle(0));
+ SLANG_ASSERT(m_range.contains(directiveLoc));
+
+ // Check that the directiveLoc values are always increasing
+ SLANG_ASSERT(m_entries.Count() == 0 || (m_entries.Last().m_startLoc.getRaw() < directiveLoc.getRaw()));
- return sourceManager->sourceFiles[entryIndex].sourceFile->path;
+ // Calculate the offset
+ const int offset = m_range.getOffset(directiveLoc);
+
+ // Get the line index in the original file
+ const int lineIndex = m_sourceFile->calcLineIndexFromOffset(offset);
+
+ Entry entry;
+ entry.m_startLoc = directiveLoc;
+ entry.m_pathHandle = pathHandle;
+
+ // We also need to make sure that any lookups for line numbers will
+ // get corrected based on this files location.
+ // We assume the line number coming in is a line number, NOT an index so the correction needs + 1
+ // There is an additional + 1 because we want the NEXT line to be 99 (ie +2 is correct 'fix')
+ entry.m_lineAdjust = line - (lineIndex + 2);
+
+ m_entries.Add(entry);
}
-SourceFile* ExpandedSourceLoc::getSourceFile() const
+void SourceUnit::addLineDirective(SourceLoc directiveLoc, const String& path, int line)
{
- if(!sourceManager)
- return nullptr;
+ StringSlicePool::Handle pathHandle = m_sourceManager->getStringSlicePool().add(path.getUnownedSlice());
+ return addLineDirective(directiveLoc, pathHandle, line);
+}
+
+void SourceUnit::addDefaultLineDirective(SourceLoc directiveLoc)
+{
+ SLANG_ASSERT(m_range.contains(directiveLoc));
+ // Check that the directiveLoc values are always increasing
+ SLANG_ASSERT(m_entries.Count() == 0 || (m_entries.Last().m_startLoc.getRaw() < directiveLoc.getRaw()));
- return sourceManager->sourceFiles[entryIndex].sourceFile;
+ // Well if there are no entries, or the last one puts it in default case, then we don't need to add anything
+ if (m_entries.Count() == 0 || (m_entries.Count() && m_entries.Last().isDefault()))
+ {
+ return;
+ }
+
+ Entry entry;
+ entry.m_startLoc = directiveLoc;
+ entry.m_lineAdjust = 0; // No line adjustment... we are going back to default
+ entry.m_pathHandle = StringSlicePool::Handle(0); // Mark that there is no path, and that this is a 'default'
+
+ SLANG_ASSERT(entry.isDefault());
+
+ m_entries.Add(entry);
}
+HumaneSourceLoc SourceUnit::getHumaneLoc(SourceLoc loc, SourceLocType type)
+{
+ const int offset = m_range.getOffset(loc);
+
+ // We need the line index from the original source file
+ const int lineIndex = m_sourceFile->calcLineIndexFromOffset(offset);
+
+ // TODO: we should really translate the byte index in the line
+ // to deal with:
+ //
+ // - Non-ASCII characters, while might consume multiple bytes
+ //
+ // - Tab characters, which should really adjust how we report
+ // columns (although how are we supposed to know the setting
+ // that an IDE expects us to use when reporting locations?)
+ const int columnIndex = m_sourceFile->calcColumnIndex(lineIndex, offset);
+
+ HumaneSourceLoc humaneLoc;
+ humaneLoc.column = columnIndex + 1;
+ humaneLoc.line = lineIndex + 1;
+
+ // Make up a default entry
+ StringSlicePool::Handle pathHandle = StringSlicePool::Handle(0);
+
+ // Only bother looking up the entry information if we want a 'Normal' lookup
+ const int entryIndex = (type == SourceLocType::Normal) ? findEntryIndex(loc) : -1;
+ if (entryIndex >= 0)
+ {
+ const Entry& entry = m_entries[entryIndex];
+ // Adjust the line
+ humaneLoc.line += entry.m_lineAdjust;
+ // Get the pathHandle..
+ pathHandle = entry.m_pathHandle;
+ }
+
+ // If there is no override path, then just the source files path
+ if (pathHandle == StringSlicePool::Handle(0))
+ {
+ humaneLoc.path = m_sourceFile->path;
+ }
+ else
+ {
+ humaneLoc.path = m_sourceManager->getStringSlicePool().getSlice(pathHandle);
+ }
+
+ return humaneLoc;
+}
+
+String SourceUnit::getPath(SourceLoc loc, SourceLocType type)
+{
+ if (type == SourceLocType::Original)
+ {
+ return m_sourceFile->path;
+ }
+
+ const int entryIndex = findEntryIndex(loc);
+ const StringSlicePool::Handle pathHandle = (entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0);
+
+ // If there is no override path, then just the source files path
+ if (pathHandle == StringSlicePool::Handle(0))
+ {
+ return m_sourceFile->path;
+ }
+ else
+ {
+ return m_sourceManager->getStringSlicePool().getSlice(pathHandle);
+ }
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!! SourceFile !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+const List<uint32_t>& SourceFile::getLineBreakOffsets()
+{
+ // We now have a raw input file that we can search for line breaks.
+ // We obviously don't want to do a linear scan over and over, so we will
+ // cache an array of line break locations in the file.
+ if (m_lineBreakOffsets.Count() == 0)
+ {
+ char const* begin = content.begin();
+ char const* end = content.end();
+
+ char const* cursor = begin;
+
+ // Treat the beginning of the file as a line break
+ m_lineBreakOffsets.Add(0);
+
+ while (cursor != end)
+ {
+ int c = *cursor++;
+ switch (c)
+ {
+ case '\r': case '\n':
+ {
+ // When we see a line-break character we need
+ // to record the line break, but we also need
+ // to deal with the annoying issue of encodings,
+ // where a multi-byte sequence might encode
+ // the line break.
+
+ int d = *cursor;
+ if ((c^d) == ('\r' ^ '\n'))
+ cursor++;
+
+ m_lineBreakOffsets.Add(uint32_t(cursor - begin));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Note that we do *not* treat the end of the file as a line
+ // break, because otherwise we would report errors like
+ // "end of file inside string literal" with a line number
+ // that points at a line that doesn't exist.
+ }
+
+ return m_lineBreakOffsets;
+}
+
+int SourceFile::calcLineIndexFromOffset(int offset)
+{
+ SLANG_ASSERT(UInt(offset) <= content.size());
+
+ // Make sure we have the line break offsets
+ const auto& lineBreakOffsets = getLineBreakOffsets();
+
+ // At this point we can assume the `lineBreakOffsets` array has been filled in.
+ // We will use a binary search to find the line index that contains our
+ // chosen offset.
+ int lo = 0;
+ int hi = int(lineBreakOffsets.Count());
+
+ while (lo + 1 < hi)
+ {
+ const int mid = (hi + lo) >> 1;
+ const uint32_t midOffset = lineBreakOffsets[mid];
+ if (midOffset <= uint32_t(offset))
+ {
+ lo = mid;
+ }
+ else
+ {
+ hi = mid;
+ }
+ }
+
+ return lo;
+}
+
+int SourceFile::calcColumnIndex(int lineIndex, int offset)
+{
+ const auto& lineBreakOffsets = getLineBreakOffsets();
+ return offset - lineBreakOffsets[lineIndex];
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!! SourceManager !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
void SourceManager::initialize(
SourceManager* p)
{
@@ -70,7 +301,7 @@ SourceRange SourceManager::allocateSourceRange(UInt size)
return SourceRange(beginLoc, endLoc);
}
-SourceFile* SourceManager::allocateSourceFile(
+SourceFile* SourceManager::newSourceFile(
String const& path,
ISlangBlob* contentBlob)
{
@@ -78,110 +309,56 @@ SourceFile* SourceManager::allocateSourceFile(
UInt contentSize = contentBlob->getBufferSize();
char const* contentEnd = contentBegin + contentSize;
- SourceRange sourceRange = allocateSourceRange(contentSize);
-
SourceFile* sourceFile = new SourceFile();
sourceFile->path = path;
sourceFile->contentBlob = contentBlob;
sourceFile->content = UnownedStringSlice(contentBegin, contentEnd);
- sourceFile->sourceRange = sourceRange;
-
- Entry entry;
- entry.sourceFile = sourceFile;
- entry.startLoc = sourceRange.begin;
- entry.path = path;
-
- sourceFiles.Add(entry);
-
+
return sourceFile;
}
-SourceFile* SourceManager::allocateSourceFile(
+SourceFile* SourceManager::newSourceFile(
String const& path,
String const& content)
{
ComPtr<ISlangBlob> contentBlob = createStringBlob(content);
- return allocateSourceFile(path, contentBlob);
+ return newSourceFile(path, contentBlob);
}
-SourceLoc SourceManager::allocateSourceFileForLineDirective(
- SourceLoc const& directiveLoc,
- String const& path,
- UInt line)
+SourceUnit* SourceManager::newSourceUnit(SourceFile* sourceFile)
{
- // First, we need to find out what file we are being asked to remap
- ExpandedSourceLoc expandedDirectiveLoc = expandSourceLoc(getSpellingLoc(directiveLoc));
- HumaneSourceLoc humaneDirectiveLoc = getHumaneLoc(expandedDirectiveLoc);
+ SourceRange range = allocateSourceRange(sourceFile->content.size());
+ SourceUnit* sourceUnit = new SourceUnit(this, sourceFile, range);
+ m_sourceUnits.Add(sourceUnit);
- SourceFile* sourceFile = expandedDirectiveLoc.getSourceFile();
- if(!sourceFile)
- return SourceLoc();
-
- // We are going to be wasteful here and allocate a range of source locations
- // that can cover the entire input file. This will lead to a problem with
- // memory usage if we ever had a large input file that used many `#line` directives,
- // since our usage of ranges would be quadratic!
-
- // Count how many locations we'd need to reserve for a complete clone of the input
- UInt size = sourceFile->sourceRange.end.getRaw() - sourceFile->sourceRange.begin.getRaw();
-
- // Allocate a fresh range for our logically remapped file
- SourceRange sourceRange = allocateSourceRange(size);
-
- // Now fill in an entry that will point at the original source file,
- // but use our new range.
- Entry entry;
- entry.sourceFile = sourceFile;
- entry.startLoc = sourceRange.begin;
- entry.path = path;
-
- // We also need to make sure that any lookups for line numbers will
- // get corrected based on this files location.
- entry.lineAdjust = Int(line) - Int(humaneDirectiveLoc.line + 1);
-
- sourceFiles.Add(entry);
-
- return entry.startLoc;
+ return sourceUnit;
}
-static ExpandedSourceLoc expandSourceLoc(
- SourceManager* inSourceManager,
- SourceLoc const& loc)
+SourceUnit* SourceManager::findSourceUnit(SourceLoc loc)
{
- SourceManager* sourceManager = inSourceManager;
-
- ExpandedSourceLoc expanded;
-
- SourceLoc::RawValue rawValue = loc.getRaw();
+ SourceLoc::RawValue rawLoc = loc.getRaw();
- // Invalid location? -> invalid expanded location
- if(rawValue == 0)
- return expanded;
+ int hi = int(m_sourceUnits.Count());
- // Past the end of what we can handle? -> invalid
- if(rawValue >= sourceManager->nextLoc.getRaw())
- return expanded;
-
- // Maybe the location came from a parent source manager
- while( rawValue < sourceManager->startLoc.getRaw()
- && sourceManager->parent)
+ if (hi == 0)
{
- sourceManager = sourceManager->parent;
+ return nullptr;
}
- SLANG_ASSERT(sourceManager->sourceFiles.Count() > 0);
-
- UInt lo = 0;
- UInt hi = sourceManager->sourceFiles.Count();
-
- while( lo+1 < hi )
+ int lo = 0;
+ while (lo + 1 < hi)
{
- UInt mid = lo + (hi - lo) / 2;
+ int mid = (hi + lo) >> 1;
+
+ SourceUnit* midEntry = m_sourceUnits[mid];
+ if (midEntry->getRange().contains(loc))
+ {
+ return midEntry;
+ }
- SourceManager::Entry const& midEntry = sourceManager->sourceFiles[mid];
- SourceLoc::RawValue midValue = midEntry.startLoc.getRaw();
+ SourceLoc::RawValue midValue = midEntry->getRange().begin.getRaw();
- if( midValue <= rawValue )
+ if (midValue <= rawLoc)
{
// The location we seek is at or after this entry
lo = mid;
@@ -193,159 +370,60 @@ static ExpandedSourceLoc expandSourceLoc(
}
}
- // `lo` should now point at the entry we want
- UInt entryIndex = lo;
-
- expanded.setRaw(loc.getRaw());
- expanded.sourceManager = sourceManager;
- expanded.entryIndex = entryIndex;
-
- return expanded;
-
-
-}
-
-ExpandedSourceLoc SourceManager::expandSourceLoc(SourceLoc const& loc)
-{
- return Slang::expandSourceLoc(this, loc);
-}
-
-HumaneSourceLoc getHumaneLoc(ExpandedSourceLoc const& loc)
-{
- // First check if this location maps to an actual file.
- SourceFile* sourceFile = loc.getSourceFile();
- if(!sourceFile)
- return HumaneSourceLoc();
-
- auto sourceManager = loc.sourceManager;
-
- auto& entry = sourceManager->sourceFiles[loc.entryIndex];
- UInt offset = loc.getRaw() - entry.startLoc.getRaw();
-
- // We now have a raw input file that we can search for line breaks.
- // We obviously don't want to do a linear scan over and over, so we will
- // cache an array of line break locations in the file.
- auto& lineBreakOffsets = sourceFile->lineBreakOffsets;
- if( lineBreakOffsets.Count() == 0 )
+ // Check if low is a hit
{
- char const* begin = sourceFile->content.begin();
- char const* end = sourceFile->content.end();
-
- char const* cursor = begin;
-
- // Treat the beginning of the file as a line break
- lineBreakOffsets.Add(0);
-
- while( cursor != end )
+ SourceUnit* unit = m_sourceUnits[lo];
+ if (unit->getRange().contains(loc))
{
- int c = *cursor++;
- switch( c )
- {
- case '\r': case '\n':
- {
- // When we see a line-break character we need
- // to record the line break, but we also need
- // to deal with the annoying issue of encodings,
- // where a multi-byte sequence might encode
- // the line break.
-
- int d = *cursor;
- if( (c^d) == ('\r' ^ '\n'))
- cursor++;
-
- lineBreakOffsets.Add(cursor - begin);
- }
- break;
-
- default:
- break;
- }
+ return unit;
}
-
- // Note taht we do *not* treat the end of the file as a line
- // break, because otherwise we would report errors like
- // "end of file inside string literal" with a line number
- // that points at a line that doesn't exist.
}
- // At this point we can assume the `lineBreakOffsets` array has been filled in.
- // We will use a binary search to find the line index that contains our
- // chosen offset.
- UInt lo = 0;
- UInt hi = lineBreakOffsets.Count();
+ // Check the parent if there is a parent
+ return (parent) ? parent->findSourceUnit(loc) : nullptr;
+}
- while( lo+1 < hi )
+SourceFile* SourceManager::findSourceFile(const String& path)
+{
+ RefPtr<SourceFile>* filePtr = m_sourceFiles.TryGetValue(path);
+ if (filePtr)
{
- UInt mid = lo + (hi - lo)/2;
-
- UInt midOffset = lineBreakOffsets[mid];
- if( midOffset <= offset )
- {
- lo = mid;
- }
- else
- {
- hi = mid;
- }
+ return filePtr->Ptr();
}
-
- UInt lineIndex = lo;
- UInt byteIndexInLine = offset - lineBreakOffsets[lineIndex];
-
- // Apply adjustment to the line number
- lineIndex = lineIndex + entry.lineAdjust;
-
- // TODO: we should really translate the byte index in the line
- // to deal with:
- //
- // - Non-ASCII characters, while might consume multiple bytes
- //
- // - Tab characters, which should really adjust how we report
- // columns (although how are we supposed to know the setting
- // that an IDE expects us to use when reporting locations?)
-
- HumaneSourceLoc humaneLoc;
- humaneLoc.path = entry.path;
- humaneLoc.line = lineIndex + 1;
- humaneLoc.column = byteIndexInLine + 1;
-
- return humaneLoc;
+ return parent ? parent->findSourceFile(path) : nullptr;
}
-HumaneSourceLoc ExpandedSourceLoc::getHumaneLoc()
+void SourceManager::addSourceFile(const String& path, SourceFile* sourceFile)
{
- return Slang::getHumaneLoc(*this);
+ SLANG_ASSERT(!findSourceFile(path));
+ m_sourceFiles.Add(path, sourceFile);
}
-HumaneSourceLoc SourceManager::getHumaneLoc(SourceLoc const& loc)
+HumaneSourceLoc SourceManager::getHumaneLoc(SourceLoc loc, SourceLocType type)
{
- return expandSourceLoc(loc).getHumaneLoc();
+ SourceUnit* sourceUnit = findSourceUnit(loc);
+ if (sourceUnit)
+ {
+ return sourceUnit->getHumaneLoc(loc, type);
+ }
+ else
+ {
+ return HumaneSourceLoc();
+ }
}
-SourceLoc SourceManager::getSpellingLoc(ExpandedSourceLoc const& loc)
+String SourceManager::getPath(SourceLoc loc, SourceLocType type)
{
- // First check if this location maps to some raw source file,
- // so that a "spelling" is even possible
- SourceFile* sourceFile = loc.getSourceFile();
- if(!sourceFile)
- return loc;
-
- // If we mapped to a source file, then the location must represent
- // some offset from an entry in our array.
- auto& entry = sourceFiles[loc.entryIndex];
-
- // We extract the offset of the location from the start of the entry
- SourceLoc::RawValue offsetFromStart = loc.getRaw() - entry.startLoc.getRaw();
-
- // And instead apply that offset to the spelling location of the file start
- SourceLoc result = sourceFile->sourceRange.begin + offsetFromStart;
-
- return result;
+ SourceUnit* sourceUnit = findSourceUnit(loc);
+ if (sourceUnit)
+ {
+ return sourceUnit->getPath(loc, type);
+ }
+ else
+ {
+ return String("unknown");
+ }
}
-SourceLoc SourceManager::getSpellingLoc(SourceLoc const& loc)
-{
- return getSpellingLoc(expandSourceLoc(loc));
-}
} // namespace Slang
diff --git a/source/slang/source-loc.h b/source/slang/source-loc.h
index c4a2301a0..45d99ce3e 100644
--- a/source/slang/source-loc.h
+++ b/source/slang/source-loc.h
@@ -3,16 +3,28 @@
#define SLANG_SOURCE_LOC_H_INCLUDED
#include "../core/basic.h"
-#include "../../slang-com-ptr.h"
+#include "../core/slang-memory-arena.h"
+#include "../core/slang-string-slice-pool.h"
+#include "../../slang-com-ptr.h"
#include "../../slang.h"
namespace Slang {
+/** Overview:
+
+SourceFile - Is the immutable contents of a file (or perhaps some generated source - say from doing a macro substitution)
+SourceUnit - Tracks a single parse of a SourceFile. Each SourceUnit defines a range of source locations used. If a SourceFile is parsed twice, two
+SourceUnits are used, with unique SourceRanges - such that it is possible to tell which specific parse a SourceLoc is from. Not only that but the SourceUnit
+contains the modifications of the interpretations of source (say by #line) directives. It is necessary to have these different 'views' on the
+source because if a file is included twice, it may be used in different ways and have different #line directives.
+
+*/
+
class SourceLoc
{
public:
- typedef UInt RawValue;
+ typedef uint32_t RawValue;
private:
RawValue raw;
@@ -45,12 +57,20 @@ public:
inline SourceLoc operator+(SourceLoc loc, Int offset)
{
- return SourceLoc::fromRaw(loc.getRaw() + UInt(offset));
+ return SourceLoc::fromRaw(SourceLoc::RawValue(Int(loc.getRaw()) + offset));
}
// A range of locations in the input source
struct SourceRange
{
+ /// True if the loc is in the range. Range is inclusive on begin to end.
+ bool contains(SourceLoc loc) const { const auto rawLoc = loc.getRaw(); return rawLoc >= begin.getRaw() && rawLoc <= end.getRaw(); }
+ /// Get the total size
+ UInt getSize() const { return UInt(end.getRaw() - begin.getRaw()); }
+
+ /// Get the offset of a loc in this range
+ int getOffset(SourceLoc loc) const { SLANG_ASSERT(contains(loc)); return int(loc.getRaw() - begin.getRaw()); }
+
SourceRange()
{}
@@ -68,11 +88,22 @@ struct SourceRange
SourceLoc end;
};
-// A logical or phyiscal storage object for a range of input code
+// A logical or physical storage object for a range of input code
// that has logically contiguous source locations.
class SourceFile : public RefObject
{
public:
+
+ /// Returns the line break offsets (in bytes from start of content)
+ /// Note that this is lazily evaluated - the line breaks are only calculated on the first request
+ const List<uint32_t>& getLineBreakOffsets();
+
+ /// Calculate the line based on the offset
+ int calcLineIndexFromOffset(int offset);
+
+ /// Calculate the offset for a line
+ int calcColumnIndex(int line, int offset);
+
// The logical file path to report for locations inside this span.
String path;
@@ -82,17 +113,21 @@ public:
/// The actual contents of the file.
UnownedStringSlice content;
- // The range of source locations that the span covers
- SourceRange sourceRange;
-
+ protected:
// In order to speed up lookup of line number information,
// we will cache the starting offset of each line break in
// the input file:
- List<UInt> lineBreakOffsets;
+ List<uint32_t> m_lineBreakOffsets;
};
struct SourceManager;
+enum class SourceLocType
+{
+ Normal, ///< Takes into account #line directives
+ Original, ///< Ignores #line directives - humane location as seen in the actual file
+};
+
// A source location in a format a human might like to see
struct HumaneSourceLoc
{
@@ -105,31 +140,73 @@ struct HumaneSourceLoc
Int getColumn() const { return column; }
};
-// A source location that has been expanded with the info
-// needed to reconstruct a "humane" location if needed.
-struct ExpandedSourceLoc : public SourceLoc
+/* A SourceUnit maps to a single span of SourceLoc range and is equivalent to a single include or use of a source file.
+It is distinct from a SourceFile - because a SourceFile may be included multiple times, with different interpretations (depending
+on #defines for example).s
+*/
+class SourceUnit: public RefObject
{
- // The source manager that owns this location
- SourceManager* sourceManager = nullptr;
+ public:
- // The entry index that is used to understand the location
- UInt entryIndex = 0;
-
- // Get the nominal path for this location
- String getPath() const;
+ // Each entry represents some contiguous span of locations that
+ // all map to the same logical file.
+ struct Entry
+ {
+ /// True if this resets the line numbering. It is distinct from a m_lineAdjust from 0, because it also means the path returns to the default.
+ bool isDefault() const { return m_pathHandle == StringSlicePool::Handle(0); }
- // Get the actual file path where this location appears
- String getSpellingPath() const;
+ SourceLoc m_startLoc; ///< Where does this entry begin?
+ StringSlicePool::Handle m_pathHandle; ///< What is the presumed path for this entry. If 0 it means there is no path.
+ int32_t m_lineAdjust; ///< Adjustment to apply to source line numbers when printing presumed locations. Relative to the line number in the underlying file.
+ };
- // Get the original source file that holds this location
- SourceFile* getSourceFile() const;
+ /// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is
+ /// associated with this location, and therefore the location should be interpreted as an offset
+ /// into the underlying sourceFile.
+ int findEntryIndex(SourceLoc sourceLoc) const;
+
+ /// Add a line directive for this unit. The directiveLoc must of course be in this SourceUnit
+ /// The path handle, must have been constructed on the SourceManager associated with the unit
+ /// NOTE! Directives are assumed to be added IN ORDER during parsing such that every directiveLoc > previous
+ void addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line);
+
+ void addLineDirective(SourceLoc directiveLoc, const String& path, int line);
+
+ /// Removes any corrections on line numbers and reverts to the source files path
+ void addDefaultLineDirective(SourceLoc directiveLoc);
+
+ /// Get the range that this unit applies to
+ const SourceRange& getRange() const { return m_range; }
+ /// Get the entries
+ const List<Entry>& getEntries() const { return m_entries; }
+ /// Get the source file holds the contents this 'unit'
+ SourceFile* getSourceFile() const { return m_sourceFile; }
+ /// Get the source manager
+ SourceManager* getSourceManager() const { return m_sourceManager; }
+
+ /// Get the humane location
+ /// Type determines if the location wanted is the original, or the 'normal' (which modifys behavior based on #line directives)
+ HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Normal);
+
+ /// Get the path associated with a location
+ String getPath(SourceLoc loc, SourceLocType type = SourceLocType::Normal);
+
+ /// Ctor
+ SourceUnit(SourceManager* sourceManager, SourceFile* sourceFile, SourceRange range):
+ m_sourceManager(sourceManager),
+ m_range(range),
+ m_sourceFile(sourceFile)
+ {
+ }
- // Get a "humane" version of a source location
- HumaneSourceLoc getHumaneLoc();
+ protected:
+
+ SourceManager* m_sourceManager; /// Get the manager this belongs to
+ SourceRange m_range; ///< The range that this SourceUnit applies to
+ RefPtr<SourceFile> m_sourceFile; ///< The source file can hold the line breaks
+ List<Entry> m_entries; ///< An array entries describing how we should interpret a range, starting from the start location.
};
-HumaneSourceLoc getHumaneLoc(ExpandedSourceLoc const& loc);
-
struct SourceManager
{
// Initialize a source manager, with an optional parent
@@ -138,29 +215,36 @@ struct SourceManager
SourceRange allocateSourceRange(UInt size);
- SourceFile* allocateSourceFile(
+ SourceFile* newSourceFile(
String const& path,
ISlangBlob* content);
- SourceFile* allocateSourceFile(
+ SourceFile* newSourceFile(
String const& path,
String const& content);
- SourceLoc allocateSourceFileForLineDirective(
- SourceLoc const& directiveLoc,
- String const& path,
- UInt line);
+ /// Get the humane source location
+ HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Normal);
+
+ /// Get the path associated with a location
+ String getPath(SourceLoc loc, SourceLocType type = SourceLocType::Normal);
- // Expand a source location to include more explicit info
- ExpandedSourceLoc expandSourceLoc(SourceLoc const& loc);
+ /// Allocate a new source unit from a file
+ SourceUnit* newSourceUnit(SourceFile* sourceFile);
- // Get a "humane" version of a source location
- HumaneSourceLoc getHumaneLoc(SourceLoc const& loc);
+ /// Find a unit by a source file location. If not found in this will look in the parent/
+ /// Returns nullptr if not found
+ SourceUnit* findSourceUnit(SourceLoc loc);
+ /// Searches this manager, and then the parent to see if can find a match for path.
+ /// If not found returns nullptr.
+ SourceFile* findSourceFile(const String& path);
- // Get the source location that represents the spelling location corresponding to a location.
- SourceLoc getSpellingLoc(ExpandedSourceLoc const& loc);
- SourceLoc getSpellingLoc(SourceLoc const& loc);
+ /// Add a source file, path must be unique for this manager AND any parents
+ void addSourceFile(const String& path, SourceFile* sourceFile);
+
+ /// Get the slice pool
+ StringSlicePool& getStringSlicePool() { return m_slicePool; }
// The first location available to this source manager
// (may not be the first location of all, because we might
@@ -173,26 +257,13 @@ struct SourceManager
// The location to be used by the next source file to be loaded
SourceLoc nextLoc;
- // Each entry represents some contiguous span of locations that
- // all map to the same logical file.
- struct Entry
- {
- // Where does this entry begin?
- SourceLoc startLoc;
-
- // The soure file that represents the actual data
- RefPtr<SourceFile> sourceFile;
+ protected:
- // What is the presumed path for this entry
- String path;
-
- // Adjustment to apply to source line numbers when printing presumed locations
- Int lineAdjust = 0;
- };
+ // All of the source units. These are held in increasing order of range, so can find by doing a binary chop.
+ List<RefPtr<SourceUnit> > m_sourceUnits;
+ StringSlicePool m_slicePool;
- // An array of soure files we have loaded, ordered by
- // increasing starting location
- List<Entry> sourceFiles;
+ Dictionary<String, RefPtr<SourceFile> > m_sourceFiles;
};
diff --git a/tools/slang-test/slang-test.vcxproj b/tools/slang-test/slang-test.vcxproj
index 54ea6f342..adc12f8d1 100644
--- a/tools/slang-test/slang-test.vcxproj
+++ b/tools/slang-test/slang-test.vcxproj
@@ -183,4 +183,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project> \ No newline at end of file
+</Project> \ No newline at end of file
diff --git a/tools/slang-test/slang-test.vcxproj.filters b/tools/slang-test/slang-test.vcxproj.filters
index 03bb10348..b34d45798 100644
--- a/tools/slang-test/slang-test.vcxproj.filters
+++ b/tools/slang-test/slang-test.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
@@ -32,13 +32,13 @@
<ClCompile Include="test-context.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="unit-test-free-list.cpp">
+ <ClCompile Include="unit-test-byte-encode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="unit-test-memory-arena.cpp">
+ <ClCompile Include="unit-test-free-list.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="unit-test-byte-encode.cpp">
+ <ClCompile Include="unit-test-memory-arena.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>