Index: /trunk/src/kmk/Makefile.kmk
===================================================================
--- /trunk/src/kmk/Makefile.kmk	(revision 2764)
+++ /trunk/src/kmk/Makefile.kmk	(revision 2765)
@@ -193,4 +193,5 @@
 	CONFIG_WITH_LAZY_DEPS_VARS \
 	CONFIG_WITH_MEMORY_OPTIMIZATIONS \
+	CONFIG_WITH_COMPILER \
 	\
 	KBUILD_HOST=\"$(KBUILD_TARGET)\" \
@@ -207,12 +208,7 @@
 kmk_SOURCES = \
 	main.c \
-	kbuild.c \
-	kbuild-object.c \
 	read.c \
-	expreval.c \
-	incdep.c \
 	hash.c \
 	strcache.c \
-	strcache2.c \
 	variable.c \
 	ar.c \
@@ -227,5 +223,4 @@
 	job.c \
 	misc.c \
-	alloccache.c \
 	remake.c \
 	rule.c \
@@ -233,5 +228,13 @@
 	version.c \
 	vpath.c \
-	remote-stub.c
+	remote-stub.c \
+       \
+	alloccache.c \
+	expreval.c \
+	incdep.c \
+	strcache2.c \
+       kmk_cc_exec.c \
+	kbuild.c \
+	kbuild-object.c
 
 kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS
Index: /trunk/src/kmk/expand.c
===================================================================
--- /trunk/src/kmk/expand.c	(revision 2764)
+++ /trunk/src/kmk/expand.c	(revision 2765)
@@ -26,4 +26,7 @@
 #include "variable.h"
 #include "rule.h"
+#ifdef CONFIG_WITH_COMPILER
+# include "kmk_cc_exec.h"
+#endif
 
 /* Initially, any errors reported when expanding strings will be reported
@@ -248,6 +251,18 @@
   v->expanding = 1;
   if (!v->append)
-    /* Expand directly into the variable buffer.  */
-    variable_expand_string_2 (o, v->value, v->value_length, &o);
+    {
+      /* Expand directly into the variable buffer.  */
+# ifdef CONFIG_WITH_COMPILER
+      v->expand_count++;
+      if (   v->expandprog
+          || (v->expand_count == 10 && kmk_cc_compile_variable_for_expand (v)) )
+        o = kmk_exec_expand_to_var_buf (v, o);
+      else
+        variable_expand_string_2 (o, v->value, v->value_length, &o);
+# else
+      MAKE_STATS_2 (v->expand_count++);
+      variable_expand_string_2 (o, v->value, v->value_length, &o);
+# endif
+    }
   else
     {
Index: /trunk/src/kmk/function.c
===================================================================
--- /trunk/src/kmk/function.c	(revision 2764)
+++ /trunk/src/kmk/function.c	(revision 2765)
@@ -43,4 +43,7 @@
 #  include <limits.h>
 # endif
+#endif
+#ifdef CONFIG_WITH_COMPILER
+# include "kmk_cc_exec.h"
 #endif
 #include <assert.h> /* bird */
@@ -2043,20 +2046,11 @@
       size_t off;
       const struct floc *reading_file_saved = reading_file;
-#ifdef CONFIG_WITH_MAKE_STATS
+# ifdef CONFIG_WITH_MAKE_STATS
       unsigned long long uStartTick = CURRENT_CLOCK_TICK();
-      MAKE_STATS_2(v->cEvalVals++);
-#endif
-
-      /* Make a copy of the value to the variable buffer since
-         eval_buffer will make changes to its input. */
-
-      off = o - variable_buffer;
-      variable_buffer_output (o, v->value, v->value_length + 1);
-      o = variable_buffer + off;
-
-      /* Eval the value.  Pop the current variable buffer setting so that the
-         eval'd code can use its own without conflicting. (really necessary?)  */
-
-      install_variable_buffer (&buf, &len);
+#  ifndef CONFIG_WITH_COMPILER
+      MAKE_STATS_2(v->evalval_count++);
+#  endif
+# endif
+
       var_ctx = !strcmp (funcname, "evalvalctx");
       if (var_ctx)
@@ -2065,11 +2059,35 @@
         reading_file = &v->fileinfo;
 
-      assert (!o[v->value_length]);
-      eval_buffer (o, o + v->value_length);
+# ifdef CONFIG_WITH_COMPILER
+      /* If this variable has been evaluated more than a few times, it make
+         sense to compile it to speed up the processing. */
+
+      v->evalval_count++;
+      if (   v->evalprog
+          || (v->evalval_count == 3 && kmk_cc_compile_variable_for_eval (v)))
+        {
+          install_variable_buffer (&buf, &len); /* Really necessary? */
+          kmk_exec_evalval (v);
+          restore_variable_buffer (buf, len);
+        }
+      else
+# endif
+      {
+        /* Make a copy of the value to the variable buffer first since
+           eval_buffer will make changes to its input. */
+
+        off = o - variable_buffer;
+        variable_buffer_output (o, v->value, v->value_length + 1);
+        o = variable_buffer + off;
+        assert (!o[v->value_length]);
+
+        install_variable_buffer (&buf, &len); /* Really necessary? */
+        eval_buffer (o, o + v->value_length);
+        restore_variable_buffer (buf, len);
+      }
 
       reading_file = reading_file_saved;
       if (var_ctx)
         pop_variable_scope ();
-      restore_variable_buffer (buf, len);
 
       MAKE_STATS_2(v->cTicksEvalVal += CURRENT_CLOCK_TICK() - uStartTick);
@@ -2142,4 +2160,13 @@
               v->value_length = dst - v->value;
             }
