Merge remote-tracking branch 'aosp/upstream-master' into update-shaderc

Includes the following:
427daa5 Update tests for more strict glslang
2df47b5 Add -flimit to glslc to support shader resource limits.
9d52054 Indicate Shaderc's level of stability.
1ef0a89 Support resource limits in C, C++ API
89eefb9 Add -fentry-point to glslc
725a8fd Update READMEs.
4b8ad0e Add source/parsed_operand.cpp to SPIRV-Tools
38bd2b0 Some source files are renamed in SPIRV-Tools.
fc71c2f Added SPIRV-Tools source file validate_datarules.cpp
f036381 C, C++ APIs are sensitive to entry_point_name
aaa8b0c Removed SPIRV-Tools source/instruction.cpp
525a48c Add glslang source file hlsl/hlslAttributes.cpp
cdefe18 glslc: expose HLSL compilation support from Glslang
fa93320 Add API support for compiling HLSL
e6b4795 Rename GlslInitialzer -> GlslangInitializer
a39e3cf Ignore .DS_Store files

Test: checkbuild.py on Linux x86; unit tests on Windows
Change-Id: Ia3c8c4ef67bac740818b1a0ef0089159a4a40535
diff --git a/.gitignore b/.gitignore
index 27cd089..61cc44f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
 third_party/glslang/
 third_party/googletest/
 third_party/spirv-tools/
+.DS_Store
diff --git a/CHANGES b/CHANGES
index 1f9df68..05d6d96 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,19 @@
 Revision history for Shaderc
 
 v2016.2-dev 2016-10-12
+ - Describe Shaderc's level of stability.
+ - Support HLSL compilation, exposing functionality in Glslang.
+   - Supported in C, C++ API
+   - glslc accepts "-x hlsl", and assumes .hlsl files are HLSL.
+   - glslc accepts "-fentry-point=<name>" to set entry point name,
+     overriding default value "main".
+ - Support setting shader resource limits in C, C++ APIs, and in
+   glslc
+   - glslc adds -flimit=<setting>
+   - glslc adds --show-limits to display defaults and valid resource
+     limit syntax.
+   - glslc adds "-flimit-file <file>" support to read Glslang resource
+     configuration files, i.e. the output of "glslangValidator -c".
 
 v2016.1 2016-10-12
  - C API for assembling now takes an options object
diff --git a/README.md b/README.md
index f322636..c3410cd 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,11 @@
 A collection of tools, libraries and tests for shader compilation.
 At the moment it includes:
 
-- [`glslc`](glslc), a command line compiler for GLSL to SPIR-V, and
-- `libshaderc` a library API for doing the same.
+- [`glslc`](glslc), a command line compiler for GLSL/HLSL to SPIR-V, and
+- [`libshaderc`](libshaderc), a library API for doing the same.
 
