diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-10-10 13:56:25 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-10 13:56:25 -0400 |
| commit | 879ec1b385d290a4375682ec613a9e7a1967fc7d (patch) | |
| tree | 0d5f32d83d45458db54cce281c0c6331a677cdff | |
| parent | 60a91d63afab47a172690974c8b566af74072932 (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.sln | 164 | ||||
| -rw-r--r-- | source/core/core.vcxproj | 5 | ||||
| -rw-r--r-- | source/core/core.vcxproj.filters | 27 | ||||
| -rw-r--r-- | source/core/slang-string-slice-pool.cpp | 43 | ||||
| -rw-r--r-- | source/core/slang-string-slice-pool.h | 50 | ||||
| -rw-r--r-- | source/slang/diagnostics.cpp | 3 | ||||
| -rw-r--r-- | source/slang/ir-serialize.cpp | 21 | ||||
| -rw-r--r-- | source/slang/ir-serialize.h | 2 | ||||
| -rw-r--r-- | source/slang/lexer.cpp | 30 | ||||
| -rw-r--r-- | source/slang/lexer.h | 19 | ||||
| -rw-r--r-- | source/slang/preprocessor.cpp | 74 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 21 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj | 10 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 24 | ||||
| -rw-r--r-- | source/slang/source-loc.cpp | 530 | ||||
| -rw-r--r-- | source/slang/source-loc.h | 185 | ||||
| -rw-r--r-- | tools/slang-test/slang-test.vcxproj | 2 | ||||
| -rw-r--r-- | tools/slang-test/slang-test.vcxproj.filters | 8 |
18 files changed, 728 insertions, 490 deletions
@@ -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> |
