Implement dFdx, dFdy, and fwidth via new expression opcodes.
diff --git a/builtin_function.cpp b/builtin_function.cpp
index 377fd509..4ee43df 100644
--- a/builtin_function.cpp
+++ b/builtin_function.cpp
@@ -2496,6 +2496,82 @@
 
 /* 110_fs builtins */
 
+static const char *builtins_110_fs_derivatives = {
+   "((function dFdx\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p))\n"
+   "     ((return (expression float dFdx (var_ref p)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p))\n"
+   "     ((return (expression vec2 dFdx (var_ref p)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p))\n"
+   "     ((return (expression vec3 dFdx (var_ref p)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p))\n"
+   "     ((return (expression vec4 dFdx (var_ref p)))))\n"
+   " )\n"
+   "\n"
+   " (function dFdy\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p))\n"
+   "     ((return (expression float dFdy (var_ref p)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p))\n"
+   "     ((return (expression vec2 dFdy (var_ref p)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p))\n"
+   "     ((return (expression vec3 dFdy (var_ref p)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p))\n"
+   "     ((return (expression vec4 dFdy (var_ref p)))))\n"
+   " )\n"
+   "\n"
+   " (function fwidth\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p))\n"
+   "     ((return (expression float +\n"
+   "                (expression float abs (expression float dFdx (var_ref p)))\n"
+   "                (expression float abs (expression float dFdy (var_ref p)))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p))\n"
+   "     ((return (expression vec2 +\n"
+   "                (expression vec2 abs (expression vec2 dFdx (var_ref p)))\n"
+   "                (expression vec2 abs (expression vec2 dFdy (var_ref p)))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p))\n"
+   "     ((return (expression vec3 +\n"
+   "                (expression vec3 abs (expression vec3 dFdx (var_ref p)))\n"
+   "                (expression vec3 abs (expression vec3 dFdy (var_ref p)))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p))\n"
+   "     ((return (expression vec4 +\n"
+   "                (expression vec4 abs (expression vec4 dFdx (var_ref p)))\n"
+   "                (expression vec4 abs (expression vec4 dFdy (var_ref p)))))))\n"
+   "))\n"
+};
+
 static const char *builtins_110_fs_textures = {
    "((function texture1D\n"
    "   (signature vec4\n"
@@ -2613,6 +2689,7 @@
 };
 
 static const char *functions_for_110_fs [] = {
+   builtins_110_fs_derivatives,
    builtins_110_fs_textures,
 };