-Shaderc wraps around core functionality in
-[Glslang](https://github.com/KhronosGroup/glslang)
-and [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools).  Shaderc aims to
+Shaderc wraps around core functionality in [glslang][khr-glslang]
+and [SPIRV-Tools][spirv-tools].  Shaderc aims to
 to provide:
 * a command line compiler with GCC- and Clang-like usage, for better
   integration with build systems
@@ -23,7 +22,9 @@
 
 ## Status
 
-Shaderc is approaching maturity, but is still subject to incompatible changes.
+Shaderc has maintained backward compatibility for quite some time, and we
+don't anticipate any breaking changes.
+Ongoing enhancements are described in the [CHANGES](CHANGES) file.
 
 Shaderc has been shipping in the
 [Android NDK](https://developer.android.com/ndk/index.html) since version r12b.
@@ -31,7 +32,7 @@
 Those repos are downstream from GitHub.)
 
 For licensing terms, please see the [`LICENSE`](LICENSE) file.  If interested in
-contributing to this project, please see [`CONTRIBUTING.md`](CONTRIBUTING.md)
+contributing to this project, please see [`CONTRIBUTING.md`](CONTRIBUTING.md).
 
 This is not an official Google product (experimental or otherwise), it is just
 code that happens to be owned by Google.  That may change if Shaderc gains
@@ -50,18 +51,17 @@
 - `third_party/`: third party open source packages; see below
 - `utils/`: utility scripts for Shaderc
 
-Shaderc depends on `glslang`, the Khronos reference compiler for GLSL.
+Shaderc depends on glslang, the Khronos reference compiler for GLSL.
 Sometimes a change updates both Shaderc and glslang.  In that case the
-glslang change will appear in [google/glslang](https://github.com/google/glslang)
-before it appears upstream in
-[KhronosGroup/glslang](https://github.com/KhronosGroup/glslang).
+glslang change will appear in [google/glslang][google-glslang]
+before it appears upstream in [KhronosGroup/glslang][khr-glslang]
 We intend to upstream all changes to glslang. We maintain the separate
 copy only to stage those changes for review, and to provide something for
 Shaderc to build against in the meantime.  Please see
 [DEVELOPMENT.howto.md](DEVELOPMENT.howto.md) for more details.
 
-Shaderc depends on [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools)
-for assembling and disassembling SPIR-V binaries.
+Shaderc depends on [SPIRV-Tools][spirv-tools] for assembling, disassembling,
+and transforming SPIR-V binaries.
 
 Shaderc depends on the [Google Test](https://github.com/google/googletest)
 testing framework.
@@ -212,3 +212,7 @@
 
 Then the coverage report can be found under the `$BUILD_DIR/coverage-report`
 directory.
+
+[khr-glslang]: https://github.com/KhronosGroup/glslang
+[google-glslang]: https://github.com/google/glslang
+[spirv-tools]: https://github.com/KhronosGroup/SPIRV-Tools
diff --git a/glslc/CMakeLists.txt b/glslc/CMakeLists.txt
index ba4d4c5..8f21aa2 100644
--- a/glslc/CMakeLists.txt
+++ b/glslc/CMakeLists.txt
@@ -7,6 +7,8 @@
   src/file.h
   src/file_includer.cc
   src/file_includer.h
+  src/resource_parse.h
+  src/resource_parse.cc
   src/shader_stage.cc
   src/shader_stage.h
   src/dependency_info.cc
@@ -31,6 +33,7 @@
   LINK_LIBS glslc shaderc_util shaderc
   TEST_NAMES
     file
+    resource_parse
     stage)
 
 shaderc_add_asciidoc(glslc_doc_README README)
diff --git a/glslc/README.asciidoc b/glslc/README.asciidoc
index ba6375a..b1551cd 100644
--- a/glslc/README.asciidoc
+++ b/glslc/README.asciidoc
@@ -5,13 +5,20 @@
 
 == Name
 
-`glslc` - A command-line GLSL to SPIR-V compiler with Clang-compatible arguments.
+`glslc` - A command-line GLSL/HLSL to SPIR-V compiler with
+Clang-compatible arguments.
 
 == Synopsis
 
 ----
+glslc [--help]
+
+glslc [--show-limits]
+
 glslc [-c|-S|-E]
-      [-x glsl] [-std=standard]
+      [-x ...] [-std=standard]
+      [-fentry-point=...]
+      [-flimit=...]
       [-fshader-stage=...]
       [--target-env=...]
       [-g]
@@ -27,7 +34,7 @@
 
 === Input file languages
 
-glslc accepts both GLSL source and SPIR-V assembly files as inputs.
+glslc accepts both GLSL/HLSL source and SPIR-V assembly files as inputs.
 
 ==== Shader stage specification
 
@@ -108,6 +115,12 @@
 
 `--help` tells the glslc compiler to display all available options and exit.
 
+==== `--show-limits`
+
+`--show-limits` shows default resource limits for shader compilation.  The syntax
+is the same as accepted by `-flimit=` and for the contents of the file specified
+by `-flimit-file`.
+
 ==== `-o`
 
 `-o` lets you specify the output file's name. It cannot be used when there are
@@ -115,6 +128,34 @@
 
 === Language and Mode Selection Options
 
+[[option-f-entry-point]]
+==== `-fentry-point=`
+
+`-fentry-point=<name>` lets you specify the entry point name.  This is only
+significant for HLSL compilation.  The default is "main".
+
+[[option-f-limit]]
+==== `-flimit=`
+
+`-flimit=<resource-limits>` lets you specify resource limits.
+The argument should be a sequence of limit name, integer value pairs.  Tokens
+should be separated by whitespace.  If the same limit is specified several
+times, only the last setting takes effect.
+
+Use `--show-limits` to show the default values, and example syntax.
+
+This option affects all compiled shaders.
+
+[[option-f-limit-file]]
+==== `-flimit-file`
+
+`-flimit-file <resource-limits-file>` lets you specify resource limits in a file.
+The syntax of the file contents is the same as the argument to `-flimit=` and
+the output of `--show-limits`.  This option accepts Glslang resource configuration
+files, e.g. as emitted by `glslangValidator -c`.
+
+This option affects all compiled shaders.
+
 [[option-f-shader-stage]]
 ==== `-fshader-stage=`
 
@@ -158,7 +199,8 @@
 
 `-std=` behaves as follows:
 
-* `-std=` affects the version of all inputs passed to `glslc`.
+* `-std=` affects the version of all GLSL inputs passed to `glslc`.
+* `-std=` is ignored for HLSL inputs.
 * `-std=` overwrites `#version` directives in all input shaders, including those
   preceding the argument.
 * If a `-std=` argument specifies a different version from a `#version`
@@ -189,8 +231,9 @@
 
 ==== `-x`
 
-`-x` lets you specify the language of the input shader files. Right now, the
-only accepted argument is `glsl`.
+`-x` lets you specify the language of the input shader files. Valid languages
+are `glsl` and `hlsl`.  If the file extension is `hlsl` then the default language
+is HLSL.  Otherwise the default is 'glsl'.
 
 [[compilation-stage-selection-options]]
 === Compilation Stage Selection Options
diff --git a/glslc/src/file.h b/glslc/src/file.h
index 93d98ef..902b4cf 100644
--- a/glslc/src/file.h
+++ b/glslc/src/file.h
@@ -32,9 +32,13 @@
          extension == "tese" || extension == "geom" || extension == "comp";
 }
 
-// Returns true if the given file name has extension "glsl".
-inline bool IsGlslFile(const shaderc_util::string_piece& filename) {
-  return glslc::GetFileExtension(filename) == "glsl";
+// Returns the file extension if is either "glsl" or "hlsl", or an empty
+// string otherwise.
+inline std::string GetGlslOrHlslExtension(
+    const shaderc_util::string_piece& filename) {
+  auto extension = glslc::GetFileExtension(filename);
+  if ((extension == "glsl") || (extension == "hlsl")) return extension.str();
+  return "";
 }
 
 }  // namespace glslc
diff --git a/glslc/src/file_compiler.cc b/glslc/src/file_compiler.cc
index 311fddf..5469736 100644
--- a/glslc/src/file_compiler.cc
+++ b/glslc/src/file_compiler.cc
@@ -62,15 +62,14 @@
 }  // anonymous namespace
 
 namespace glslc {
-bool FileCompiler::CompileShaderFile(const std::string& input_file,
-                                     shaderc_shader_kind shader_stage) {
+bool FileCompiler::CompileShaderFile(const InputFileSpec& input_file) {
   std::vector<char> input_data;
-  std::string path = input_file;
+  std::string path = input_file.name;
   if (!shaderc_util::ReadFile(path, &input_data)) {
     return false;
   }
 
-  std::string output_name = GetOutputFileName(input_file);
+  std::string output_name = GetOutputFileName(input_file.name);
 
   std::ofstream potential_file_stream;
   std::ostream* output_stream =
@@ -79,7 +78,7 @@
     // An error message has already been emitted to the stderr stream.
     return false;
   }
-  string_piece error_file_name = input_file;
+  string_piece error_file_name = input_file.name;
 
   if (error_file_name == "-") {
     // If the input file was stdin, we want to output errors as <stdin>.
@@ -99,38 +98,45 @@
   const auto& used_source_files = includer->file_path_trace();
   options_.SetIncluder(std::move(includer));
 
-  if (shader_stage == shaderc_spirv_assembly) {
+  if (input_file.stage == shaderc_spirv_assembly) {
     // Only act if the requested target is SPIR-V binary.
     if (output_type_ == OutputType::SpirvBinary) {
       const auto result =
           compiler_.AssembleToSpv(source_string.data(), source_string.size());
-      return EmitCompiledResult(result, input_file, error_file_name,
+      return EmitCompiledResult(result, input_file.name, error_file_name,
                                 used_source_files, output_stream);
     } else {
       return true;
     }
   }
 
+  // Set the language.  Since we only use the options object in this
+  // method, then it's ok to always set it without resetting it after
+  // compilation.  A subsequent compilation will set it again anyway.
+  options_.SetSourceLanguage(input_file.language);
+
   switch (output_type_) {
     case OutputType::SpirvBinary: {
       const auto result = compiler_.CompileGlslToSpv(
-          source_string.data(), source_string.size(), shader_stage,
-          error_file_name.data(), options_);
-      return EmitCompiledResult(result, input_file, error_file_name,
+          source_string.data(), source_string.size(), input_file.stage,
+          error_file_name.data(), input_file.entry_point_name.c_str(),
+          options_);
+      return EmitCompiledResult(result, input_file.name, error_file_name,
                                 used_source_files, output_stream);
     }
     case OutputType::SpirvAssemblyText: {
       const auto result = compiler_.CompileGlslToSpvAssembly(
-          source_string.data(), source_string.size(), shader_stage,
-          error_file_name.data(), options_);
-      return EmitCompiledResult(result, input_file, error_file_name,
+          source_string.data(), source_string.size(), input_file.stage,
+          error_file_name.data(), input_file.entry_point_name.c_str(),
+          options_);
+      return EmitCompiledResult(result, input_file.name, error_file_name,
                                 used_source_files, output_stream);
     }
     case OutputType::PreprocessedText: {
       const auto result = compiler_.PreprocessGlsl(
-          source_string.data(), source_string.size(), shader_stage,
+          source_string.data(), source_string.size(), input_file.stage,
           error_file_name.data(), options_);
-      return EmitCompiledResult(result, input_file, error_file_name,
+      return EmitCompiledResult(result, input_file.name, error_file_name,
                                 used_source_files, output_stream);
     }
   }
@@ -152,11 +158,12 @@
   // Handle the error message for failing to deduce the shader kind.
   if (result.GetCompilationStatus() ==
       shaderc_compilation_status_invalid_stage) {
-    if (IsGlslFile(error_file_name)) {
+    auto glsl_or_hlsl_extension = GetGlslOrHlslExtension(error_file_name);
+    if (glsl_or_hlsl_extension != "") {
       std::cerr << "glslc: error: "
                 << "'" << error_file_name << "': "
-                << ".glsl file encountered but no -fshader-stage "
-                   "specified ahead";
+                << "." << glsl_or_hlsl_extension
+                << " file encountered but no -fshader-stage specified ahead";
     } else if (error_file_name == "<stdin>") {
       std::cerr
           << "glslc: error: '-': -fshader-stage required when input is from "
diff --git a/glslc/src/file_compiler.h b/glslc/src/file_compiler.h
index 6b077a1..2f45e92 100644
--- a/glslc/src/file_compiler.h
+++ b/glslc/src/file_compiler.h
@@ -25,6 +25,14 @@
 
 namespace glslc {
 
+// Describes an input file to be compiled.
+struct InputFileSpec {
+  std::string name;
+  shaderc_shader_kind stage;
+  shaderc_source_language language;
+  std::string entry_point_name;
+};
+
 // Context for managing compilation of source GLSL files into destination
 // SPIR-V files or preprocessed output.
 class FileCompiler {
@@ -46,10 +54,11 @@
         total_warnings_(0),
         total_errors_(0) {}
 
-  // Compiles a shader received in input_file, returning true on success and
-  // false otherwise. If force_shader_stage is not shaderc_glsl_infer_source or
-  // any default shader stage then the given shader_stage will be used,
-  // otherwise it will be determined from the source or the file type.
+  // Compiles a shader received as specified by input_file, returning true
+  // on success and false otherwise. If force_shader_stage is not
+  // shaderc_glsl_infer_source or any default shader stage then the given
+  // shader_stage will be used, otherwise it will be determined from the source
+  // or the file type.
   //
   // Places the compilation output into a new file whose name is derived from
   // input_file according to the rules from glslc/README.asciidoc.
@@ -59,8 +68,7 @@
   //
   // Any errors/warnings found in the shader source will be output to std::cerr
   // and increment the counts reported by OutputMessages().
-  bool CompileShaderFile(const std::string& input_file,
-                         shaderc_shader_kind shader_stage);
+  bool CompileShaderFile(const InputFileSpec& input_file);
 
   // Adds a directory to be searched when processing #include directives.
   //
diff --git a/glslc/src/file_test.cc b/glslc/src/file_test.cc
index f242621..d9e075b 100644
--- a/glslc/src/file_test.cc
+++ b/glslc/src/file_test.cc
@@ -14,14 +14,15 @@
 
 #include "file.h"
 
-#include <gtest/gtest.h>
+#include <gmock/gmock.h>
 
 namespace {
 
 using glslc::GetFileExtension;
 using glslc::IsStageFile;
-using glslc::IsGlslFile;
+using glslc::GetGlslOrHlslExtension;
 using shaderc_util::string_piece;
+using testing::Eq;
 
 class FileExtensionTest : public testing::Test {
  protected:
@@ -36,7 +37,10 @@
   string_piece geom_ext = "shader.geom";
   string_piece comp_ext = "shader.comp";
   string_piece glsl_ext = "shader.glsl";
+  string_piece hlsl_ext = "shader.hlsl";
   string_piece multi_dot = "shader.some..ext";
+  string_piece both_hg_ext = "shader.hlsl.glsl";
+  string_piece both_gh_ext = "shader.glsl.hlsl";
 };
 
 TEST_F(FileExtensionTest, GetFileExtension) {
@@ -52,21 +56,26 @@
   EXPECT_EQ("comp", GetFileExtension(comp_ext));
   EXPECT_EQ("glsl", GetFileExtension(glsl_ext));
   EXPECT_EQ("ext", GetFileExtension(multi_dot));
+  EXPECT_EQ("glsl", GetFileExtension(both_hg_ext));
+  EXPECT_EQ("hlsl", GetFileExtension(both_gh_ext));
 }
 
-TEST_F(FileExtensionTest, IsGlslFile) {
-  EXPECT_FALSE(IsGlslFile(empty));
-  EXPECT_FALSE(IsGlslFile(dot));
-  EXPECT_FALSE(IsGlslFile(no_ext));
-  EXPECT_FALSE(IsGlslFile(trailing_dot));
-  EXPECT_FALSE(IsGlslFile(vert_ext));
-  EXPECT_FALSE(IsGlslFile(frag_ext));
-  EXPECT_FALSE(IsGlslFile(tesc_ext));
-  EXPECT_FALSE(IsGlslFile(tese_ext));
-  EXPECT_FALSE(IsGlslFile(geom_ext));
-  EXPECT_FALSE(IsGlslFile(comp_ext));
-  EXPECT_TRUE(IsGlslFile(glsl_ext));
-  EXPECT_FALSE(IsGlslFile(multi_dot));
+TEST_F(FileExtensionTest, GetGlslOrHlslExtension) {
+  EXPECT_THAT(GetGlslOrHlslExtension(empty), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(dot), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(no_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(trailing_dot), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(vert_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(frag_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(tesc_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(tese_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(geom_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(comp_ext), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(glsl_ext), Eq("glsl"));
+  EXPECT_THAT(GetGlslOrHlslExtension(hlsl_ext), Eq("hlsl"));
+  EXPECT_THAT(GetGlslOrHlslExtension(multi_dot), Eq(""));
+  EXPECT_THAT(GetGlslOrHlslExtension(both_hg_ext), Eq("glsl"));
+  EXPECT_THAT(GetGlslOrHlslExtension(both_gh_ext), Eq("hlsl"));
 }
 
 TEST_F(FileExtensionTest, IsStageFile) {
diff --git a/glslc/src/main.cc b/glslc/src/main.cc
index 782e3ce..108212d 100644
--- a/glslc/src/main.cc
+++ b/glslc/src/main.cc
@@ -21,11 +21,15 @@
 #include <string>
 #include <utility>
 
+#include "libshaderc_util/compiler.h"
+#include "libshaderc_util/io.h"
 #include "libshaderc_util/string_piece.h"
+#include "shaderc/shaderc.h"
 #include "spirv-tools/libspirv.h"
 
 #include "file.h"
 #include "file_compiler.h"
+#include "resource_parse.h"
 #include "shader_stage.h"
 
 using shaderc_util::string_piece;
@@ -45,6 +49,17 @@
   -Dmacro[=defn]    Add an implicit macro definition.
   -E                Outputs only the results of the preprocessing step.
                     Output defaults to standard output.
+  -fentry-point=<name>
+                    Specify the entry point name for HLSL compilation, for
+                    all subsequent source files.  Default is "main".
+  -flimit=<settings>
+                    Specify resource limits. Each limit is specified by a limit
+                    name followed by an integer value.  Tokens should be
+                    separated by whitespace.  If the same limit is specified
+                    several times, only the last setting takes effect.
+  --show-limits     Display available limit names and their default values.
+  -flimit-file <file>
+                    Set limits as specified in the given file.
   -fshader-stage=<stage>
                     Treat subsequent input files as having stage <stage>.
                     Valid stages are vertex, fragment, tesscontrol, tesseval,
@@ -56,9 +71,9 @@
   -I <value>        Add directory to include search path.
   -o <file>         Write output to <file>.
                     A file name of '-' represents standard output.
-  -std=<value>      Version and profile for input files. Possible values
+  -std=<value>      Version and profile for GLSL input files. Possible values
                     are concatenations of version and profile, e.g. 310es,
-                    450core, etc.
+                    450core, etc.  Ignored for HLSL files.
   -mfmt=<format>    Output SPIR-V binary code using the selected format. This
                     option may be specified only when the compilation output is
                     in SPIR-V binary code form. Available options include bin, c
@@ -77,7 +92,9 @@
   -w                Suppresses all warning messages.
   -Werror           Treat all warnings as errors.
   -x <language>     Treat subsequent input files as having type <language>.
-                    The only supported language is glsl.
+                    Valid languages are: glsl, hlsl.
+                    For files ending in .hlsl the default is hlsl.
+                    Otherwise the default is glsl.
 )";
 }
 
@@ -104,14 +121,34 @@
   }
 }
 
+// Sets resource limits according to the given string. The string
+// should be formated as required for ParseResourceSettings.
+// Returns true on success.  Otherwise returns false and sets err
+// to a descriptive error message.
+bool SetResourceLimits(const std::string& str, shaderc::CompileOptions* options,
+                       std::string* err) {
+  std::vector<glslc::ResourceSetting> settings;
+  if (!ParseResourceSettings(str, &settings, err)) {
+    return false;
+  }
+  for (const auto& setting : settings) {
+    options->SetLimit(setting.limit, setting.value);
+  }
+  return true;
+}
+
 const char kBuildVersion[] =
 #include "build-version.inc"
     ;
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
-  std::vector<std::pair<std::string, shaderc_shader_kind>> input_files;
+  std::vector<glslc::InputFileSpec> input_files;
   shaderc_shader_kind current_fshader_stage = shaderc_glsl_infer_from_source;
+  bool source_language_forced = false;
+  shaderc_source_language current_source_language =
+      shaderc_source_language_glsl;
+  std::string current_entry_point_name("main");
   glslc::FileCompiler compiler;
   bool success = true;
   bool has_stdin_input = false;
@@ -121,6 +158,20 @@
     if (arg == "--help") {
       ::PrintHelp(&std::cout);
       return 0;
+    } else if (arg == "--show-limits") {
+      shaderc_util::Compiler default_compiler;
+// The static cast here depends on us keeping the shaderc_limit enum in
+// lockstep with the shaderc_util::Compiler::Limit enum.  The risk of mismatch
+// is low since both are generated from the same resources.inc file.
+#define RESOURCE(NAME, FIELD, ENUM)                            \
+  std::cout << #NAME << " "                                    \
+            << default_compiler.GetLimit(                      \
+                   static_cast<shaderc_util::Compiler::Limit>( \
+                       shaderc_limit_##ENUM))                  \
+            << std::endl;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+      return 0;
     } else if (arg == "--version") {
       std::cout << kBuildVersion << std::endl;
       std::cout << "Target: " << spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0)
@@ -143,6 +194,37 @@
                   << std::endl;
         return 1;
       }
+    } else if (arg.starts_with("-fentry-point=")) {
+      current_entry_point_name =
+          arg.substr(std::strlen("-fentry-point=")).str();
+    } else if (arg.starts_with("-flimit=")) {
+      std::string err;
+      if (!SetResourceLimits(arg.substr(std::strlen("-flimit=")).str(),
+                             &compiler.options(), &err)) {
+        std::cerr << "glslc: error: -flimit error: " << err << std::endl;
+        return 1;
+      }
+    } else if (arg.starts_with("-flimit-file")) {
+      std::string err;
+      string_piece limits_file;
+      if (!GetOptionArgument(argc, argv, &i, "-flimit-file", &limits_file)) {
+        std::cerr << "glslc: error: argument to '-flimit-file' is missing"
+                  << std::endl;
+        return 1;
+      }
+      std::vector<char> contents;
+      if (!shaderc_util::ReadFile(limits_file.str(), &contents)) {
+        std::cerr << "glslc: cannot read limits file: " << limits_file
+                  << std::endl;
+        return 1;
+      }
+      if (!SetResourceLimits(
+              string_piece(contents.data(), contents.data() + contents.size())
+                  .str(),
+              &compiler.options(), &err)) {
+        std::cerr << "glslc: error: -flimit-file error: " << err << std::endl;
+        return 1;
+      }
     } else if (arg.starts_with("-std=")) {
       const string_piece standard = arg.substr(std::strlen("-std="));
       int version;
@@ -196,11 +278,16 @@
             << std::endl;
         success = false;
       } else {
-        if (option_arg != "glsl") {
+        if (option_arg == "glsl") {
+          current_source_language = shaderc_source_language_glsl;
+        } else if (option_arg == "hlsl") {
+          current_source_language = shaderc_source_language_hlsl;
+        } else {
           std::cerr << "glslc: error: language not recognized: '" << option_arg
                     << "'" << std::endl;
           return 1;
         }
+        source_language_forced = true;
       }
     } else if (arg == "-c") {
       compiler.SetIndividualCompilationFlag();
@@ -329,15 +416,22 @@
         has_stdin_input = true;
       }
 
+      const auto language = source_language_forced
+                                ? current_source_language
+                                : ((glslc::GetFileExtension(arg) == "hlsl")
+                                       ? shaderc_source_language_hlsl
+                                       : shaderc_source_language_glsl);
+
       // If current_fshader_stage is shaderc_glsl_infer_from_source, that means
       // we didn't set forced shader kinds (otherwise an error should have
       // already been emitted before). So we should deduce the shader kind
       // from the file name. If current_fshader_stage is specifed to one of
       // the forced shader kinds, use that for the following compilation.
-      input_files.emplace_back(
-          arg.str(), current_fshader_stage == shaderc_glsl_infer_from_source
-                         ? glslc::DeduceDefaultShaderKindFromFileName(arg)
-                         : current_fshader_stage);
+      input_files.emplace_back(glslc::InputFileSpec{
+          arg.str(), (current_fshader_stage == shaderc_glsl_infer_from_source
+                          ? glslc::DeduceDefaultShaderKindFromFileName(arg)
+                          : current_fshader_stage),
+          language, current_entry_point_name});
     }
   }
 
@@ -346,10 +440,7 @@
   if (!success) return 1;
 
   for (const auto& input_file : input_files) {
-    const std::string& name = input_file.first;
-    const shaderc_shader_kind stage = input_file.second;
-
-    success &= compiler.CompileShaderFile(name, stage);
+    success &= compiler.CompileShaderFile(input_file);
   }
 
   compiler.OutputMessages();
diff --git a/glslc/src/resource_parse.cc b/glslc/src/resource_parse.cc
new file mode 100644
index 0000000..7109333
--- /dev/null
+++ b/glslc/src/resource_parse.cc
@@ -0,0 +1,97 @@
+// Copyright 2016 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "resource_parse.h"
+
+#include <algorithm>
+#include <cstring>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+namespace {
+
+// Converts a limit string to a limit enum.  Returns true on successful
+// conversion.
+bool StringToLimit(const std::string& str, shaderc_limit* limit) {
+  const char* cstr = str.c_str();
+#define RESOURCE(NAME, FIELD, ENUM)    \
+  if (0 == std::strcmp(#NAME, cstr)) { \
+    *limit = shaderc_limit_##ENUM;     \
+    return true;                       \
+  }
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+  return false;
+}
+
+// Returns true if we should ignore the setting.
+bool IgnoreSetting(const std::string& str) {
+  const std::string ignore_list[] = {
+      "nonInductiveForLoops",
+      "whileLoops",
+      "doWhileLoops",
+      "generalUniformIndexing",
+      "generalAttributeMatrixVectorIndexing",
+      "generalVaryingIndexing",
+      "generalSamplerIndexing",
+      "generalVariableIndexing",
+      "generalConstantMatrixVectorIndexing",
+  };
+  return std::find(std::begin(ignore_list), std::end(ignore_list), str) !=
+         std::end(ignore_list);
+}
+
+}  //  anonymous namespace
+
+namespace glslc {
+
+bool ParseResourceSettings(const std::string& input,
+                           std::vector<ResourceSetting>* limits,
+                           std::string* err) {
+  auto failure = [err, limits](std::string msg) {
+    *err = msg;
+    limits->clear();
+    return false;
+  };
+  std::istringstream input_stream(input);
+  std::istream_iterator<std::string> pos((input_stream));
+  limits->clear();
+
+  while (pos != std::istream_iterator<std::string>()) {
+    const std::string limit_name = *pos++;
+    shaderc_limit limit = static_cast<shaderc_limit>(0);
+    bool ignore = IgnoreSetting(limit_name);
+    if (!ignore) {
+      if (!StringToLimit(limit_name, &limit))
+        return failure(std::string("invalid resource limit: " + limit_name));
+    }
+
+    if (pos == std::istream_iterator<std::string>())
+      return failure(std::string("missing value after limit: ") + limit_name);
+
+    const std::string value_str = *pos;
+    int value;
+    std::istringstream value_stream(value_str);
+    value_stream >> value;
+    if (value_stream.bad() || !value_stream.eof() || value_stream.fail())
+      return failure(std::string("invalid integer: ") + value_str);
+
+    if (!ignore) limits->push_back({limit, value});
+    ++pos;
+  }
+
+  return true;
+}
+}  // anonymous namespace
diff --git a/glslc/src/resource_parse.h b/glslc/src/resource_parse.h
new file mode 100644
index 0000000..9794ce4
--- /dev/null
+++ b/glslc/src/resource_parse.h
@@ -0,0 +1,60 @@
+// Copyright 2016 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GLSLC_RESOURCE_PARSE_H
+#define GLSLC_RESOURCE_PARSE_H
+
+#include <string>
+#include <vector>
+
+#include "shaderc/shaderc.h"
+
+namespace glslc {
+
+// A resource limit setting.
+struct ResourceSetting {
+  shaderc_limit limit;
+  int value;
+};
+
+
+// Returns true when two resource setting structures are equal.
+inline bool operator==(const ResourceSetting& lhs, const ResourceSetting& rhs) {
+  return (lhs.limit == rhs.limit) && (lhs.value == rhs.value);
+}
+
+
+// Parses a resource limit setting string.  On success, returns true and populates
+// the limits parameter.  On failure returns failure and emits a message to err.
+// The setting string should be a seqeuence of pairs, where each pair
+// is a limit name followed by a decimal integer.  Tokens should be separated
+// by whitespace.  In particular, this function accepts Glslang's configuration
+// file syntax.  If a limit is mentioned multiple times, then the last setting
+// takes effect.  Ignore settings for:
+//   nonInductiveForLoops
+//   whileLoops
+//   doWhileLoops
+//   generalUniformIndexing
+//   generalAttributeMatrixVectorIndexing
+//   generalVaryingIndexing
+//   generalSamplerIndexing
+//   generalVariableIndexing
+//   generalConstantMatrixVectorIndexing
+bool ParseResourceSettings(const std::string& input,
+                           std::vector<ResourceSetting>* limits,
+                           std::string* err);
+}  // namespace glslc
+
+
+#endif  // GLSLC_FILE_H_
diff --git a/glslc/src/resource_parse_test.cc b/glslc/src/resource_parse_test.cc
new file mode 100644
index 0000000..42c877b
--- /dev/null
+++ b/glslc/src/resource_parse_test.cc
@@ -0,0 +1,75 @@
+// Copyright 2017 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "resource_parse.h"
+
+#include <gmock/gmock.h>
+
+namespace {
+
+using glslc::ParseResourceSettings;
+using glslc::ResourceSetting;
+using testing::Eq;
+
+struct ResourceSettingsCase {
+  std::string input;
+  bool success;
+  std::vector<ResourceSetting> settings;
+  std::string message;
+};
+
+using ParseResourceSettingsTest = ::testing::TestWithParam<ResourceSettingsCase>;
+
+TEST_P(ParseResourceSettingsTest, Sample) {
+  std::vector<ResourceSetting> settings;
+  std::string err;
+  const bool succeeded = ParseResourceSettings(GetParam().input, &settings, &err);
+  EXPECT_THAT(succeeded, Eq(GetParam().success));
+  EXPECT_THAT(settings, Eq(GetParam().settings));
+  EXPECT_THAT(err, Eq(GetParam().message));
+}
+
+INSTANTIATE_TEST_CASE_P(ParseResources, ParseResourceSettingsTest,
+  ::testing::ValuesIn(std::vector<ResourceSettingsCase>{
+    {"", true, {}, ""},
+    {"   \t \t \n ", true, {}, ""},
+    {" blorp blam", false, {}, "invalid resource limit: blorp"},
+    {"MaxLightsxyz", false, {}, "invalid resource limit: MaxLightsxyz"},
+    {"MaxLights", false, {}, "missing value after limit: MaxLights"},
+    {"MaxLights x", false, {}, "invalid integer: x"},
+    {"MaxLights 99x", false, {}, "invalid integer: 99x"},
+    {"MaxLights 12 blam", false, {}, "invalid resource limit: blam"},
+    {"MaxLights 12", true, {{shaderc_limit_max_lights, 12}}, ""},
+    // Test negative number
+    {"MinProgramTexelOffset -9", true, {{shaderc_limit_min_program_texel_offset, -9}}, ""},
+    // Test leading, intervening, and trailing whitespace
+    {" \tMaxLights \n 12 \t ", true, {{shaderc_limit_max_lights, 12}}, ""},
+    // Test more than one limit setting.
+    {"MinProgramTexelOffset -10 MaxLights 4", true, {{shaderc_limit_min_program_texel_offset, -10}, {shaderc_limit_max_lights, 4}}, ""},
+    // Check ignore cases.
+    {"nonInductiveForLoops", false, {}, "missing value after limit: nonInductiveForLoops"},
+    {"nonInductiveForLoops 1", true, {}, ""},
+    {"whileLoops 1", true, {}, ""},
+    {"doWhileLoops 1", true, {}, ""},
+    {"generalUniformIndexing 1", true, {}, ""},
+    {"generalAttributeMatrixVectorIndexing 1", true, {}, ""},
+    {"generalVaryingIndexing 1", true, {}, ""},
+    {"generalSamplerIndexing 1", true, {}, ""},
+    {"generalVariableIndexing 1", true, {}, ""},
+    {"generalConstantMatrixVectorIndexing 1", true, {}, ""},
+    // Check an ignore case with a regular case
+    {"whileLoops 1 MaxLights 99", true, {{shaderc_limit_max_lights, 99}}, ""},
+  }), );
+
+}  // anonymous namespace
diff --git a/glslc/test/CMakeLists.txt b/glslc/test/CMakeLists.txt
index bb82a70..cca9314 100644
--- a/glslc/test/CMakeLists.txt
+++ b/glslc/test/CMakeLists.txt
@@ -5,5 +5,6 @@
   add_test(NAME glslc_tests
     COMMAND ${PYTHON_EXE}
     ${CMAKE_CURRENT_SOURCE_DIR}/glslc_test_framework.py
-    $<TARGET_FILE:glslc_exe> --test-dir ${CMAKE_CURRENT_SOURCE_DIR})
+    $<TARGET_FILE:glslc_exe> $<TARGET_FILE:spirv-dis>
+    --test-dir ${CMAKE_CURRENT_SOURCE_DIR})
 endif()
diff --git a/glslc/test/expect.py b/glslc/test/expect.py
index 00e31d4..cfd0524 100644
--- a/glslc/test/expect.py
+++ b/glslc/test/expect.py
@@ -21,6 +21,7 @@
 import difflib
 import os
 import re
+import subprocess
 from glslc_test_framework import GlslCTest
 
 
@@ -212,6 +213,33 @@
         return True, ''
 
 
+class ValidObjectFileWithAssemblySubstr(SuccessfulReturn, CorrectObjectFilePreamble):
+    """Mixin class for checking that every input file generates a valid object
+    file following the object file naming rule, there is no output on
+    stdout/stderr, and the disassmbly contains a specified substring per input."""
+
+    def check_object_file_disassembly(self, status):
+        for an_input in status.inputs:
+            object_filename = get_object_filename(an_input.filename)
+            obj_file = str(os.path.join(status.directory, object_filename))
+            success, message = self.verify_object_file_preamble(obj_file)
+            if not success:
+                return False, message
+            cmd = [status.test_manager.disassembler_path, '--no-color', obj_file]
+            process = subprocess.Popen(
+                args=cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                stderr=subprocess.PIPE, cwd=status.directory)
+            output = process.communicate(None)
+            disassembly = output[0]
+            if not isinstance(an_input.assembly_substr, str):
+                return False, "Missing assembly_substr member"
+            if an_input.assembly_substr not in disassembly:
+                return False, ('Incorrect disassembly output:\n{asm}\n'
+                    'Expected substring not found:\n{exp}'.format(
+                    asm=disassembly, exp=an_input.assembly_substr))
+        return True, ''
+
+
 class ValidNamedObjectFile(SuccessfulReturn, CorrectObjectFilePreamble):
     """Mixin class for checking that a list of object files with the given
     names are correctly generated, and there is no output on stdout/stderr.
@@ -280,6 +308,32 @@
         return True, ''
 
 
+class ValidAssemblyFileWithSubstr(ValidAssemblyFile):
+    """Mixin class for checking that every input file generates a valid assembly
+    file following the assembly file naming rule, there is no output on
+    stdout/stderr, and all assembly files have the given substring specified
+    by expected_assembly_substr.
+
+    To mix in this class, subclasses need to provde expected_assembly_substr
+    as the expected substring.
+    """
+
+    def check_assembly_with_substr(self, status):
+        for input_filename in status.input_filenames:
+            assembly_filename = get_assembly_filename(input_filename)
+            success, message = self.verify_assembly_file_preamble(
+                os.path.join(status.directory, assembly_filename))
+            if not success:
+                return False, message
+            with open(assembly_filename, 'r') as f:
+                content = f.read()
+                if self.expected_assembly_substr not in convert_to_unix_line_endings(content):
+                   return False, ('Incorrect assembly output:\n{asm}\n'
+                                  'Expected substring not found:\n{exp}'.format(
+                                  asm=content, exp=self.expected_assembly_substr))
+        return True, ''
+
+
 class ValidNamedAssemblyFile(SuccessfulReturn, CorrectAssemblyFilePreamble):
     """Mixin class for checking that a list of assembly files with the given
     names are correctly generated, and there is no output on stdout/stderr.
diff --git a/glslc/test/expect_nosetest.py b/glslc/test/expect_nosetest.py
index dc33e4d..567b0a0 100644
--- a/glslc/test/expect_nosetest.py
+++ b/glslc/test/expect_nosetest.py
@@ -41,20 +41,20 @@
 
 def nosetest_stdout_match_regex_has_match():
     test = TestStdoutMatchADotC()
-    status = TestStatus(returncode=0, stdout='0abc1', stderr=None,
-                        directory=None, input_filenames=None)
+    status = TestStatus(test_manager=None, returncode=0, stdout='0abc1',
+                        stderr=None, directory=None, inputs=None, input_filenames=None)
     assert_true(test.check_stdout_match(status)[0])
 
 
 def nosetest_stdout_match_regex_no_match():
     test = TestStdoutMatchADotC()
-    status = TestStatus(returncode=0, stdout='ab', stderr=None,
-                        directory=None, input_filenames=None)
+    status = TestStatus(test_manager=None, returncode=0, stdout='ab',
+                        stderr=None, directory=None, inputs=None, input_filenames=None)
     assert_false(test.check_stdout_match(status)[0])
 
 
 def nosetest_stdout_match_regex_empty_stdout():
     test = TestStdoutMatchADotC()
-    status = TestStatus(returncode=0, stdout='', stderr=None,
-                        directory=None, input_filenames=None)
+    status = TestStatus(test_manager=None, returncode=0, stdout='', stderr=None,
+                        directory=None, inputs=None, input_filenames=None)
     assert_false(test.check_stdout_match(status)[0])
diff --git a/glslc/test/glslc_test_framework.py b/glslc/test/glslc_test_framework.py
index 9454a66..6bf43a7 100755
--- a/glslc/test/glslc_test_framework.py
+++ b/glslc/test/glslc_test_framework.py
@@ -28,7 +28,7 @@
      The transformed list elements are then supplied as glslc arguments.
   3. If the environment member variable exists, its write() method will be
      invoked.
-  4. All expected_* member varibles will be inspected and all placeholders in
+  4. All expected_* member variables will be inspected and all placeholders in
      them will be expanded by calling instantiate_for_expectation() on those
      placeholders. After placeholder expansion, if the expected_* variable is
      a list, its element will be joined together with '' to form a single
@@ -141,12 +141,15 @@
 class TestStatus:
     """A struct for holding run status of a test case."""
 
-    def __init__(self, returncode, stdout, stderr, directory, input_filenames):
+    def __init__(self, test_manager, returncode, stdout, stderr, directory, inputs, input_filenames):
+        self.test_manager = test_manager
         self.returncode = returncode
         self.stdout = stdout
         self.stderr = stderr
         # temporary directory where the test runs
         self.directory = directory
+        # List of inputs, as PlaceHolder objects.
+        self.inputs = inputs
         # the names of input shader files (potentially including paths)
         self.input_filenames = input_filenames
 
@@ -198,8 +201,9 @@
 class TestManager:
     """Manages and runs a set of tests."""
 
-    def __init__(self, executable_path):
+    def __init__(self, executable_path, disassembler_path):
         self.executable_path = executable_path
+        self.disassembler_path = disassembler_path
         self.num_successes = 0
         self.num_failures = 0
         self.num_tests = 0
@@ -236,7 +240,8 @@
     def __init__(self, test, test_manager):
         self.test = test
         self.test_manager = test_manager
-        self.file_shaders = []  # filenames of shader files
+        self.inputs = []  # inputs, as PlaceHolder objects.
+        self.file_shaders = []  # filenames of shader files.
         self.stdin_shader = None  # text to be passed to glslc as stdin
 
     def setUp(self):
@@ -250,8 +255,8 @@
             if isinstance(arg, PlaceHolder) else arg
             for arg in self.test.glslc_args]
         # Get all shader files' names
-        self.file_shaders = [
-            arg.filename for arg in glslc_args if isinstance(arg, PlaceHolder)]
+        self.inputs = [arg for arg in glslc_args if isinstance(arg, PlaceHolder)]
+        self.file_shaders = [arg.filename for arg in self.inputs]
 
         if 'environment' in get_all_variables(self.test):
             self.test.environment.write(self.directory)
@@ -294,8 +299,9 @@
                 cwd=self.directory)
             output = process.communicate(self.stdin_shader)
             test_status = TestStatus(
+                self.test_manager,
                 process.returncode, output[0], output[1],
-                self.directory, self.file_shaders)
+                self.directory, self.inputs, self.file_shaders)
             run_results = [getattr(self.test, test_method)(test_status)
                            for test_method in get_all_test_methods(
                                self.test.__class__)]
@@ -313,6 +319,8 @@
     parser = argparse.ArgumentParser()
     parser.add_argument('glslc', metavar='path/to/glslc', type=str, nargs=1,
                         help='Path to glslc')
+    parser.add_argument('spirvdis', metavar='path/to/glslc', type=str, nargs=1,
+                        help='Path to spirv-dis')
     parser.add_argument('--leave-output', action='store_const', const=1,
                         help='Do not clean up temporary directories')
     parser.add_argument('--test-dir', nargs=1,
@@ -322,7 +330,7 @@
     root_dir = os.getcwd()
     if args.test_dir:
         root_dir = args.test_dir[0]
-    manager = TestManager(args.glslc[0])
+    manager = TestManager(args.glslc[0], args.spirvdis[0])
     if args.leave_output:
         manager.leave_output = True
     for root, _, filenames in os.walk(root_dir):
diff --git a/glslc/test/option_dash_x.py b/glslc/test/option_dash_x.py
index 5e2c5ee..0288017 100644
--- a/glslc/test/option_dash_x.py
+++ b/glslc/test/option_dash_x.py
@@ -17,6 +17,11 @@
 from placeholder import FileShader
 
 MINIMAL_SHADER = "#version 140\nvoid main(){}"
+# This one is valid GLSL but not valid HLSL.
+GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}"
+# This one is valid HLSL but not valid GLSL.
+# Use entry point "main" so we don't have to specify -fentry-point
+HLSL_VERTEX_SHADER = "float4 main() : SV_POSITION { return float4(1.0); }"
 
 @inside_glslc_testsuite('OptionDashX')
 class TestDashXNoArg(expect.ErrorMessage):
@@ -29,14 +34,33 @@
 
 
 @inside_glslc_testsuite('OptionDashX')
-class TestDashXGlsl(expect.ValidObjectFile):
-    """Tests -x glsl."""
+class TestDashXGlslOnGlslShader(expect.ValidObjectFile):
+    """Tests -x glsl on a GLSL shader."""
 
-    shader = FileShader(MINIMAL_SHADER, '.vert')
+    shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
     glslc_args = ['-x', 'glsl', '-c', shader]
 
 
 @inside_glslc_testsuite('OptionDashX')
+class TestDashXGlslOnHlslShader(expect.ErrorMessageSubstr):
+    """Tests -x glsl on an HLSL shader."""
+
+    shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
+    glslc_args = ['-x', 'glsl', '-c', shader]
+    expected_error_substr = ["error: #version: Desktop shaders for Vulkan SPIR-V"
+                             " require version 140 or higher\n"]
+
+
+@inside_glslc_testsuite('OptionDashX')
+class TestDashXHlslOnGlslShader(expect.ErrorMessageSubstr):
+    """Tests -x hlsl on a GLSL shader."""
+
+    shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
+    glslc_args = ['-x', 'hlsl', '-c', shader]
+    expected_error_substr = ["error: 'vec4' : no matching overloaded function found\n"]
+
+
+@inside_glslc_testsuite('OptionDashX')
 class TestDashXWrongParam(expect.ErrorMessage):
     """Tests -x with wrong parameter."""
 
@@ -47,13 +71,25 @@
 
 @inside_glslc_testsuite('OptionDashX')
 class TestMultipleDashX(expect.ValidObjectFile):
-    """Tests that multiple -x glsl works."""
+    """Tests that multiple -x works with a single language."""
 
-    shader = FileShader(MINIMAL_SHADER, '.vert')
+    shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
     glslc_args = ['-c', '-x', 'glsl', '-x', 'glsl', shader, '-x', 'glsl']
 
 
 @inside_glslc_testsuite('OptionDashX')
+class TestMultipleDashXMixedLanguages(expect.ValidObjectFile):
+    """Tests that multiple -x works with different languages."""
+
+    glsl_shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
+    hlsl_shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
+    glslc_args = ['-c', '-x', 'hlsl', hlsl_shader,
+                  '-x', 'glsl', glsl_shader,
+                  '-x', 'hlsl', hlsl_shader,
+                  '-x', 'glsl', glsl_shader]
+
+
+@inside_glslc_testsuite('OptionDashX')
 class TestMultipleDashXCorrectWrong(expect.ErrorMessage):
     """Tests -x glsl -x [wrong-language]."""
 
diff --git a/glslc/test/option_fentry_point.py b/glslc/test/option_fentry_point.py
new file mode 100644
index 0000000..8625732
--- /dev/null
+++ b/glslc/test/option_fentry_point.py
@@ -0,0 +1,113 @@
+# Copyright 2016 The Shaderc Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import expect
+from glslc_test_framework import inside_glslc_testsuite
+from placeholder import FileShader
+
+MINIMAL_SHADER = "#version 140\nvoid main(){}"
+# This one is valid GLSL but not valid HLSL.
+GLSL_VERTEX_SHADER = "#version 140\nvoid main(){ gl_Position = vec4(1.0);}"
+# This one is valid HLSL but not valid GLSL.
+HLSL_VERTEX_SHADER = "float4 EntryPoint() : SV_POSITION { return float4(1.0); }"
+HLSL_VERTEX_SHADER_WITH_MAIN = "float4 main() : SV_POSITION { return float4(1.0); }"
+HLSL_VERTEX_SHADER_WITH_FOOBAR = "float4 Foobar() : SV_POSITION { return float4(1.0); }"
+
+# Expected assembly code within certain shaders.
+ASSEMBLY_ENTRY_POINT = "OpEntryPoint Vertex %EntryPoint \"EntryPoint\""
+ASSEMBLY_MAIN = "OpEntryPoint Vertex %main \"main\""
+ASSEMBLY_FOOBAR = "OpEntryPoint Vertex %Foobar \"Foobar\""
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestEntryPointDefaultsToMainForGlsl(expect.ValidAssemblyFileWithSubstr):
+    """Tests that entry point name defaults to "main" in a GLSL shader."""
+
+    shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
+    glslc_args = ['-S', shader]
+    expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestEntryPointDefaultsToMainForHlsl(expect.ValidAssemblyFileWithSubstr):
+    """Tests that entry point name defaults to "main" in an HLSL shader."""
+
+    shader = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert')
+    glslc_args = ['-x', 'hlsl', '-S', shader]
+    expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointMainOnGlslShader(expect.ValidAssemblyFileWithSubstr):
+    """Tests -fentry-point=main with a GLSL shader."""
+
+    shader = FileShader(GLSL_VERTEX_SHADER, '.vert')
+    glslc_args = ['-fentry-point=main', '-S', shader]
+    expected_assembly_substr = ASSEMBLY_MAIN
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointMainOnHlslShaderNotMatchingSource(expect.ValidObjectFileWithWarning):
+    """Tests -x hlsl on an HLSL shader with -fentry-point=main
+    not matching the source."""
+
+    shader = FileShader(HLSL_VERTEX_SHADER, '.vert')
+    glslc_args = ['-x', 'hlsl', '-fentry-point=main', '-c', shader]
+    expected_warning = [shader,
+                        ': warning: Linking vertex stage: Entry point not found\n'
+                        '1 warning generated.\n']
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointSpecifiedOnHlslShaderInDisassembly(expect.ValidObjectFileWithAssemblySubstr):
+    """Tests -x hlsl on an HLSL shader with -fentry-point=EntryPoint
+    matching source."""
+
+    shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+    glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader]
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointAffectsSubsequentShaderFiles(expect.ValidObjectFileWithAssemblySubstr):
+    """Tests -x hlsl affects several subsequent shader source files."""
+
+    shader1 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+    shader2 = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+    glslc_args = ['-x', 'hlsl', '-fentry-point=EntryPoint', '-c', shader1, shader2]
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointOverridesItself(expect.ValidObjectFileWithAssemblySubstr):
+    """Tests that a later -fentry-point option overrides an earlier use."""
+
+    shader = FileShader(HLSL_VERTEX_SHADER, '.vert', assembly_substr=ASSEMBLY_ENTRY_POINT)
+    glslc_args = ['-x', 'hlsl', '-fentry-point=foobar', '-fentry-point=EntryPoint',
+                  '-c', shader]
+
+
+@inside_glslc_testsuite('OptionFEntryPoint')
+class TestFEntryPointDefaultAndTwoOthers(expect.ValidObjectFileWithAssemblySubstr):
+    """Tests three shaders with different entry point names. The first uses "main"
+    with default entry point processing, and the remaining shaders get their
+    own -fentry-point argument."""
+
+    shaderMain = FileShader(HLSL_VERTEX_SHADER_WITH_MAIN, '.vert',
+                            assembly_substr=ASSEMBLY_MAIN)
+    shaderEntryPoint = FileShader(HLSL_VERTEX_SHADER, '.vert',
+                                  assembly_substr=ASSEMBLY_ENTRY_POINT)
+    shaderFoobar = FileShader(HLSL_VERTEX_SHADER_WITH_FOOBAR, '.vert',
+                              assembly_substr=ASSEMBLY_FOOBAR)
+    glslc_args = ['-x', 'hlsl', '-c', shaderMain,
+                  '-fentry-point=EntryPoint', shaderEntryPoint,
+                  '-fentry-point=Foobar', shaderFoobar]
diff --git a/glslc/test/option_flimit.py b/glslc/test/option_flimit.py
new file mode 100644
index 0000000..0fbfd9d
--- /dev/null
+++ b/glslc/test/option_flimit.py
@@ -0,0 +1,136 @@
+# Copyright 2016 The Shaderc Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import expect
+from environment import File, Directory
+from glslc_test_framework import inside_glslc_testsuite
+from placeholder import FileShader
+
+
+def shader_source_with_tex_offset(offset):
+    """Returns a vertex shader using a texture access with the given offset."""
+
+    return """#version 150
+              uniform sampler1D tex;
+              void main() { vec4 x = textureOffset(tex, 1.0, """ + str(offset) + "); }"
+
+
+def shader_with_tex_offset(offset):
+    """Returns a vertex FileShader using a texture access with the given offset."""
+
+    return FileShader(shader_source_with_tex_offset(offset), ".vert")
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitNoEqual(expect.ErrorMessage):
+    """Tests -flimit without equal."""
+
+    glslc_args = ['-flimit']
+    expected_error = ["glslc: error: unknown argument: '-flimit'\n"]
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqual(expect.ValidObjectFile):
+    """Tests -flimit= with no argument."""
+
+    shader = shader_with_tex_offset(0);
+    glslc_args = ['-c', shader, '-flimit=']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqualMaxOffset(expect.ValidObjectFile):
+    """Tests -flimit= with no argument.  The shader uses max offset."""
+
+    shader = shader_with_tex_offset(7);
+    glslc_args = ['-c', shader, '-flimit=']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqualMinOffset(expect.ValidObjectFile):
+    """Tests -flimit= with no argument.  The shader uses min offset."""
+
+    shader = shader_with_tex_offset(-8);
+    glslc_args = ['-c', shader, '-flimit=']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqualBelowMinOffset(expect.ErrorMessageSubstr):
+    """Tests -flimit= with no argument.  The shader uses below min default offset."""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit=']
+    expected_error_substr = ["'texel offset' : value is out of range"]
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile):
+    """Tests -flimit= with lower than default argument.  The shader uses below min offset."""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 ']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitIgnoredLangFeatureSettingSample(expect.ValidObjectFile):
+    """Tests -flimit= an ignored option."""
+
+    shader = FileShader("#version 150\nvoid main() { while(true); }", '.vert')
+    glslc_args = ['-c', shader, '-flimit=whileLoops 0']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile):
+    """Tests -flimit= with lower than default argument.  The shader uses that offset."""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 ']
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileNoArg(expect.ErrorMessage):
+    """Tests -flimit-file without an argument"""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit-file']
+    expected_error = "glslc: error: argument to '-flimit-file' is missing\n"
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileMissingFile(expect.ErrorMessageSubstr):
+    """Tests -flimit-file without an argument"""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit-file', 'i do not exist']
+    expected_error_substr = "glslc: error: cannot open input file: 'i do not exist'";
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileSetsLowerMinTexelOffset(expect.ValidObjectFile):
+    """Tests -flimit-file with lower than default argument.  The shader uses that offset."""
+
+    limits_file = File('limits.txt', 'MinProgramTexelOffset -9')
+    shader = File('shader.vert', shader_source_with_tex_offset(-9));
+    environment = Directory('.', [limits_file, shader])
+    glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileInvalidContents(expect.ErrorMessage):
+    """Tests -flimit-file bad file contents."""
+
+    limits_file = File('limits.txt', 'thisIsBad')
+    shader = File('shader.vert', shader_source_with_tex_offset(-9));
+    environment = Directory('.', [limits_file, shader])
+    glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
+    expected_error = 'glslc: error: -flimit-file error: invalid resource limit: thisIsBad\n'
diff --git a/glslc/test/option_shader_stage.py b/glslc/test/option_shader_stage.py
index 8e0bcbb..6b2ec0b 100644
--- a/glslc/test/option_shader_stage.py
+++ b/glslc/test/option_shader_stage.py
@@ -24,6 +24,11 @@
     }"""
 
 
+def simple_hlsl_vertex_shader():
+    # Use "main" so we don't have to specify -fentry-point
+    return """float4 main() : SV_POSITION { return float4(1.0); } """
+
+
 def simple_fragment_shader():
     return """#version 310 es
     void main() {
@@ -66,6 +71,14 @@
 
 
 @inside_glslc_testsuite('OptionShaderStage')
+class TestShaderStageWithHlslExtension(expect.ValidObjectFile):
+    """Tests -fshader-stage with .hlsl extension."""
+
+    shader = FileShader(simple_hlsl_vertex_shader(), '.hlsl')
+    glslc_args = ['-c', '-fshader-stage=vertex', shader]
+
+
+@inside_glslc_testsuite('OptionShaderStage')
 class TestShaderStageWithKnownExtension(expect.ValidObjectFile):
     """Tests -fshader-stage with known extension."""
 
@@ -188,6 +201,18 @@
 
 
 @inside_glslc_testsuite('OptionShaderStage')
+class TestShaderStageHlslExtensionMissingShaderStage(expect.ErrorMessage):
+    """Tests that missing -fshader-stage for .hlsl extension results in
+    an error."""
+
+    shader = FileShader(simple_hlsl_vertex_shader(), '.hlsl')
+    glslc_args = ['-c', '-x', 'hlsl', shader]
+    expected_error = [
+        "glslc: error: '", shader,
+        "': .hlsl file encountered but no -fshader-stage specified ahead\n"]
+
+
+@inside_glslc_testsuite('OptionShaderStage')
 class TestShaderStageUnknownExtensionMissingShaderStage(expect.ErrorMessage):
     """Tests that missing -fshader-stage for unknown extension results in
     an error."""
diff --git a/glslc/test/option_std.py b/glslc/test/option_std.py
index 9ad762b..b01d584 100644
--- a/glslc/test/option_std.py
+++ b/glslc/test/option_std.py
@@ -28,6 +28,11 @@
     return 'void main() { int temp = gl_SampleID; }'
 
 
+def hlsl_compute_shader_with_barriers():
+    # Use "main" to avoid the need for -fentry-point
+    return 'void main() { AllMemoryBarrierWithGroupSync(); }'
+
+
 @inside_glslc_testsuite('OptionStd')
 class TestStdNoArg(expect.ErrorMessage):
     """Tests -std alone."""
@@ -72,6 +77,15 @@
 
 
 @inside_glslc_testsuite('OptionStd')
+class TestStdIgnoredInHlsl(expect.ValidObjectFile):
+    """Tests HLSL compilation ignores -std."""
+
+    # Compute shaders are not available in OpenGL 150
+    shader = FileShader(hlsl_compute_shader_with_barriers(), '.comp')
+    glslc_args = ['-c', '-x', 'hlsl', '-std=150', shader]
+
+
+@inside_glslc_testsuite('OptionStd')
 class TestMissingVersionAndWrongStd(expect.ErrorMessage):
     """Tests missing #version and wrong -std results in errors."""
 
diff --git a/glslc/test/parameter_tests.py b/glslc/test/parameter_tests.py
index 235b609..b00d75f 100644
--- a/glslc/test/parameter_tests.py
+++ b/glslc/test/parameter_tests.py
@@ -57,6 +57,17 @@
   -Dmacro[=defn]    Add an implicit macro definition.
   -E                Outputs only the results of the preprocessing step.
                     Output defaults to standard output.
+  -fentry-point=<name>
+                    Specify the entry point name for HLSL compilation, for
+                    all subsequent source files.  Default is "main".
+  -flimit=<settings>
+                    Specify resource limits. Each limit is specified by a limit
+                    name followed by an integer value.  Tokens should be
+                    separated by whitespace.  If the same limit is specified
+                    several times, only the last setting takes effect.
+  --show-limits     Display available limit names and their default values.
+  -flimit-file <file>
+                    Set limits as specified in the given file.
   -fshader-stage=<stage>
                     Treat subsequent input files as having stage <stage>.
                     Valid stages are vertex, fragment, tesscontrol, tesseval,
@@ -68,9 +79,9 @@
   -I <value>        Add directory to include search path.
   -o <file>         Write output to <file>.
                     A file name of '-' represents standard output.
-  -std=<value>      Version and profile for input files. Possible values
+  -std=<value>      Version and profile for GLSL input files. Possible values
                     are concatenations of version and profile, e.g. 310es,
-                    450core, etc.
+                    450core, etc.  Ignored for HLSL files.
   -mfmt=<format>    Output SPIR-V binary code using the selected format. This
                     option may be specified only when the compilation output is
                     in SPIR-V binary code form. Available options include bin, c
@@ -89,7 +100,9 @@
   -w                Suppresses all warning messages.
   -Werror           Treat all warnings as errors.
   -x <language>     Treat subsequent input files as having type <language>.
-                    The only supported language is glsl.
+                    Valid languages are: glsl, hlsl.
+                    For files ending in .hlsl the default is hlsl.
+                    Otherwise the default is glsl.
 '''
 
     expected_stderr = ''
@@ -177,3 +190,96 @@
     expected_stderr = [
         "glslc: error: '-': -fshader-stage required when input is from "
         'standard input "-"\n']
+
+
+@inside_glslc_testsuite('Parameters')
+class LimitsHelp(expect.StdoutMatch, expect.StderrMatch):
+    """Tests --show-limits shows correct output."""
+
+    glslc_args = ['--show-limits']
+
+    expected_stderr = ''
+    expected_stdout = """MaxLights 8
+MaxClipPlanes 6
+MaxTextureUnits 2
+MaxTextureCoords 8
+MaxVertexAttribs 16
+MaxVertexUniformComponents 4096
+MaxVaryingFloats 60
+MaxVertexTextureImageUnits 16
+MaxCombinedTextureImageUnits 80
+MaxTextureImageUnits 16
+MaxFragmentUniformComponents 1024
+MaxDrawBuffers 2
+MaxVertexUniformVectors 256
+MaxVaryingVectors 15
+MaxFragmentUniformVectors 256
+MaxVertexOutputVectors 16
+MaxFragmentInputVectors 15
+MinProgramTexelOffset -8
+MaxProgramTexelOffset 7
+MaxClipDistances 8
+MaxComputeWorkGroupCountX 65535
+MaxComputeWorkGroupCountY 65535
+MaxComputeWorkGroupCountZ 65535
+MaxComputeWorkGroupSizeX 1024
+MaxComputeWorkGroupSizeY 1024
+MaxComputeWorkGroupSizeZ 64
+MaxComputeUniformComponents 512
+MaxComputeTextureImageUnits 16
+MaxComputeImageUniforms 8
+MaxComputeAtomicCounters 8
+MaxComputeAtomicCounterBuffers 1
+MaxVaryingComponents 60
+MaxVertexOutputComponents 64
+MaxGeometryInputComponents 64
+MaxGeometryOutputComponents 128
+MaxFragmentInputComponents 128
+MaxImageUnits 8
+MaxCombinedImageUnitsAndFragmentOutputs 8
+MaxCombinedShaderOutputResources 8
+MaxImageSamples 0
+MaxVertexImageUniforms 0
+MaxTessControlImageUniforms 0
+MaxTessEvaluationImageUniforms 0
+MaxGeometryImageUniforms 0
+MaxFragmentImageUniforms 8
+MaxCombinedImageUniforms 8
+MaxGeometryTextureImageUnits 16
+MaxGeometryOutputVertices 256
+MaxGeometryTotalOutputComponents 1024
+MaxGeometryUniformComponents 512
+MaxGeometryVaryingComponents 60
+MaxTessControlInputComponents 128
+MaxTessControlOutputComponents 128
+MaxTessControlTextureImageUnits 16
+MaxTessControlUniformComponents 1024
+MaxTessControlTotalOutputComponents 4096
+MaxTessEvaluationInputComponents 128
+MaxTessEvaluationOutputComponents 128
+MaxTessEvaluationTextureImageUnits 16
+MaxTessEvaluationUniformComponents 1024
+MaxTessPatchComponents 120
+MaxPatchVertices 32
+MaxTessGenLevel 64
+MaxViewports 16
+MaxVertexAtomicCounters 0
+MaxTessControlAtomicCounters 0
+MaxTessEvaluationAtomicCounters 0
+MaxGeometryAtomicCounters 0
+MaxFragmentAtomicCounters 8
+MaxCombinedAtomicCounters 8
+MaxAtomicCounterBindings 1
+MaxVertexAtomicCounterBuffers 0
+MaxTessControlAtomicCounterBuffers 0
+MaxTessEvaluationAtomicCounterBuffers 0
+MaxGeometryAtomicCounterBuffers 0
+MaxFragmentAtomicCounterBuffers 0
+MaxCombinedAtomicCounterBuffers 1
+MaxAtomicCounterBufferSize 32
+MaxTransformFeedbackBuffers 4
+MaxTransformFeedbackInterleavedComponents 64
+MaxCullDistances 8
+MaxCombinedClipAndCullDistances 8
+MaxSamples 4
+"""
diff --git a/glslc/test/placeholder.py b/glslc/test/placeholder.py
index 9c5bcfc..8a701bf 100644
--- a/glslc/test/placeholder.py
+++ b/glslc/test/placeholder.py
@@ -59,12 +59,15 @@
 class FileShader(PlaceHolder):
     """Stands for a shader whose source code is in a file."""
 
-    def __init__(self, source, suffix):
+    def __init__(self, source, suffix, assembly_substr=None):
         assert isinstance(source, str)
         assert isinstance(suffix, str)
         self.source = source
         self.suffix = suffix
         self.filename = None
+        # If provided, this is a substring which is expected to be in
+        # the disassembly of the module generated from this input file.
+        self.assembly_substr = assembly_substr
 
     def instantiate_for_glslc_args(self, testcase):
         """Creates a temporary file and writes the source into it.
diff --git a/libshaderc/CMakeLists.txt b/libshaderc/CMakeLists.txt
index 59ff932..888c858 100644
--- a/libshaderc/CMakeLists.txt
+++ b/libshaderc/CMakeLists.txt
@@ -23,7 +23,7 @@
 shaderc_add_tests(
   TEST_PREFIX shaderc
   LINK_LIBS shaderc
-  INCLUDE_DIRS include ${glslang_SOURCE_DIR}
+  INCLUDE_DIRS include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include
   TEST_NAMES
     shaderc
     shaderc_cpp)
@@ -34,7 +34,7 @@
 shaderc_add_tests(
   TEST_PREFIX shaderc_combined
   LINK_LIBS shaderc_combined ${CMAKE_THREAD_LIBS_INIT}
-  INCLUDE_DIRS include ${glslang_SOURCE_DIR}
+  INCLUDE_DIRS include ${glslang_SOURCE_DIR} ${spirv-tools_SOURCE_DIR}/include
   TEST_NAMES
     shaderc
     shaderc_cpp)
diff --git a/libshaderc/README.md b/libshaderc/README.md
index d5e9ec3..bf9d317 100644
--- a/libshaderc/README.md
+++ b/libshaderc/README.md
@@ -5,10 +5,10 @@
 ## Build Artifacts
 
 There are two main shaderc libraries that are created during a CMake
-compilation. The first is `libshaderc`, which is a static library 
-containing just the functionality exposed by libshaderc. It depends 
+compilation. The first is `libshaderc`, which is a static library
+containing just the functionality exposed by libshaderc. It depends
 on other compilation targets `glslang`, `OSDependent`, `OGLCompiler`,
-`shaderc_util` and `SPIRV`.
+`shaderc_util`, `SPIRV`, `HLSL`, `SPIRV-Tools`, and `SPIRV-Tools-opt`.
 
 The other is `libshaderc_combined`, which is a static library containing
 libshaderc and all of its dependencies.
@@ -34,15 +34,18 @@
 platforms `-lpthread` should also be specified.
 
 4. If the external project does not use CMake and cannot use
-libshaderc_combined, the following libraries or their platform-dependent
+`libshaderc_combined`, the following libraries or their platform-dependent
 counterparts should be linked in the order specified.
- `build/libshaderc/libshaderc.a`  
- `build/third_party/glslang/glslang/glslang.a`  
- `build/third_party/glslang/glslang/OSDependent/{Platform}/libOSDependent.a`  
- `build/third_party/glslang/OGLCompilersDLL/libOGLCompiler.a`  
- `build/third_party/glslang/libglslang.a`  
- `build/shaderc_util/libshaderc_util.a`  
- `build/third_party/glslang/SPIRV/libSPIRV.a`
+  * `build/libshaderc/libshaderc.a`
+  * `build/third_party/glslang/glslang/glslang.a`
+  * `build/third_party/glslang/glslang/OSDependent/{Platform}/libOSDependent.a`
+  * `build/third_party/glslang/OGLCompilersDLL/libOGLCompiler.a`
+  * `build/third_party/glslang/libglslang.a`
+  * `build/shaderc_util/libshaderc_util.a`
+  * `build/third_party/glslang/SPIRV/libSPIRV.a`
+  * `build/third_party/glslang/hlsl/libHLSL.a`
+  * `build/third_party/spirv-tools/libSPIRV-Tools-opt.a`
+  * `build/third_party/spirv-tools/libSPIRV-Tools.a`
 
 5. If building for Android using the Android NDK, `shaderc/Android.mk` can be
 included in the application's `Android.mk` and `LOCAL_STATIC_LIBRARIES:=shaderc`
diff --git a/libshaderc/include/shaderc/shaderc.h b/libshaderc/include/shaderc/shaderc.h
index 46d98b4..26d5421 100644
--- a/libshaderc/include/shaderc/shaderc.h
+++ b/libshaderc/include/shaderc/shaderc.h
@@ -23,6 +23,12 @@
 #include <stddef.h>
 #include <stdint.h>
 
+// Source language kind.
+typedef enum {
+  shaderc_source_language_glsl,
+  shaderc_source_language_hlsl,
+} shaderc_source_language;
+
 typedef enum {
   // Forced shader kinds. These shader kinds force the compiler to compile the
   // source code as the specified kind of shader.
@@ -80,6 +86,93 @@
   shaderc_optimization_level_size,  // optimize towards reducing code size
 } shaderc_optimization_level;
 
+// Resource limits.
+typedef enum {
+  shaderc_limit_max_lights,
+  shaderc_limit_max_clip_planes,
+  shaderc_limit_max_texture_units,
+  shaderc_limit_max_texture_coords,
+  shaderc_limit_max_vertex_attribs,
+  shaderc_limit_max_vertex_uniform_components,
+  shaderc_limit_max_varying_floats,
+  shaderc_limit_max_vertex_texture_image_units,
+  shaderc_limit_max_combined_texture_image_units,
+  shaderc_limit_max_texture_image_units,
+  shaderc_limit_max_fragment_uniform_components,
+  shaderc_limit_max_draw_buffers,
+  shaderc_limit_max_vertex_uniform_vectors,
+  shaderc_limit_max_varying_vectors,
+  shaderc_limit_max_fragment_uniform_vectors,
+  shaderc_limit_max_vertex_output_vectors,
+  shaderc_limit_max_fragment_input_vectors,
+  shaderc_limit_min_program_texel_offset,
+  shaderc_limit_max_program_texel_offset,
+  shaderc_limit_max_clip_distances,
+  shaderc_limit_max_compute_work_group_count_x,
+  shaderc_limit_max_compute_work_group_count_y,
+  shaderc_limit_max_compute_work_group_count_z,
+  shaderc_limit_max_compute_work_group_size_x,
+  shaderc_limit_max_compute_work_group_size_y,
+  shaderc_limit_max_compute_work_group_size_z,
+  shaderc_limit_max_compute_uniform_components,
+  shaderc_limit_max_compute_texture_image_units,
+  shaderc_limit_max_compute_image_uniforms,
+  shaderc_limit_max_compute_atomic_counters,
+  shaderc_limit_max_compute_atomic_counter_buffers,
+  shaderc_limit_max_varying_components,
+  shaderc_limit_max_vertex_output_components,
+  shaderc_limit_max_geometry_input_components,
+  shaderc_limit_max_geometry_output_components,
+  shaderc_limit_max_fragment_input_components,
+  shaderc_limit_max_image_units,
+  shaderc_limit_max_combined_image_units_and_fragment_outputs,
+  shaderc_limit_max_combined_shader_output_resources,
+  shaderc_limit_max_image_samples,
+  shaderc_limit_max_vertex_image_uniforms,
+  shaderc_limit_max_tess_control_image_uniforms,
+  shaderc_limit_max_tess_evaluation_image_uniforms,
+  shaderc_limit_max_geometry_image_uniforms,
+  shaderc_limit_max_fragment_image_uniforms,
+  shaderc_limit_max_combined_image_uniforms,
+  shaderc_limit_max_geometry_texture_image_units,
+  shaderc_limit_max_geometry_output_vertices,
+  shaderc_limit_max_geometry_total_output_components,
+  shaderc_limit_max_geometry_uniform_components,
+  shaderc_limit_max_geometry_varying_components,
+  shaderc_limit_max_tess_control_input_components,
+  shaderc_limit_max_tess_control_output_components,
+  shaderc_limit_max_tess_control_texture_image_units,
+  shaderc_limit_max_tess_control_uniform_components,
+  shaderc_limit_max_tess_control_total_output_components,
+  shaderc_limit_max_tess_evaluation_input_components,
+  shaderc_limit_max_tess_evaluation_output_components,
+  shaderc_limit_max_tess_evaluation_texture_image_units,
+  shaderc_limit_max_tess_evaluation_uniform_components,
+  shaderc_limit_max_tess_patch_components,
+  shaderc_limit_max_patch_vertices,
+  shaderc_limit_max_tess_gen_level,
+  shaderc_limit_max_viewports,
+  shaderc_limit_max_vertex_atomic_counters,
+  shaderc_limit_max_tess_control_atomic_counters,
+  shaderc_limit_max_tess_evaluation_atomic_counters,
+  shaderc_limit_max_geometry_atomic_counters,
+  shaderc_limit_max_fragment_atomic_counters,
+  shaderc_limit_max_combined_atomic_counters,
+  shaderc_limit_max_atomic_counter_bindings,
+  shaderc_limit_max_vertex_atomic_counter_buffers,
+  shaderc_limit_max_tess_control_atomic_counter_buffers,
+  shaderc_limit_max_tess_evaluation_atomic_counter_buffers,
+  shaderc_limit_max_geometry_atomic_counter_buffers,
+  shaderc_limit_max_fragment_atomic_counter_buffers,
+  shaderc_limit_max_combined_atomic_counter_buffers,
+  shaderc_limit_max_atomic_counter_buffer_size,
+  shaderc_limit_max_transform_feedback_buffers,
+  shaderc_limit_max_transform_feedback_interleaved_components,
+  shaderc_limit_max_cull_distances,
+  shaderc_limit_max_combined_clip_and_cull_distances,
+  shaderc_limit_max_samples,
+} shaderc_limit;
+
 // Usage examples:
 //
 // Aggressively release compiler resources, but spend time in initialization
@@ -158,6 +251,10 @@
     shaderc_compile_options_t options, const char* name, size_t name_length,
     const char* value, size_t value_length);
 
+// Sets the source language.  The default is GLSL.
+void shaderc_compile_options_set_source_language(
+    shaderc_compile_options_t options, shaderc_source_language lang);
+
 // Sets the compiler mode to generate debug information in the output.
 void shaderc_compile_options_set_generate_debug_info(
     shaderc_compile_options_t options);
@@ -245,6 +342,10 @@
 void shaderc_compile_options_set_warnings_as_errors(
     shaderc_compile_options_t options);
 
+// Sets a resource limit.
+void shaderc_compile_options_set_limit(
+    shaderc_compile_options_t options, shaderc_limit limit, int value);
+
 // An opaque handle to the results of a call to any shaderc_compile_into_*()
 // function.
 typedef struct shaderc_compilation_result* shaderc_compilation_result_t;
diff --git a/libshaderc/include/shaderc/shaderc.hpp b/libshaderc/include/shaderc/shaderc.hpp
index 4e5dfd7..3023ebb 100644
--- a/libshaderc/include/shaderc/shaderc.hpp
+++ b/libshaderc/include/shaderc/shaderc.hpp
@@ -221,6 +221,11 @@
     shaderc_compile_options_set_suppress_warnings(options_);
   }
 
+  // Sets the source language. The default is GLSL.
+  void SetSourceLanguage(shaderc_source_language lang) {
+    shaderc_compile_options_set_source_language(options_, lang);
+  }
+
   // Sets the target shader environment, affecting which warnings or errors will
   // be issued.
   // The version will be for distinguishing between different versions of the
@@ -238,6 +243,11 @@
     shaderc_compile_options_set_warnings_as_errors(options_);
   }
 
+  // Sets a resource limit.
+  void SetLimit(shaderc_limit limit, int value) {
+    shaderc_compile_options_set_limit(options_, limit, value);
+  }
+
  private:
   CompileOptions& operator=(const CompileOptions& other) = delete;
   shaderc_compile_options_t options_;
@@ -274,6 +284,9 @@
   // The input_file_name is a null-termintated string. It is used as a tag to
   // identify the source string in cases like emitting error messages. It
   // doesn't have to be a 'file name'.
+  // The entry_point_name parameter is a null-terminated string specifying
+  // the entry point name for HLSL compilation.  For GLSL compilation, the
+  // entry point name is assumed to be "main".
   // The compilation is passed any options specified in the CompileOptions
   // parameter.
   // It is valid for the returned CompilationResult object to outlive this
@@ -285,16 +298,30 @@
                                         size_t source_text_size,
                                         shaderc_shader_kind shader_kind,
                                         const char* input_file_name,
+                                        const char* entry_point_name,
                                         const CompileOptions& options) const {
     shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv(
         compiler_, source_text, source_text_size, shader_kind, input_file_name,
-        "main", options.options_);
+        entry_point_name, options.options_);
     return SpvCompilationResult(compilation_result);
   }
 
+  // Compiles the given source shader and returns a SPIR-V binary module
+  // compilation result.
+  // Like the first CompileGlslToSpv method but assumes the entry point name
+  // is "main".
+  SpvCompilationResult CompileGlslToSpv(const char* source_text,
+                                        size_t source_text_size,
+                                        shaderc_shader_kind shader_kind,
+                                        const char* input_file_name,
+                                        const CompileOptions& options) const {
+    return CompileGlslToSpv(source_text, source_text_size, shader_kind,
+                            input_file_name, "main", options);
+  }
+
   // Compiles the given source GLSL and returns a SPIR-V binary module
   // compilation result.
-  // Like the first CompileGlslToSpv method but uses default options.
+  // Like the previous CompileGlslToSpv method but uses default options.
   SpvCompilationResult CompileGlslToSpv(const char* source_text,
                                         size_t source_text_size,
                                         shaderc_shader_kind shader_kind,
@@ -305,10 +332,10 @@
     return SpvCompilationResult(compilation_result);
   }
 
-  // Compiles the given source GLSL and returns a SPIR-V binary module
+  // Compiles the given source shader and returns a SPIR-V binary module
   // compilation result.
   // Like the first CompileGlslToSpv method but the source is provided as
-  // a std::string.
+  // a std::string, and we assume the entry point is "main".
   SpvCompilationResult CompileGlslToSpv(const std::string& source_text,
                                         shaderc_shader_kind shader_kind,
                                         const char* input_file_name,
@@ -317,10 +344,23 @@
                             input_file_name, options);
   }
 
-  // Compiles the given source GLSL and returns a SPIR-V binary module
+  // Compiles the given source shader and returns a SPIR-V binary module
   // compilation result.
   // Like the first CompileGlslToSpv method but the source is provided as
-  // a std::string and also uses default compiler options.
+  // a std::string.
+  SpvCompilationResult CompileGlslToSpv(const std::string& source_text,
+                                        shaderc_shader_kind shader_kind,
+                                        const char* input_file_name,
+                                        const char* entry_point_name,
+                                        const CompileOptions& options) const {
+    return CompileGlslToSpv(source_text.data(), source_text.size(), shader_kind,
+                            input_file_name, entry_point_name, options);
+  }
+
+  // Compiles the given source GLSL and returns a SPIR-V binary module
+  // compilation result.
+  // Like the previous CompileGlslToSpv method but assumes the entry point
+  // name is "main".
   SpvCompilationResult CompileGlslToSpv(const std::string& source_text,
                                         shaderc_shader_kind shader_kind,
                                         const char* input_file_name) const {
@@ -378,23 +418,46 @@
   AssemblyCompilationResult CompileGlslToSpvAssembly(
       const char* source_text, size_t source_text_size,
       shaderc_shader_kind shader_kind, const char* input_file_name,
-      const CompileOptions& options) const {
+      const char* entry_point_name, const CompileOptions& options) const {
     shaderc_compilation_result_t compilation_result =
         shaderc_compile_into_spv_assembly(
             compiler_, source_text, source_text_size, shader_kind,
-            input_file_name, "main", options.options_);
+            input_file_name, entry_point_name, options.options_);
     return AssemblyCompilationResult(compilation_result);
   }
 
   // Compiles the given source GLSL and returns the SPIR-V assembly text
+  // compilation result.
+  // Similare to the previous method, but assumes entry point name is "main".
+  AssemblyCompilationResult CompileGlslToSpvAssembly(
+      const char* source_text, size_t source_text_size,
+      shaderc_shader_kind shader_kind, const char* input_file_name,
+      const CompileOptions& options) const {
+    return CompileGlslToSpvAssembly(source_text, source_text_size, shader_kind,
+                                    input_file_name, "main", options);
+  }
+
+  // Compiles the given source GLSL and returns the SPIR-V assembly text
   // result. Like the first CompileGlslToSpvAssembly method but the source
   // is provided as a std::string.  Options are otherwise similar to
   // the first CompileToSpv method.
   AssemblyCompilationResult CompileGlslToSpvAssembly(
       const std::string& source_text, shaderc_shader_kind shader_kind,
-      const char* input_file_name, const CompileOptions& options) const {
+      const char* input_file_name, const char* entry_point_name,
+      const CompileOptions& options) const {
     return CompileGlslToSpvAssembly(source_text.data(), source_text.size(),
-                                    shader_kind, input_file_name, options);
+                                    shader_kind, input_file_name,
+                                    entry_point_name, options);
+  }
+
+  // Compiles the given source GLSL and returns the SPIR-V assembly text
+  // result. Like the previous  CompileGlslToSpvAssembly method but assumes
+  // the entry point name is "main".
+  AssemblyCompilationResult CompileGlslToSpvAssembly(
+      const std::string& source_text, shaderc_shader_kind shader_kind,
+      const char* input_file_name, const CompileOptions& options) const {
+    return CompileGlslToSpvAssembly(source_text, shader_kind, input_file_name,
+                                    "main", options);
   }
 
   // Preprocesses the given source GLSL and returns the preprocessed
diff --git a/libshaderc/src/common_shaders_for_test.h b/libshaderc/src/common_shaders_for_test.h
index d25c6bf..a0120a2 100644
--- a/libshaderc/src/common_shaders_for_test.h
+++ b/libshaderc/src/common_shaders_for_test.h
@@ -25,6 +25,9 @@
 const char kMinimalShader[] =
     "#version 140\n"
     "void main(){}";
+const char kMinimalHlslShader[] =
+    "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n"
+    "{ return float4(1.0, 2.0, 3.0, 4.0); }";
 const char kMinimalShaderWithMacro[] =
     "#version 140\n"
     "#define E main\n"
diff --git a/libshaderc/src/shaderc.cc b/libshaderc/src/shaderc.cc
index 4702608..c7b6ef2 100644
--- a/libshaderc/src/shaderc.cc
+++ b/libshaderc/src/shaderc.cc
@@ -238,6 +238,20 @@
   return shaderc_util::Compiler::TargetEnv::Vulkan;
 }
 
+// Returns the Compiler::Limit enum for the given shaderc_limit enum.
+shaderc_util::Compiler::Limit CompilerLimit(shaderc_limit limit) {
+  switch (limit) {
+#define RESOURCE(NAME,FIELD,CNAME) \
+     case shaderc_limit_##CNAME: return shaderc_util::Compiler::Limit::NAME;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+    default:
+      break;
+  }
+  assert(0 && "Should not have reached here");
+  return static_cast<shaderc_util::Compiler::Limit>(0);
+}
+
 }  // anonymous namespace
 
 struct shaderc_compile_options {
@@ -270,6 +284,15 @@
   options->compiler.AddMacroDefinition(name, name_length, value, value_length);
 }
 
+void shaderc_compile_options_set_source_language(
+    shaderc_compile_options_t options,
+    shaderc_source_language set_lang) {
+  auto lang = shaderc_util::Compiler::SourceLanguage::GLSL;
+  if (set_lang == shaderc_source_language_hlsl)
+    lang = shaderc_util::Compiler::SourceLanguage::HLSL;
+  options->compiler.SetSourceLanguage(lang);
+}
+
 void shaderc_compile_options_set_generate_debug_info(
     shaderc_compile_options_t options) {
   options->compiler.SetGenerateDebugInfo();
@@ -337,9 +360,14 @@
   options->compiler.SetWarningsAsErrors();
 }
 
+void shaderc_compile_options_set_limit(
+    shaderc_compile_options_t options, shaderc_limit limit, int value) {
+  options->compiler.SetLimit(CompilerLimit(limit), value);
+}
+
 shaderc_compiler_t shaderc_compiler_initialize() {
-  static shaderc_util::GlslInitializer* initializer =
-      new shaderc_util::GlslInitializer;
+  static shaderc_util::GlslangInitializer* initializer =
+      new shaderc_util::GlslangInitializer;
   shaderc_compiler_t compiler = new (std::nothrow) shaderc_compiler;
   compiler->initializer = initializer;
   return compiler;
@@ -385,7 +413,7 @@
       std::tie(compilation_succeeded, compilation_output_data,
                compilation_output_data_size_in_bytes) =
           additional_options->compiler.Compile(
-              source_string, forced_stage, input_file_name_str,
+              source_string, forced_stage, input_file_name_str, entry_point_name,
               // stage_deducer has a flag: error_, which we need to check later.
               // We need to make this a reference wrapper, so that std::function
               // won't make a copy for this callable object.
@@ -397,7 +425,7 @@
       std::tie(compilation_succeeded, compilation_output_data,
                compilation_output_data_size_in_bytes) =
           shaderc_util::Compiler().Compile(
-              source_string, forced_stage, input_file_name_str,
+              source_string, forced_stage, input_file_name_str, entry_point_name,
               std::ref(stage_deducer), includer, output_type, &errors,
               &total_warnings, &total_errors, compiler->initializer);
     }
diff --git a/libshaderc/src/shaderc_cpp_test.cc b/libshaderc/src/shaderc_cpp_test.cc
index 521f109..bf5aa33 100644
--- a/libshaderc/src/shaderc_cpp_test.cc
+++ b/libshaderc/src/shaderc_cpp_test.cc
@@ -19,6 +19,7 @@
 #include <unordered_map>
 
 #include "SPIRV/spirv.hpp"
+#include "spirv-tools/libspirv.hpp"
 
 #include "common_shaders_for_test.h"
 #include "shaderc/shaderc.hpp"
@@ -1015,4 +1016,136 @@
   EXPECT_THAT(string_via_begin_end, Eq(forced_to_be_a_string));
 }
 
+TEST_F(CppInterface, SourceLangGlslMinimalGlslVertexShaderSucceeds) {
+  options_.SetSourceLanguage(shaderc_source_language_glsl);
+  EXPECT_TRUE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader,
+                                 options_));
+}
+
+TEST_F(CppInterface, SourceLangGlslMinimalHlslVertexShaderFails) {
+  options_.SetSourceLanguage(shaderc_source_language_glsl);
+  EXPECT_FALSE(CompilationSuccess(kMinimalHlslShader,
+                                  shaderc_glsl_vertex_shader, options_));
+}
+
+TEST_F(CppInterface, SourceLangHlslMinimalGlslVertexShaderFails) {
+  options_.SetSourceLanguage(shaderc_source_language_hlsl);
+  EXPECT_FALSE(CompilationSuccess(kVertexOnlyShader, shaderc_glsl_vertex_shader,
+                                  options_));
+}
+
+TEST_F(CppInterface, SourceLangHlslMinimalHlslVertexShaderSucceeds) {
+  options_.SetSourceLanguage(shaderc_source_language_hlsl);
+  EXPECT_TRUE(CompilationSuccess(kMinimalHlslShader, shaderc_glsl_vertex_shader,
+                                 options_));
+}
+
+TEST(
+    EntryPointTest,
+    SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsWithEntryPointName) {
+  shaderc::Compiler compiler;
+  CompileOptions options;
+  options.SetSourceLanguage(shaderc_source_language_hlsl);
+  auto result = compiler.CompileGlslToSpv(
+      kMinimalHlslShader, strlen(kMinimalHlslShader),
+      shaderc_glsl_vertex_shader, "shader", "EntryPoint", options);
+  std::vector<uint32_t> binary(result.begin(), result.end());
+  std::string assembly;
+  spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly);
+  EXPECT_THAT(assembly,
+              HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
+      << assembly;
+}
+
+TEST(
+    EntryPointTest,
+    SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsWithEntryPointName) {
+  shaderc::Compiler compiler;
+  CompileOptions options;
+  options.SetSourceLanguage(shaderc_source_language_hlsl);
+  std::string shader(kMinimalHlslShader);
+  auto result = compiler.CompileGlslToSpv(shader, shaderc_glsl_vertex_shader,
+                                          "shader", "EntryPoint", options);
+  std::vector<uint32_t> binary(result.begin(), result.end());
+  std::string assembly;
+  spvtools::SpirvTools(SPV_ENV_UNIVERSAL_1_0).Disassemble(binary, &assembly);
+  EXPECT_THAT(assembly,
+              HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
+      << assembly;
+}
+
+TEST(
+    EntryPointTest,
+    SourceLangHlslMinimalHlslVertexShaderAsConstCharPtrSucceedsToAssemblyWithEntryPointName) {
+  shaderc::Compiler compiler;
+  CompileOptions options;
+  options.SetSourceLanguage(shaderc_source_language_hlsl);
+  auto assembly = compiler.CompileGlslToSpvAssembly(
+      kMinimalHlslShader, strlen(kMinimalHlslShader),
+      shaderc_glsl_vertex_shader, "shader", "EntryPoint", options);
+  EXPECT_THAT(std::string(assembly.begin(), assembly.end()),
+              HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""));
+}
+
+TEST(
+    EntryPointTest,
+    SourceLangHlslMinimalHlslVertexShaderAsStdStringSucceedsToAssemblyWithEntryPointName) {
+  shaderc::Compiler compiler;
+  CompileOptions options;
+  options.SetSourceLanguage(shaderc_source_language_hlsl);
+  std::string shader(kMinimalHlslShader);
+  auto assembly = compiler.CompileGlslToSpvAssembly(
+      shader, shaderc_glsl_vertex_shader, "shader", "EntryPoint", options);
+  EXPECT_THAT(std::string(assembly.begin(), assembly.end()),
+              HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""));
+}
+
+// Returns a fragment shader accessing a texture with the given
+// offset.
+std::string ShaderWithTexOffset(int offset) {
+  std::ostringstream oss;
+  oss <<
+    "#version 150\n"
+    "uniform sampler1D tex;\n"
+    "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n";
+  return oss.str();
+}
+
+// Ensure compilation is sensitive to limit setting.  Sample just
+// two particular limits.
+TEST_F(CppInterface, LimitsTexelOffsetDefault) {
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_));
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_));
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_));
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_));
+}
+
+TEST_F(CppInterface, LimitsTexelOffsetLowerMinimum) {
+  options_.SetLimit(shaderc_limit_min_program_texel_offset, -99);
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_));
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_));
+}
+
+TEST_F(CppInterface, LimitsTexelOffsetHigherMaximum) {
+  options_.SetLimit(shaderc_limit_max_program_texel_offset, 10);
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_));
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_));
+}
+
 }  // anonymous namespace
diff --git a/libshaderc/src/shaderc_private.h b/libshaderc/src/shaderc_private.h
index a11d449..de8fd07 100644
--- a/libshaderc/src/shaderc_private.h
+++ b/libshaderc/src/shaderc_private.h
@@ -84,11 +84,11 @@
 };
 
 namespace shaderc_util {
-class GlslInitializer;
+class GlslangInitializer;
 }
 
 struct shaderc_compiler {
-  shaderc_util::GlslInitializer* initializer;
+  shaderc_util::GlslangInitializer* initializer;
 };
 
 #endif  // LIBSHADERC_SRC_SHADERC_PRIVATE_H_
diff --git a/libshaderc/src/shaderc_test.cc b/libshaderc/src/shaderc_test.cc
index c14b9c3..927a53d 100644
--- a/libshaderc/src/shaderc_test.cc
+++ b/libshaderc/src/shaderc_test.cc
@@ -72,43 +72,49 @@
 };
 
 // Generate a compilation result object with the given compile,
-// shader source, shader kind, input file name, options, and for the
-// specified output type.
+// shader source, shader kind, input file name, entry point name, options,
+// and for the specified output type.  The entry point name is only significant
+// for HLSL compilation.
 shaderc_compilation_result_t MakeCompilationResult(
     const shaderc_compiler_t compiler, const std::string& shader,
     shaderc_shader_kind kind, const char* input_file_name,
-    const shaderc_compile_options_t options, OutputType output_type) {
+    const char* entry_point_name, const shaderc_compile_options_t options,
+    OutputType output_type) {
   switch (output_type) {
     case OutputType::SpirvBinary:
       return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(),
-                                      kind, input_file_name, "", options);
+                                      kind, input_file_name, entry_point_name,
+                                      options);
       break;
     case OutputType::SpirvAssemblyText:
-      return shaderc_compile_into_spv_assembly(compiler, shader.c_str(),
-                                               shader.size(), kind,
-                                               input_file_name, "", options);
+      return shaderc_compile_into_spv_assembly(
+          compiler, shader.c_str(), shader.size(), kind, input_file_name,
+          entry_point_name, options);
       break;
     case OutputType::PreprocessedText:
       return shaderc_compile_into_preprocessed_text(
-          compiler, shader.c_str(), shader.size(), kind, input_file_name, "",
-          options);
+          compiler, shader.c_str(), shader.size(), kind, input_file_name,
+          entry_point_name, options);
       break;
   }
   // We shouldn't reach here.  But some compilers might not know that.
   // Be a little defensive and produce something.
   return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind,
-                                  input_file_name, "", options);
+                                  input_file_name, entry_point_name, options);
 }
+
 // RAII class for shaderc_compilation_result. Used for shader compilation.
 class Compilation {
  public:
   // Compiles shader and keeps the result.
   Compilation(const shaderc_compiler_t compiler, const std::string& shader,
               shaderc_shader_kind kind, const char* input_file_name,
+              const char* entry_point_name,
               const shaderc_compile_options_t options = nullptr,
               OutputType output_type = OutputType::SpirvBinary)
-      : compiled_result_(MakeCompilationResult(
-            compiler, shader, kind, input_file_name, options, output_type)) {}
+      : compiled_result_(
+            MakeCompilationResult(compiler, shader, kind, input_file_name,
+                                  entry_point_name, options, output_type)) {}
 
   ~Compilation() { shaderc_result_release(compiled_result_); }
 
@@ -155,6 +161,17 @@
   shaderc_compiler_t compiler;
 };
 
+// RAII class for shader_compiler_options_t
+class Options {
+ public:
+  Options() : options_(shaderc_compile_options_initialize()) {}
+  ~Options() { shaderc_compile_options_release(options_); }
+  shaderc_compile_options_t get() { return options_; }
+
+ private:
+  shaderc_compile_options_t options_;
+};
+
 // Helper function to check if the compilation result indicates a successful
 // compilation.
 bool CompilationResultIsSuccess(const shaderc_compilation_result_t result) {
@@ -178,7 +195,7 @@
                         shaderc_shader_kind kind,
                         const shaderc_compile_options_t options = nullptr) {
   const Compilation comp(compiler.get_compiler_handle(), shader, kind, "shader",
-                         options, OutputType::SpirvBinary);
+                         "main", options, OutputType::SpirvBinary);
   return ResultContainsValidSpv(comp.result());
 }
 
@@ -195,7 +212,7 @@
                           OutputType output_type = OutputType::SpirvBinary) {
     return CompilationResultIsSuccess(
         Compilation(compiler_.get_compiler_handle(), shader, kind, "shader",
-                    options, output_type)
+                    "main", options, output_type)
             .result());
   }
 
@@ -206,7 +223,7 @@
       const shaderc_compile_options_t options = nullptr,
       OutputType output_type = OutputType::SpirvBinary) {
     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
-                           "shader", options, output_type);
+                           "shader", "main", options, output_type);
     EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n'
                                                            << shader;
     return shaderc_result_get_error_message(comp.result());
@@ -219,7 +236,7 @@
       OutputType output_type = OutputType::SpirvBinary,
       const char* source_name = "shader") {
     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
-                           source_name, options, output_type);
+                           source_name, "main", options, output_type);
     EXPECT_FALSE(CompilationResultIsSuccess(comp.result())) << kind << '\n'
                                                             << shader;
     EXPECT_EQ(0u, shaderc_result_get_length(comp.result()));
@@ -232,7 +249,7 @@
       const shaderc_compile_options_t options = nullptr,
       OutputType output_type = OutputType::SpirvBinary) {
     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
-                           "shader", options, output_type);
+                           "shader", "main", options, output_type);
     return shaderc_result_get_error_message(comp.result());
   };
 
@@ -243,7 +260,7 @@
       const shaderc_compile_options_t options = nullptr,
       OutputType output_type = OutputType::SpirvBinary) {
     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
-                           "shader", options, output_type);
+                           "shader", "main", options, output_type);
     EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n'
                                                            << shader;
     // Use string(const char* s, size_t n) constructor instead of
@@ -362,7 +379,7 @@
 
 TEST_F(CompileStringTest, GetNumErrors) {
   Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader,
-                   shaderc_glsl_vertex_shader, "shader");
+                   shaderc_glsl_vertex_shader, "shader", "main");
   // Expects compilation failure and two errors.
   EXPECT_FALSE(CompilationResultIsSuccess(comp.result()));
   EXPECT_EQ(2u, shaderc_result_get_num_errors(comp.result()));
@@ -372,7 +389,7 @@
 
 TEST_F(CompileStringTest, GetNumWarnings) {
   Compilation comp(compiler_.get_compiler_handle(), kTwoWarningsShader,
-                   shaderc_glsl_vertex_shader, "shader");
+                   shaderc_glsl_vertex_shader, "shader", "main");
   // Expects compilation success with two warnings.
   EXPECT_TRUE(CompilationResultIsSuccess(comp.result()));
   EXPECT_EQ(2u, shaderc_result_get_num_warnings(comp.result()));
@@ -382,7 +399,7 @@
 
 TEST_F(CompileStringTest, ZeroErrorsZeroWarnings) {
   Compilation comp(compiler_.get_compiler_handle(), kMinimalShader,
-                   shaderc_glsl_vertex_shader, "shader");
+                   shaderc_glsl_vertex_shader, "shader", "main");
   // Expects compilation success with zero warnings.
   EXPECT_TRUE(CompilationResultIsSuccess(comp.result()));
   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result()));
@@ -394,7 +411,7 @@
   // The shader kind/stage can not be determined, the error type field should
   // indicate the error type is shaderc_shader_kind_error.
   Compilation comp(compiler_.get_compiler_handle(), kMinimalShader,
-                   shaderc_glsl_infer_from_source, "shader");
+                   shaderc_glsl_infer_from_source, "shader", "main");
   EXPECT_EQ(shaderc_compilation_status_invalid_stage,
             shaderc_result_get_compilation_status(comp.result()));
 }
@@ -402,7 +419,7 @@
   // The shader kind is valid, the result object's error type field should
   // indicate this compilaion fails due to compilation errors.
   Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader,
-                   shaderc_glsl_vertex_shader, "shader");
+                   shaderc_glsl_vertex_shader, "shader", "main");
   EXPECT_EQ(shaderc_compilation_status_compilation_error,
             shaderc_result_get_compilation_status(comp.result()));
 }
@@ -869,8 +886,8 @@
       TestIncluder::ReleaseIncluderResponseWrapper, &includer);
 
   const Compilation comp(compiler.get_compiler_handle(), shader,
-                         shaderc_glsl_vertex_shader, "shader", options.get(),
-                         OutputType::PreprocessedText);
+                         shaderc_glsl_vertex_shader, "shader", "main",
+                         options.get(), OutputType::PreprocessedText);
   // Checks the existence of the expected string.
   EXPECT_THAT(shaderc_result_get_bytes(comp.result()),
               HasSubstr(test_case.expected_substring()));
@@ -892,7 +909,7 @@
       shaderc_compile_options_clone(options.get()));
 
   const Compilation comp(compiler.get_compiler_handle(), shader,
-                         shaderc_glsl_vertex_shader, "shader",
+                         shaderc_glsl_vertex_shader, "shader", "main",
                          cloned_options.get(), OutputType::PreprocessedText);
   // Checks the existence of the expected string.
   EXPECT_THAT(shaderc_result_get_bytes(comp.result()),
@@ -998,13 +1015,13 @@
   // Warnings on particular lines should be inhibited.
   Compilation comp_line(compiler_.get_compiler_handle(),
                         kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,
-                        "shader", options_.get());
+                        "shader", "main", options_.get());
   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result()));
 
   // Global warnings should be inhibited.
-  Compilation comp_global(compiler_.get_compiler_handle(),
-                          kMinimalUnknownVersionShader,
-                          shaderc_glsl_vertex_shader, "shader", options_.get());
+  Compilation comp_global(
+      compiler_.get_compiler_handle(), kMinimalUnknownVersionShader,
+      shaderc_glsl_vertex_shader, "shader", "main", options_.get());
   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result()));
 }
 
@@ -1019,13 +1036,13 @@
   // Warnings on particular lines should be inhibited.
   Compilation comp_line(compiler_.get_compiler_handle(),
                         kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,
-                        "shader", options_.get());
+                        "shader", "main", options_.get());
   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result()));
 
   // Global warnings should be inhibited.
-  Compilation comp_global(compiler_.get_compiler_handle(),
-                          kMinimalUnknownVersionShader,
-                          shaderc_glsl_vertex_shader, "shader", options_.get());
+  Compilation comp_global(
+      compiler_.get_compiler_handle(), kMinimalUnknownVersionShader,
+      shaderc_glsl_vertex_shader, "shader", "main", options_.get());
   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result()));
 }
 
@@ -1292,4 +1309,120 @@
               HasSubstr("Input file name string was null."));
 }
 
+const char kGlslVertexShader[] =
+    "#version 140\nvoid main(){ gl_Position = vec4(0);}";
+
+const char kHlslVertexShader[] =
+    "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n"
+    "{ return float4(1.0, 2.0, 3.0, 4.0); }";
+
+TEST_F(CompileStringTest, LangGlslOnGlslVertexSucceeds) {
+  shaderc_compile_options_set_source_language(options_.get(),
+                                              shaderc_source_language_glsl);
+  EXPECT_TRUE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader,
+                                 options_.get()));
+}
+
+TEST_F(CompileStringTest, LangGlslOnHlslVertexFails) {
+  shaderc_compile_options_set_source_language(options_.get(),
+                                              shaderc_source_language_glsl);
+  EXPECT_FALSE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader,
+                                  options_.get()));
+}
+
+TEST_F(CompileStringTest, LangHlslOnGlslVertexFails) {
+  shaderc_compile_options_set_source_language(options_.get(),
+                                              shaderc_source_language_hlsl);
+  EXPECT_FALSE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader,
+                                  options_.get()));
+}
+
+TEST_F(CompileStringTest, LangHlslOnHlslVertexSucceeds) {
+  shaderc_compile_options_set_source_language(options_.get(),
+                                              shaderc_source_language_hlsl);
+  EXPECT_TRUE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader,
+                                 options_.get()));
+}
+
+TEST(EntryPointTest,
+     LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain) {
+  Compiler compiler;
+  Options options;
+  auto compilation =
+      Compilation(compiler.get_compiler_handle(), kGlslVertexShader,
+                  shaderc_glsl_vertex_shader, "shader", "blah blah blah",
+                  options.get(), OutputType::SpirvAssemblyText);
+
+  EXPECT_THAT(shaderc_result_get_bytes(compilation.result()),
+              HasSubstr("OpEntryPoint Vertex %main \"main\""))
+      << std::string(shaderc_result_get_bytes(compilation.result()));
+}
+
+TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) {
+  Compiler compiler;
+  Options options;
+  shaderc_compile_options_set_source_language(options.get(),
+                                              shaderc_source_language_hlsl);
+  auto compilation =
+      Compilation(compiler.get_compiler_handle(), kHlslVertexShader,
+                  shaderc_glsl_vertex_shader, "shader", "EntryPoint",
+                  options.get(), OutputType::SpirvAssemblyText);
+
+  EXPECT_THAT(shaderc_result_get_bytes(compilation.result()),
+              HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
+      << std::string(shaderc_result_get_bytes(compilation.result()));
+}
+
+// Returns a fragment shader accessing a texture with the given
+// offset.
+std::string ShaderWithTexOffset(int offset) {
+  std::ostringstream oss;
+  oss <<
+    "#version 150\n"
+    "uniform sampler1D tex;\n"
+    "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n";
+  return oss.str();
+}
+
+// Ensure compilation is sensitive to limit setting.  Sample just
+// two particular limits.
+TEST_F(CompileStringTest, LimitsTexelOffsetDefault) {
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_.get()));
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_.get()));
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_.get()));
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_.get()));
+}
+
+TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) {
+  shaderc_compile_options_set_limit(options_.get(),
+                                    shaderc_limit_min_program_texel_offset,
+                                    -99);
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_.get()));
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_.get()));
+}
+
+TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) {
+  shaderc_compile_options_set_limit(options_.get(),
+                                    shaderc_limit_max_program_texel_offset,
+                                    10);
+  EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),
+                                 shaderc_glsl_fragment_shader,
+                                 options_.get()));
+  EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),
+                                  shaderc_glsl_fragment_shader,
+                                  options_.get()));
+}
+
 }  // anonymous namespace
diff --git a/libshaderc_util/include/libshaderc_util/compiler.h b/libshaderc_util/include/libshaderc_util/compiler.h
index bbddca5..50ab01c 100644
--- a/libshaderc_util/include/libshaderc_util/compiler.h
+++ b/libshaderc_util/include/libshaderc_util/compiler.h
@@ -26,6 +26,7 @@
 #include "counting_includer.h"
 #include "file_finder.h"
 #include "mutex.h"
+#include "resources.h"
 #include "string_piece.h"
 
 namespace shaderc_util {
@@ -39,11 +40,11 @@
 // glslang state can be correctly handled.
 // TODO(awoloszyn): Once glslang no longer has static global mutable state
 //                  remove this class.
-class GlslInitializer {
+class GlslangInitializer {
  public:
-  GlslInitializer() { glslang::InitializeProcess(); }
+  GlslangInitializer() { glslang::InitializeProcess(); }
 
-  ~GlslInitializer() { glslang::FinalizeProcess(); }
+  ~GlslangInitializer() { glslang::FinalizeProcess(); }
 
   // Calls release on GlslangInitializer used to intialize this object
   // when it is destroyed.
@@ -63,11 +64,11 @@
     InitializationToken(const InitializationToken&) = delete;
 
    private:
-    InitializationToken(GlslInitializer* initializer)
+    InitializationToken(GlslangInitializer* initializer)
         : initializer_(initializer) {}
 
-    friend class GlslInitializer;
-    GlslInitializer* initializer_;
+    friend class GlslangInitializer;
+    GlslangInitializer* initializer_;
   };
 
   // Obtains exclusive access to the glslang state. The state remains
@@ -92,6 +93,12 @@
 // Holds all of the state required to compile source GLSL into SPIR-V.
 class Compiler {
  public:
+  // Source language
+  enum class SourceLanguage {
+    GLSL,  // The default
+    HLSL,
+  };
+
   // Target environment.
   enum class TargetEnv {
     Vulkan,
@@ -111,6 +118,13 @@
     Size,  // Optimization towards reducing code size.
   };
 
+  // Resource limits.  These map to the "max*" fields in glslang::TBuiltInResource.
+  enum class Limit {
+#define RESOURCE(NAME,FIELD,CNAME) NAME,
+#include "resources.inc"
+#undef RESOURCE
+  };
+
   // Creates an default compiler instance targeting at Vulkan environment. Uses
   // version 110 and no profile specification as the default for GLSL.
   Compiler()
@@ -123,7 +137,9 @@
         suppress_warnings_(false),
         generate_debug_info_(false),
         enabled_opt_passes_(),
-        target_env_(TargetEnv::Vulkan) {}
+        target_env_(TargetEnv::Vulkan),
+        source_language_(SourceLanguage::GLSL),
+        limits_(kDefaultTBuiltInResource) {}
 
   // Requests that the compiler place debug information into the object code,
   // such as identifier names and line numbers.
@@ -149,23 +165,36 @@
   // Sets the target environment.
   void SetTargetEnv(TargetEnv env);
 
+  // Sets the souce language.
+  void SetSourceLanguage(SourceLanguage lang);
+
   // Forces (without any verification) the default version and profile for
   // subsequent CompileShader() calls.
   void SetForcedVersionProfile(int version, EProfile profile);
 
+  // Sets a resource limit.
+  void SetLimit(Limit limit, int value);
+
+  // Returns the current limit.
+  int GetLimit(Limit limit) const;
+
   // Compiles the shader source in the input_source_string parameter.
   //
   // If the forced_shader stage parameter is not EShLangCount then
   // the shader is assumed to be of the given stage.
   //
+  // For HLSL compilation, entry_point_name is the null-terminated string for
+  // the entry point.  For GLSL compilation, entry_point_name is ignored, and
+  // compilation assumes the entry point is named "main".
+  //
   // The stage_callback function will be called if a shader_stage has
   // not been forced and the stage can not be determined
   // from the shader text. Any #include directives are parsed with the given
   // includer.
   //
-  // The initializer parameter must be a valid GlslInitializer object.
+  // The initializer parameter must be a valid GlslangInitializer object.
   // Acquire will be called on the initializer and the result will be
-  // destoryed before the function ends.
+  // destroyed before the function ends.
   //
   // The output_type parameter determines what kind of output should be
   // produced.
@@ -184,13 +213,13 @@
   // If the output is a text string, the size equals the length of that string.
   std::tuple<bool, std::vector<uint32_t>, size_t> Compile(
       const string_piece& input_source_string, EShLanguage forced_shader_stage,
-      const std::string& error_tag,
+      const std::string& error_tag, const char* entry_point_name,
       const std::function<EShLanguage(std::ostream* error_stream,
                                       const string_piece& error_tag)>&
           stage_callback,
       CountingIncluder& includer, OutputType output_type,
       std::ostream* error_stream, size_t* total_warnings, size_t* total_errors,
-      GlslInitializer* initializer) const;
+      GlslangInitializer* initializer) const;
 
   static EShMessages GetDefaultRules() {
     return static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules |
@@ -292,6 +321,12 @@
   // messages as well as the set of available builtins, as per the
   // implementation of glslang.
   TargetEnv target_env_;
+
+  // The source language.  Defaults to GLSL.
+  SourceLanguage source_language_;
+
+  // The resource limits to be used.
+  TBuiltInResource limits_;
 };
 
 // Converts a string to a vector of uint32_t by copying the content of a given
diff --git a/libshaderc_util/include/libshaderc_util/resources.h b/libshaderc_util/include/libshaderc_util/resources.h
index 5b185b8..a8f635b 100644
--- a/libshaderc_util/include/libshaderc_util/resources.h
+++ b/libshaderc_util/include/libshaderc_util/resources.h
@@ -15,10 +15,13 @@
 #ifndef LIBSHADERC_UTIL_RESOURCES_H_
 #define LIBSHADERC_UTIL_RESOURCES_H_
 
-struct TBuiltInResource;
+// We want TBuiltInResource
+#include "glslang/Include/ResourceLimits.h"
 
 namespace shaderc_util {
 
+using TBuiltInResource = ::TBuiltInResource;
+
 // A set of suitable defaults.
 extern const TBuiltInResource kDefaultTBuiltInResource;
 
diff --git a/libshaderc_util/include/libshaderc_util/resources.inc b/libshaderc_util/include/libshaderc_util/resources.inc
new file mode 100644
index 0000000..8e86f01
--- /dev/null
+++ b/libshaderc_util/include/libshaderc_util/resources.inc
@@ -0,0 +1,107 @@
+// Copyright 2016 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// These are the resource limits in a glslang::TBuiltInResource.
+// The first field is the string name to be used in a configuration setting.
+// The second field is the fieldname in TBuiltInResource.
+// The third field is the enum name fragment for shaderc_limit.
+//
+// TODO(dneto): Consider using a single list of names, but use a Python script
+// to generate *this* file.  The original data file would have the first field,
+// then generate the second field by lowering the case of the first letter, and
+// generate the third field by taking the second field, and converting a
+// lower-to-upper case transition into an underscore with lower-case.
+RESOURCE(MaxLights,maxLights,max_lights)
+RESOURCE(MaxClipPlanes,maxClipPlanes,max_clip_planes)
+RESOURCE(MaxTextureUnits,maxTextureUnits,max_texture_units)
+RESOURCE(MaxTextureCoords,maxTextureCoords,max_texture_coords)
+RESOURCE(MaxVertexAttribs,maxVertexAttribs,max_vertex_attribs)
+RESOURCE(MaxVertexUniformComponents,maxVertexUniformComponents,max_vertex_uniform_components)
+RESOURCE(MaxVaryingFloats,maxVaryingFloats,max_varying_floats)
+RESOURCE(MaxVertexTextureImageUnits,maxVertexTextureImageUnits,max_vertex_texture_image_units)
+RESOURCE(MaxCombinedTextureImageUnits,maxCombinedTextureImageUnits,max_combined_texture_image_units)
+RESOURCE(MaxTextureImageUnits,maxTextureImageUnits,max_texture_image_units)
+RESOURCE(MaxFragmentUniformComponents,maxFragmentUniformComponents,max_fragment_uniform_components)
+RESOURCE(MaxDrawBuffers,maxDrawBuffers,max_draw_buffers)
+RESOURCE(MaxVertexUniformVectors,maxVertexUniformVectors,max_vertex_uniform_vectors)
+RESOURCE(MaxVaryingVectors,maxVaryingVectors,max_varying_vectors)
+RESOURCE(MaxFragmentUniformVectors,maxFragmentUniformVectors,max_fragment_uniform_vectors)
+RESOURCE(MaxVertexOutputVectors,maxVertexOutputVectors,max_vertex_output_vectors)
+RESOURCE(MaxFragmentInputVectors,maxFragmentInputVectors,max_fragment_input_vectors)
+RESOURCE(MinProgramTexelOffset,minProgramTexelOffset,min_program_texel_offset)
+RESOURCE(MaxProgramTexelOffset,maxProgramTexelOffset,max_program_texel_offset)
+RESOURCE(MaxClipDistances,maxClipDistances,max_clip_distances)
+RESOURCE(MaxComputeWorkGroupCountX,maxComputeWorkGroupCountX,max_compute_work_group_count_x)
+RESOURCE(MaxComputeWorkGroupCountY,maxComputeWorkGroupCountY,max_compute_work_group_count_y)
+RESOURCE(MaxComputeWorkGroupCountZ,maxComputeWorkGroupCountZ,max_compute_work_group_count_z)
+RESOURCE(MaxComputeWorkGroupSizeX,maxComputeWorkGroupSizeX,max_compute_work_group_size_x)
+RESOURCE(MaxComputeWorkGroupSizeY,maxComputeWorkGroupSizeY,max_compute_work_group_size_y)
+RESOURCE(MaxComputeWorkGroupSizeZ,maxComputeWorkGroupSizeZ,max_compute_work_group_size_z)
+RESOURCE(MaxComputeUniformComponents,maxComputeUniformComponents,max_compute_uniform_components)
+RESOURCE(MaxComputeTextureImageUnits,maxComputeTextureImageUnits,max_compute_texture_image_units)
+RESOURCE(MaxComputeImageUniforms,maxComputeImageUniforms,max_compute_image_uniforms)
+RESOURCE(MaxComputeAtomicCounters,maxComputeAtomicCounters,max_compute_atomic_counters)
+RESOURCE(MaxComputeAtomicCounterBuffers,maxComputeAtomicCounterBuffers,max_compute_atomic_counter_buffers)
+RESOURCE(MaxVaryingComponents,maxVaryingComponents,max_varying_components)
+RESOURCE(MaxVertexOutputComponents,maxVertexOutputComponents,max_vertex_output_components)
+RESOURCE(MaxGeometryInputComponents,maxGeometryInputComponents,max_geometry_input_components)
+RESOURCE(MaxGeometryOutputComponents,maxGeometryOutputComponents,max_geometry_output_components)
+RESOURCE(MaxFragmentInputComponents,maxFragmentInputComponents,max_fragment_input_components)
+RESOURCE(MaxImageUnits,maxImageUnits,max_image_units)
+RESOURCE(MaxCombinedImageUnitsAndFragmentOutputs,maxCombinedImageUnitsAndFragmentOutputs,max_combined_image_units_and_fragment_outputs)
+RESOURCE(MaxCombinedShaderOutputResources,maxCombinedShaderOutputResources,max_combined_shader_output_resources)
+RESOURCE(MaxImageSamples,maxImageSamples,max_image_samples)
+RESOURCE(MaxVertexImageUniforms,maxVertexImageUniforms,max_vertex_image_uniforms)
+RESOURCE(MaxTessControlImageUniforms,maxTessControlImageUniforms,max_tess_control_image_uniforms)
+RESOURCE(MaxTessEvaluationImageUniforms,maxTessEvaluationImageUniforms,max_tess_evaluation_image_uniforms)
+RESOURCE(MaxGeometryImageUniforms,maxGeometryImageUniforms,max_geometry_image_uniforms)
+RESOURCE(MaxFragmentImageUniforms,maxFragmentImageUniforms,max_fragment_image_uniforms)
+RESOURCE(MaxCombinedImageUniforms,maxCombinedImageUniforms,max_combined_image_uniforms)
+RESOURCE(MaxGeometryTextureImageUnits,maxGeometryTextureImageUnits,max_geometry_texture_image_units)
+RESOURCE(MaxGeometryOutputVertices,maxGeometryOutputVertices,max_geometry_output_vertices)
+RESOURCE(MaxGeometryTotalOutputComponents,maxGeometryTotalOutputComponents,max_geometry_total_output_components)
+RESOURCE(MaxGeometryUniformComponents,maxGeometryUniformComponents,max_geometry_uniform_components)
+RESOURCE(MaxGeometryVaryingComponents,maxGeometryVaryingComponents,max_geometry_varying_components)
+RESOURCE(MaxTessControlInputComponents,maxTessControlInputComponents,max_tess_control_input_components)
+RESOURCE(MaxTessControlOutputComponents,maxTessControlOutputComponents,max_tess_control_output_components)
+RESOURCE(MaxTessControlTextureImageUnits,maxTessControlTextureImageUnits,max_tess_control_texture_image_units)
+RESOURCE(MaxTessControlUniformComponents,maxTessControlUniformComponents,max_tess_control_uniform_components)
+RESOURCE(MaxTessControlTotalOutputComponents,maxTessControlTotalOutputComponents,max_tess_control_total_output_components)
+RESOURCE(MaxTessEvaluationInputComponents,maxTessEvaluationInputComponents,max_tess_evaluation_input_components)
+RESOURCE(MaxTessEvaluationOutputComponents,maxTessEvaluationOutputComponents,max_tess_evaluation_output_components)
+RESOURCE(MaxTessEvaluationTextureImageUnits,maxTessEvaluationTextureImageUnits,max_tess_evaluation_texture_image_units)
+RESOURCE(MaxTessEvaluationUniformComponents,maxTessEvaluationUniformComponents,max_tess_evaluation_uniform_components)
+RESOURCE(MaxTessPatchComponents,maxTessPatchComponents,max_tess_patch_components)
+RESOURCE(MaxPatchVertices,maxPatchVertices,max_patch_vertices)
+RESOURCE(MaxTessGenLevel,maxTessGenLevel,max_tess_gen_level)
+RESOURCE(MaxViewports,maxViewports,max_viewports)
+RESOURCE(MaxVertexAtomicCounters,maxVertexAtomicCounters,max_vertex_atomic_counters)
+RESOURCE(MaxTessControlAtomicCounters,maxTessControlAtomicCounters,max_tess_control_atomic_counters)
+RESOURCE(MaxTessEvaluationAtomicCounters,maxTessEvaluationAtomicCounters,max_tess_evaluation_atomic_counters)
+RESOURCE(MaxGeometryAtomicCounters,maxGeometryAtomicCounters,max_geometry_atomic_counters)
+RESOURCE(MaxFragmentAtomicCounters,maxFragmentAtomicCounters,max_fragment_atomic_counters)
+RESOURCE(MaxCombinedAtomicCounters,maxCombinedAtomicCounters,max_combined_atomic_counters)
+RESOURCE(MaxAtomicCounterBindings,maxAtomicCounterBindings,max_atomic_counter_bindings)
+RESOURCE(MaxVertexAtomicCounterBuffers,maxVertexAtomicCounterBuffers,max_vertex_atomic_counter_buffers)
+RESOURCE(MaxTessControlAtomicCounterBuffers,maxTessControlAtomicCounterBuffers,max_tess_control_atomic_counter_buffers)
+RESOURCE(MaxTessEvaluationAtomicCounterBuffers,maxTessEvaluationAtomicCounterBuffers,max_tess_evaluation_atomic_counter_buffers)
+RESOURCE(MaxGeometryAtomicCounterBuffers,maxGeometryAtomicCounterBuffers,max_geometry_atomic_counter_buffers)
+RESOURCE(MaxFragmentAtomicCounterBuffers,maxFragmentAtomicCounterBuffers,max_fragment_atomic_counter_buffers)
+RESOURCE(MaxCombinedAtomicCounterBuffers,maxCombinedAtomicCounterBuffers,max_combined_atomic_counter_buffers)
+RESOURCE(MaxAtomicCounterBufferSize,maxAtomicCounterBufferSize,max_atomic_counter_buffer_size)
+RESOURCE(MaxTransformFeedbackBuffers,maxTransformFeedbackBuffers,max_transform_feedback_buffers)
+RESOURCE(MaxTransformFeedbackInterleavedComponents,maxTransformFeedbackInterleavedComponents,max_transform_feedback_interleaved_components)
+RESOURCE(MaxCullDistances,maxCullDistances,max_cull_distances)
+RESOURCE(MaxCombinedClipAndCullDistances,maxCombinedClipAndCullDistances,max_combined_clip_and_cull_distances)
+RESOURCE(MaxSamples,maxSamples,max_samples)
diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc
index 686f78f..574ccfd 100644
--- a/libshaderc_util/src/compiler.cc
+++ b/libshaderc_util/src/compiler.cc
@@ -65,33 +65,64 @@
   return std::make_pair(line, directive);
 }
 
-// Gets the corresponding message rules for the given target environment.
-EShMessages GetMessageRules(shaderc_util::Compiler::TargetEnv env) {
+// Returns the Glslang message rules for the given target environment
+// and source language.  We assume only valid combinations are used.
+EShMessages GetMessageRules(shaderc_util::Compiler::TargetEnv env,
+                            shaderc_util::Compiler::SourceLanguage lang) {
   using shaderc_util::Compiler;
+  EShMessages result = EShMsgCascadingErrors;
+  if (lang == Compiler::SourceLanguage::HLSL) {
+    result = static_cast<EShMessages>(result | EShMsgReadHlsl);
+  }
   switch (env) {
     case Compiler::TargetEnv::OpenGLCompat:
       break;
     case Compiler::TargetEnv::OpenGL:
-      return static_cast<EShMessages>(EShMsgSpvRules | EShMsgCascadingErrors);
+      result = static_cast<EShMessages>(result | EShMsgSpvRules);
+      break;
     case Compiler::TargetEnv::Vulkan:
-      return static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules |
-                                      EShMsgCascadingErrors);
+      result =
+          static_cast<EShMessages>(result | EShMsgSpvRules | EShMsgVulkanRules);
+      break;
   }
-  return EShMsgCascadingErrors;
+  return result;
 }
 
 }  // anonymous namespace
 
 namespace shaderc_util {
+
+void Compiler::SetLimit(Compiler::Limit limit, int value) {
+  switch (limit) {
+#define RESOURCE(NAME, FIELD, CNAME) \
+  case Limit::NAME:                  \
+    limits_.FIELD = value;           \
+    break;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+  }
+}
+
+int Compiler::GetLimit(Compiler::Limit limit) const {
+  switch (limit) {
+#define RESOURCE(NAME, FIELD, CNAME) \
+  case Limit::NAME:                  \
+    return limits_.FIELD;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+  }
+  return 0;  // Unreachable
+}
+
 std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
     const string_piece& input_source_string, EShLanguage forced_shader_stage,
-    const std::string& error_tag,
+    const std::string& error_tag, const char* entry_point_name,
     const std::function<EShLanguage(std::ostream* error_stream,
                                     const string_piece& error_tag)>&
         stage_callback,
     CountingIncluder& includer, OutputType output_type,
     std::ostream* error_stream, size_t* total_warnings, size_t* total_errors,
-    GlslInitializer* initializer) const {
+    GlslangInitializer* initializer) const {
   // Compilation results to be returned:
   // Initialize the result tuple as a failed compilation. In error cases, we
   // should return result_tuple directly without setting its members.
@@ -172,12 +203,13 @@
   shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths,
                                        &string_names, 1);
   shader.setPreamble(preamble.c_str());
+  shader.setEntryPoint(entry_point_name);
 
   // TODO(dneto): Generate source-level debug info if requested.
-  bool success = shader.parse(&shaderc_util::kDefaultTBuiltInResource,
-                              default_version_, default_profile_,
-                              force_version_profile_, kNotForwardCompatible,
-                              GetMessageRules(target_env_), includer);
+  bool success =
+      shader.parse(&limits_, default_version_, default_profile_,
+                   force_version_profile_, kNotForwardCompatible,
+                   GetMessageRules(target_env_, source_language_), includer);
 
   success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
                                  suppress_warnings_, shader.getInfoLog(),
@@ -238,6 +270,10 @@
 
 void Compiler::SetTargetEnv(Compiler::TargetEnv env) { target_env_ = env; }
 
+void Compiler::SetSourceLanguage(Compiler::SourceLanguage lang) {
+  source_language_ = lang;
+}
+
 void Compiler::SetForcedVersionProfile(int version, EProfile profile) {
   default_version_ = version;
   default_profile_ = profile;
@@ -288,14 +324,13 @@
   // The preprocessor might be sensitive to the target environment.
   // So combine the existing rules with the just-give-me-preprocessor-output
   // flag.
-  const auto rules = static_cast<EShMessages>(EShMsgOnlyPreprocessor |
-                                              GetMessageRules(target_env_));
+  const auto rules = static_cast<EShMessages>(
+      EShMsgOnlyPreprocessor | GetMessageRules(target_env_, source_language_));
 
   std::string preprocessed_shader;
   const bool success = shader.preprocess(
-      &shaderc_util::kDefaultTBuiltInResource, default_version_,
-      default_profile_, force_version_profile_, kNotForwardCompatible, rules,
-      &preprocessed_shader, includer);
+      &limits_, default_version_, default_profile_, force_version_profile_,
+      kNotForwardCompatible, rules, &preprocessed_shader, includer);
 
   if (success) {
     return std::make_tuple(true, preprocessed_shader, shader.getInfoLog());
diff --git a/libshaderc_util/src/compiler_test.cc b/libshaderc_util/src/compiler_test.cc
index b11e04b..9938848 100644
--- a/libshaderc_util/src/compiler_test.cc
+++ b/libshaderc_util/src/compiler_test.cc
@@ -16,7 +16,7 @@
 
 #include <sstream>
 
-#include <gtest/gtest.h>
+#include <gmock/gmock.h>
 
 #include "death_test.h"
 #include "libshaderc_util/counting_includer.h"
@@ -24,6 +24,8 @@
 namespace {
 
 using shaderc_util::Compiler;
+using ::testing::HasSubstr;
+using ::testing::Eq;
 
 // A trivial vertex shader
 const char kVertexShader[] =
@@ -77,6 +79,11 @@
     "#error\n"
     "#endif";
 
+// An HLSL vertex shader.
+const char kHlslVertexShader[] =
+    R"(float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION
+       { return float4(1.0, 2.0, 3.0, 4.0); })";
+
 // A CountingIncluder that never returns valid content for a requested
 // file inclusion.
 class DummyCountingIncluder : public shaderc_util::CountingIncluder {
@@ -100,18 +107,14 @@
   // shader stage.
   bool SimpleCompilationSucceedsForOutputType(
       std::string source, EShLanguage stage, Compiler::OutputType output_type) {
-    std::function<EShLanguage(std::ostream*, const shaderc_util::string_piece&)>
-        stage_callback = [](std::ostream*, const shaderc_util::string_piece&) {
-          return EShLangCount;
-        };
     std::stringstream errors;
     size_t total_warnings = 0;
     size_t total_errors = 0;
-    shaderc_util::GlslInitializer initializer;
+    shaderc_util::GlslangInitializer initializer;
     bool result = false;
     DummyCountingIncluder dummy_includer;
     std::tie(result, std::ignore, std::ignore) = compiler_.Compile(
-        source, stage, "shader", stage_callback, dummy_includer,
+        source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
         Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
         &total_errors, &initializer);
     errors_ = errors.str();
@@ -129,6 +132,11 @@
   Compiler compiler_;
   // The error string from the most recent compilation.
   std::string errors_;
+  std::function<EShLanguage(std::ostream*, const shaderc_util::string_piece&)>
+      dummy_stage_callback_ =
+          [](std::ostream*, const shaderc_util::string_piece&) {
+            return EShLangCount;
+          };
 };
 
 TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToBinary) {
@@ -311,4 +319,115 @@
         {"123456789", {0x34333231, 0x38373635, 0x00000039}},
     }));
 
+TEST_F(CompilerTest, SetSourceLanguageToGLSLSucceeds) {
+  compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
+  EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, SetSourceLanguageToGLSLFailsOnHLSL) {
+  compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
+  EXPECT_FALSE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, SetSourceLanguageToHLSLSucceeds) {
+  compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
+  EXPECT_TRUE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex))
+      << errors_;
+}
+
+TEST_F(CompilerTest, SetSourceLanguageToHLSLFailsOnGLSL) {
+  compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
+  EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, EntryPointParameterTakesEffectForHLSL) {
+  compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
+  std::stringstream errors;
+  size_t total_warnings = 0;
+  size_t total_errors = 0;
+  shaderc_util::GlslangInitializer initializer;
+  bool result = false;
+  DummyCountingIncluder dummy_includer;
+  std::vector<uint32_t> words;
+  std::tie(result, words, std::ignore) =
+      compiler_.Compile(kHlslVertexShader, EShLangVertex, "shader",
+                        "EntryPoint", dummy_stage_callback_, dummy_includer,
+                        Compiler::OutputType::SpirvAssemblyText, &errors,
+                        &total_warnings, &total_errors, &initializer);
+  EXPECT_TRUE(result);
+  std::string assembly(reinterpret_cast<char*>(words.data()));
+  EXPECT_THAT(assembly,
+              HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
+      << assembly;
+}
+
+// A test case for setting resource limits.
+struct SetLimitCase {
+  Compiler::Limit limit;
+  int default_value;
+  int value;
+};
+
+using LimitTest = testing::TestWithParam<SetLimitCase>;
+
+TEST_P(LimitTest, Sample) {
+  Compiler compiler;
+  EXPECT_THAT(compiler.GetLimit(GetParam().limit),
+              Eq(GetParam().default_value));
+  compiler.SetLimit(GetParam().limit, GetParam().value);
+  EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().value));
+}
+
+#define CASE(LIMIT, DEFAULT, NEW) \
+  { Compiler::Limit::LIMIT, DEFAULT, NEW }
+INSTANTIATE_TEST_CASE_P(
+    CompilerTest, LimitTest,
+    // See resources.cc for the defaults.
+    testing::ValuesIn(std::vector<SetLimitCase>{
+        // clang-format off
+        // This is just a sampling of the possible values.
+        CASE(MaxLights, 8, 99),
+        CASE(MaxClipPlanes, 6, 10929),
+        CASE(MaxTessControlAtomicCounters, 0, 72),
+        CASE(MaxSamples, 4, 8),
+        // clang-format on
+    }), );
+#undef CASE
+
+// Returns a fragment shader accessing a texture with the given
+// offset.
+std::string ShaderWithTexOffset(int offset) {
+  std::ostringstream oss;
+  oss << "#version 150\n"
+         "uniform sampler1D tex;\n"
+         "void main() { vec4 x = textureOffset(tex, 1.0, "
+      << offset << "); }\n";
+  return oss.str();
+}
+
+// Ensure compilation is sensitive to limit setting.  Sample just
+// two particular limits.  The default minimum texel offset is -8,
+// and the default maximum texel offset is 7.
+TEST_F(CompilerTest, TexelOffsetDefaults) {
+  const EShLanguage stage = EShLangFragment;
+  EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-9), stage));
+  EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-8), stage));
+  EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(7), stage));
+  EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(8), stage));
+}
+
+TEST_F(CompilerTest, TexelOffsetLowerTheMinimum) {
+  const EShLanguage stage = EShLangFragment;
+  compiler_.SetLimit(Compiler::Limit::MinProgramTexelOffset, -99);
+  EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-100), stage));
+  EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-99), stage));
+}
+
+TEST_F(CompilerTest, TexelOffsetRaiseTheMaximum) {
+  const EShLanguage stage = EShLangFragment;
+  compiler_.SetLimit(Compiler::Limit::MaxProgramTexelOffset, 100);
+  EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(100), stage));
+  EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(101), stage));
+}
+
 }  // anonymous namespace
diff --git a/third_party/Android.mk b/third_party/Android.mk
index 7f6e04c..40395ad 100644
--- a/third_party/Android.mk
+++ b/third_party/Android.mk
@@ -48,6 +48,7 @@
 LOCAL_MODULE:=HLSL
 LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti
 LOCAL_SRC_FILES:= \
+		hlsl/hlslAttributes.cpp \
 		hlsl/hlslGrammar.cpp \
 		hlsl/hlslOpMap.cpp \
 		hlsl/hlslParseables.cpp \
@@ -176,11 +177,11 @@
 		source/diagnostic.cpp \
 		source/disassemble.cpp \
 		source/ext_inst.cpp \
-		source/instruction.cpp \
 		source/libspirv.cpp \
 		source/name_mapper.cpp \
 		source/opcode.cpp \
 		source/operand.cpp \
+		source/parsed_operand.cpp \
 		source/print.cpp \
 		source/software_version.cpp \
 		source/spirv_endian.cpp \
@@ -189,13 +190,14 @@
 		source/text.cpp \
 		source/text_handler.cpp \
 		source/util/parse_number.cpp \
-		source/val/BasicBlock.cpp \
-		source/val/Construct.cpp \
-		source/val/Function.cpp \
-		source/val/Instruction.cpp \
-		source/val/ValidationState.cpp \
+		source/val/basic_block.cpp \
+		source/val/construct.cpp \
+		source/val/function.cpp \
+		source/val/instruction.cpp \
+		source/val/validation_state.cpp \
 		source/validate.cpp \
 		source/validate_cfg.cpp \
+		source/validate_datarules.cpp \
 		source/validate_id.cpp \
 		source/validate_instruction.cpp \
 		source/validate_layout.cpp