+
+# ifdef CONFIG_WITH_COMPILER
+          /* Compile the variable for evalval, evalctx and expansion. */
+
+          if (!v->evalprog)
+            kmk_cc_compile_variable_for_eval (v);
+          if (!v->expandprog)
+            kmk_cc_compile_variable_for_expand (v);
+# endif
         }
       else if (v)
Index: /trunk/src/kmk/variable.c
===================================================================
--- /trunk/src/kmk/variable.c	(revision 2764)
+++ /trunk/src/kmk/variable.c	(revision 2765)
@@ -41,4 +41,7 @@
 #ifdef CONFIG_WITH_STRCACHE2
 # include <stddef.h>
+#endif
+#ifdef CONFIG_WITH_COMPILER
+# include "kmk_cc_exec.h"
 #endif
 
@@ -383,5 +386,9 @@
 	  v->origin = origin;
 	  v->recursive = recursive;
-          MAKE_STATS_2(v->changes++);
+         MAKE_STATS_2(v->changes++);
+#ifdef CONFIG_WITH_COMPILER
+         if (v->evalprog || v->expandprog)
+           kmk_cc_variable_changed (v);
+#endif
 	}
       return v;
@@ -445,8 +452,16 @@
 #endif
   v->export = v_default;
+#ifdef CONFIG_WITH_COMPILER
+  v->evalprog = 0;
+  v->expandprog = 0;
+  v->evalval_count = 0;
+  v->expand_count = 0;
+#else
+  MAKE_STATS_2(v->expand_count = 0);
+  MAKE_STATS_2(v->evalval_count = 0);
+#endif
   MAKE_STATS_2(v->changes = 0);
   MAKE_STATS_2(v->reallocs = 0);
   MAKE_STATS_2(v->references = 0);
-  MAKE_STATS_2(v->cEvalVals = 0);
   MAKE_STATS_2(v->cTicksEvalVal = 0);
 
@@ -589,4 +604,8 @@
           free (v->value);
       MAKE_STATS_2(v->changes++);
+#ifdef CONFIG_WITH_COMPILER
+      if (v->evalprog || v->expandprog)
+        kmk_cc_variable_changed (v);
+#endif
     }
   else
@@ -605,8 +624,16 @@
       v->aliased = 0;
       v->export = v_default;
+#ifdef CONFIG_WITH_COMPILER
+      v->evalprog = 0;
+      v->expandprog = 0;
+      v->evalval_count = 0;
+      v->expand_count = 0;
+#else
+      MAKE_STATS_2(v->expand_count = 0);
+      MAKE_STATS_2(v->evalval_count = 0);
+#endif
       MAKE_STATS_2(v->changes = 0);
       MAKE_STATS_2(v->reallocs = 0);
       MAKE_STATS_2(v->references = 0);
-      MAKE_STATS_2(v->cEvalVals = 0);
       MAKE_STATS_2(v->cTicksEvalVal = 0);
       v->exportable = 1;
@@ -1242,4 +1269,8 @@
 #ifndef CONFIG_WITH_STRCACHE2
   free (v->name);
+#endif
+#ifdef CONFIG_WITH_COMPILER
+  if (v->evalprog || v->expandprog)
+    kmk_cc_variable_deleted (v);
 #endif
 #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
@@ -1362,4 +1393,8 @@
             if (from_var->alias)
               fatal(NULL, ("Attempting to delete variable aliased '%s'"), from_var->name);
+#endif
+#ifdef CONFIG_WITH_COMPILER
+            if (from_var->evalprog || from_var->expandprog)
+              kmk_cc_variable_deleted (from_var);
 #endif
 #ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE
@@ -2335,4 +2370,8 @@
                free (free_value);
             MAKE_STATS_2(v->changes++);
+# ifdef CONFIG_WITH_COMPILER
+            if (v->evalprog || v->expandprog)
+              kmk_cc_variable_changed (v);
+# endif
             return v;
 #else /* !CONFIG_WITH_VALUE_LENGTH */
@@ -2765,10 +2804,12 @@
 
 
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+static unsigned long var_stats_evalvals, var_stats_evalvaled;
+static unsigned long var_stats_expands, var_stats_expanded;
+#endif
 #ifdef CONFIG_WITH_MAKE_STATS
 static unsigned long var_stats_changes, var_stats_changed;
 static unsigned long var_stats_reallocs, var_stats_realloced;
 static unsigned long var_stats_references, var_stats_referenced;
-static unsigned long var_stats_evalvals, var_stats_evalvaled;
-static uintmax_t var_stats_evalval_ticks;
 static unsigned long var_stats_val_len, var_stats_val_alloc_len;
 static unsigned long var_stats_val_rdonly_len;
@@ -2838,25 +2879,41 @@
 #endif /* KMK */
 
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+  if (v->evalval_count != 0)
+# ifdef CONFIG_WITH_MAKE_STATS
+    printf (_(", %u evalvals (%llu ticks)"), v->evalval_count, v->cTicksEvalVal);
+# else
+    printf (_(", %u evalvals"), v->evalval_count);
+# endif
+  var_stats_evalvals += v->evalval_count;
+  var_stats_evalvaled += (v->evalval_count != 0);
+
+  if (v->expand_count != 0)
+    printf (_(", %u expands"), v->expand_count);
+  var_stats_expands += v->expand_count;
+  var_stats_expanded += (v->expand_count != 0);
+# ifdef CONFIG_WITH_COMPILER
+  if (v->evalprog != 0)
+    printf (_(", evalprog"));
+  if (v->expandprog != 0)
+    printf (_(", expandprog"));
+# endif
+#endif
+
 #ifdef CONFIG_WITH_MAKE_STATS
   if (v->changes != 0)
-      printf (_(", %u changes"), v->changes);
+    printf (_(", %u changes"), v->changes);
   var_stats_changes += v->changes;
   var_stats_changed += (v->changes != 0);
 
   if (v->reallocs != 0)
-      printf (_(", %u reallocs"), v->reallocs);
+    printf (_(", %u reallocs"), v->reallocs);
   var_stats_reallocs += v->reallocs;
   var_stats_realloced += (v->reallocs != 0);
 
   if (v->references != 0)
-      printf (_(", %u references"), v->references);
+    printf (_(", %u references"), v->references);
   var_stats_references += v->references;
   var_stats_referenced += (v->references != 0);
-
-  if (v->cEvalVals != 0)
-      //printf (_(", %u evalvals (%llu ticks)"), v->cEvalVals, v->cTicksEvalVal);
-      printf (_(", %u evalvals (%llu ms)"), v->cEvalVals, v->cTicksEvalVal / 3299998);
-  var_stats_evalvals += v->cEvalVals;
-  var_stats_evalvaled += (v->cEvalVals != 0);
 
   var_stats_val_len += v->value_length;
@@ -2914,4 +2971,8 @@
 print_variable_set (struct variable_set *set, char *prefix)
 {
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+  var_stats_expands = var_stats_expanded = var_stats_evalvals
+    = var_stats_evalvaled = 0;
+#endif
 #ifdef CONFIG_WITH_MAKE_STATS
   var_stats_changes = var_stats_changed = var_stats_reallocs
@@ -2919,4 +2980,5 @@
     = var_stats_val_len = var_stats_val_alloc_len
     = var_stats_val_rdonly_len = 0;
+#endif
 
   hash_map_arg (&set->table, print_variable, prefix);
@@ -2924,4 +2986,5 @@
   if (set->table.ht_fill)
     {
+#ifdef CONFIG_WITH_MAKE_STATS
       unsigned long fragmentation;
 
@@ -2953,8 +3016,18 @@
                (unsigned int)((100.0 * var_stats_referenced) / set->table.ht_fill),
                var_stats_references);
+#endif
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+      if (var_stats_evalvals)
+        printf(_("#   evalvaled %5lu (%2u%%),    evalval calls %6lu\n"),
+               var_stats_evalvaled,
+               (unsigned int)((100.0 * var_stats_evalvaled) / set->table.ht_fill),
+               var_stats_evalvals);
+      if (var_stats_expands)
+        printf(_("#    expanded %5lu (%2u%%),          expands %6lu\n"),
+               var_stats_expanded,
+               (unsigned int)((100.0 * var_stats_expanded) / set->table.ht_fill),
+               var_stats_expands);
+#endif
       }
-#else
-  hash_map_arg (&set->table, print_variable, prefix);
-#endif
 
   fputs (_("# variable set hash-table stats:\n"), stdout);
Index: /trunk/src/kmk/variable.h
===================================================================
--- /trunk/src/kmk/variable.h	(revision 2764)
+++ /trunk/src/kmk/variable.h	(revision 2765)
@@ -113,6 +113,13 @@
     unsigned int reallocs;     /* Realloc on value count.  */
     unsigned int references;   /* Lookup count.  */
-    unsigned cEvalVals;        /* $(evalval v) or $(evalvalctx v) count */
     unsigned long long cTicksEvalVal; /* Number of ticks spend in cEvalVal. */
+#endif
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+    unsigned int evalval_count; /* Times used with $(evalval ) or $(evalctx ). */
+    unsigned int expand_count;  /* Times expanded (not to be confused with exp_count). */
+#endif
+#ifdef CONFIG_WITH_COMPILER
+    struct cceval *evalprog;    /* Pointer to evalval/evalctx "program". */
+    struct ccexpand *expandprog; /* Pointer to variable expand "program". */
 #endif
   };
