VDL codegen for Swift.

The codegen is largely complete. The following are missing:

- Generating const values for type Any
- vdl.Type support for VOM reflection/introspection
- TypeObject support, which requires vdl.Type
- Param support for Errors
- RPC support, which requires VOM.
- Proper integration with Xcode

Reach:
- A post-process code re-formatter to make the generated code have
  the correct spacing, etc.

Notes:
- Currently v23 won't compile until we have support for migrating
  away from v23's types that use reserved words in Swift. This
  will come in another CL.
- We don't support the fixed length VDL type explicitly -- instead
  that gets deferred to VOM. The reason is that Swift's type system
  cannot express a fixed length array, so we can only error at
  runtime. If we are to error at runtime, then we must either wrap
  arrays and monitor their length, or use getter/setters to monitor
  the length there, or enforce at VOM. The last option is currently
  preferrable as it allows for VDL generated code to be more idiomatic
  by directly using Arrays. This might change in the future.

MultiPart: 3/4
Change-Id: I6c5bdb65f15751e605d98863e5ecb89571344b80
diff --git a/cmd/vdl/doc.go b/cmd/vdl/doc.go
index 767334a..fc6f2fc 100644
--- a/cmd/vdl/doc.go
+++ b/cmd/vdl/doc.go
@@ -84,16 +84,29 @@
    If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
    commas to separate multiple rules; the first rule matching src is used, and
    if there are no matching rules, the package remains unchanged.  The special
-   dst SKIP indicates matching packages are skipped.
+   dst SKIP indicates those packages containing the string are skipped. Note
+   this skip behavior is slightly different than the -out-dir semantics which is
+   prefix-based.
  -js-out-dir=release/go/src->release/javascript/core/src,roadmap/go/src->release/javascript/core/src,third_party/go/src->SKIP,tools/go/src->SKIP,release/go/src/v.io/v23/vdlroot->SKIP
    Same semantics as --go-out-dir but applies to js code generation.
  -js-relative-path-to-core=
    If set, this is the relative path from js-out-dir to the root of the JS core
  -lang=Go
    Comma-separated list of languages to generate, currently supporting
-   Go,Java,Javascript
+   Go,Java,Javascript,Swift
  -status=true
    Show package names as they are updated
+ -swift-out-dir=release/go/src->release/swift/lib/generated-src/vdl,roadmap/go/src->release/swift/lib/generated-src/vdl
+   Same semantics as --go-out-dir but applies to Swift code generation.
+ -swift-out-pkg=v.io/x->SKIP,/internal->SKIP,/testdata->SKIP,v.io/v23->
+   Swift output package translation rules.  Must be of the form:
+      "src->dst[,s2->d2...]"
+   If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
+   commas to separate multiple rules; the first rule matching src is used, and
+   if there are no matching rules, the package remains unchanged.  The special
+   dst SKIP indicates those packages containing the string are skipped. Note
+   this skip behavior is slightly different than the -out-dir semantics which is
+   prefix-based.
 
  -ignore_unknown=false
    Ignore unknown packages provided on the command line.
@@ -172,16 +185,29 @@
    If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
    commas to separate multiple rules; the first rule matching src is used, and
    if there are no matching rules, the package remains unchanged.  The special
-   dst SKIP indicates matching packages are skipped.
+   dst SKIP indicates those packages containing the string are skipped. Note
+   this skip behavior is slightly different than the -out-dir semantics which is
+   prefix-based.
  -js-out-dir=release/go/src->release/javascript/core/src,roadmap/go/src->release/javascript/core/src,third_party/go/src->SKIP,tools/go/src->SKIP,release/go/src/v.io/v23/vdlroot->SKIP
    Same semantics as --go-out-dir but applies to js code generation.
  -js-relative-path-to-core=
    If set, this is the relative path from js-out-dir to the root of the JS core
  -lang=Go
    Comma-separated list of languages to generate, currently supporting
-   Go,Java,Javascript
+   Go,Java,Javascript,Swift
  -status=true
    Show package names as they are updated
+ -swift-out-dir=release/go/src->release/swift/lib/generated-src/vdl,roadmap/go/src->release/swift/lib/generated-src/vdl
+   Same semantics as --go-out-dir but applies to Swift code generation.
+ -swift-out-pkg=v.io/x->SKIP,/internal->SKIP,/testdata->SKIP,v.io/v23->
+   Swift output package translation rules.  Must be of the form:
+      "src->dst[,s2->d2...]"
+   If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
+   commas to separate multiple rules; the first rule matching src is used, and
+   if there are no matching rules, the package remains unchanged.  The special
+   dst SKIP indicates those packages containing the string are skipped. Note
+   this skip behavior is slightly different than the -out-dir semantics which is
+   prefix-based.
 
  -ignore_unknown=false
    Ignore unknown packages provided on the command line.
diff --git a/cmd/vdl/main.go b/cmd/vdl/main.go
index 3fd4a0b..4da7134 100644
--- a/cmd/vdl/main.go
+++ b/cmd/vdl/main.go
@@ -24,6 +24,7 @@
 	"v.io/x/ref/lib/vdl/codegen/golang"
 	"v.io/x/ref/lib/vdl/codegen/java"
 	"v.io/x/ref/lib/vdl/codegen/javascript"
+	"v.io/x/ref/lib/vdl/codegen/swift"
 	"v.io/x/ref/lib/vdl/compile"
 	"v.io/x/ref/lib/vdl/vdlutil"
 )
@@ -273,7 +274,7 @@
 // xlateSrcDst specifies a translation rule, where src must match the suffix of
 // the path just before the package path, and dst is the replacement for src.
 // If dst is the special string "SKIP" we'll skip generation of packages
-// matching the src.
+// where the path CONTAINS src.
 type xlateSrcDst struct {
 	src, dst string
 }
@@ -354,6 +355,18 @@
 	optGenJavaOutPkg = xlateRules{
 		{"v.io", "io/v"},
 	}
+	optGenSwiftOutDir = genOutDir{
+		rules: xlateRules{
+			{"release/go/src", "release/swift/lib/generated-src/vdl"},
+			{"roadmap/go/src", "release/swift/lib/generated-src/vdl"},
+		},
+	}
+	optGenSwiftOutPkg = xlateRules{
+		{"v.io/x", "SKIP"},
+		{"/internal", "SKIP"},
+		{"/testdata", "SKIP"},
+		{"v.io/v23", ""},
+	}
 	optPathToJSCore string
 	// Default to just running the go lang; other langs need special setup.
 	optGenLangs = genLangs{vdltool.GenLanguageGo}
@@ -417,12 +430,22 @@
 If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
 commas to separate multiple rules; the first rule matching src is used, and if
 there are no matching rules, the package remains unchanged.  The special dst
-SKIP indicates matching packages are skipped.`)
+SKIP indicates those packages containing the string are skipped. Note this skip
+behavior is slightly different than the -out-dir semantics which is prefix-based.`)
 	cmdGenerate.Flags.Var(&optGenJavascriptOutDir, "js-out-dir",
 		"Same semantics as --go-out-dir but applies to js code generation.")
 	cmdGenerate.Flags.StringVar(&optPathToJSCore, "js-relative-path-to-core", "",
 		"If set, this is the relative path from js-out-dir to the root of the JS core")
-
+	cmdGenerate.Flags.Var(&optGenSwiftOutDir, "swift-out-dir",
+		"Same semantics as --go-out-dir but applies to Swift code generation.")
+	cmdGenerate.Flags.Var(&optGenSwiftOutPkg, "swift-out-pkg", `
+Swift output package translation rules.  Must be of the form:
+   "src->dst[,s2->d2...]"
+If a VDL package has a prefix src, the prefix will be replaced with dst.  Use
+commas to separate multiple rules; the first rule matching src is used, and if
+there are no matching rules, the package remains unchanged.  The special dst
+SKIP indicates those packages containing the string are skipped. Note this skip
+behavior is slightly different than the -out-dir semantics which is prefix-based.`)
 	// Options for audit are identical to generate.
 	cmdAudit.Flags = cmdGenerate.Flags
 }
@@ -454,12 +477,23 @@
 	return len(config.GenLanguages) == 0 || ok
 }
 
+// builtPackage is a temp struct used in gen for storing the built packages
+// and their associated targets
+type builtPackage struct {
+	target *build.Package
+	pkg    *compile.Package
+}
+
 // gen generates the given targets with env.  If audit is true, only checks
 // whether any packages are stale; otherwise files will actually be written out.
 // Returns true if any packages are stale.
 func gen(audit bool, targets []*build.Package, env *compile.Env) bool {
 	anychanged := false
+	// Cache original file-system directories for Swift codegen (which needs to
+	// traverse the filesystem to find declarations of SwiftModule in vdl.config)
+	genPathToDir := map[string]string{}
 	for _, target := range targets {
+		genPathToDir[target.GenPath] = target.Dir
 		pkg := build.BuildPackage(target, env)
 		if pkg == nil {
 			// Stop at the first package that fails to compile.
@@ -536,6 +570,32 @@
 				if writeFile(audit, data, dir, "index.js", env, nil) {
 					pkgchanged = true
 				}
+			case vdltool.GenLanguageSwift:
+				if !shouldGenerate(pkg.Config, vdltool.GenLanguageSwift) {
+					continue
+				}
+				pkgPath, err := xlatePkgPath(pkg.GenPath, optGenSwiftOutPkg)
+				if handleErrorOrSkip("--swift-out-pkg", err, env) {
+					continue
+				}
+				dir, err := xlateOutDir(target.Dir, target.GenPath, optGenSwiftOutDir, pkgPath)
+				if handleErrorOrSkip("--swift-out-dir", err, env) {
+					continue
+				}
+				swift.SetPkgPathXlator(func(pkgPath string) string {
+					result, _ := xlatePkgPath(pkgPath, optGenSwiftOutPkg)
+					return result
+				})
+				for _, file := range swift.Generate(pkg, env, genPathToDir) {
+					if optGenSwiftOutDir.dir == "" {
+						panic("optGenSwiftOurDir.Dir must be defined")
+					}
+					relativeDir := strings.TrimPrefix(dir, optGenSwiftOutDir.dir)
+					fileDir := filepath.Join(optGenSwiftOutDir.dir, file.Module, relativeDir, file.Dir)
+					if writeFile(audit, file.Data, fileDir, file.Name, env, nil) {
+						pkgchanged = true
+					}
+				}
 			default:
 				env.Errors.Errorf("Generating code for language %v isn't supported", gl)
 			}
@@ -640,12 +700,12 @@
 
 func xlatePkgPath(pkgPath string, rules xlateRules) (string, error) {
 	for _, xlate := range rules {
+		if xlate.dst == "SKIP" && strings.Contains(pkgPath, xlate.src) {
+			return pkgPath, errSkip
+		}
 		if !strings.HasPrefix(pkgPath, xlate.src) {
 			continue
 		}
-		if xlate.dst == "SKIP" {
-			return pkgPath, errSkip
-		}
 		return xlate.dst + pkgPath[len(xlate.src):], nil
 	}
 	return pkgPath, nil
diff --git a/lib/vdl/build/internal/builtin_vdlroot/builtin_vdlroot.go b/lib/vdl/build/internal/builtin_vdlroot/builtin_vdlroot.go
index 1411b38..f4b30df 100644
--- a/lib/vdl/build/internal/builtin_vdlroot/builtin_vdlroot.go
+++ b/lib/vdl/build/internal/builtin_vdlroot/builtin_vdlroot.go
@@ -157,7 +157,7 @@
 	return a, nil
 }
 
-var _timeVdlConfig = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xac\x53\xc1\x6a\xac\x30\x14\x5d\xeb\x57\x5c\x5c\xbd\x07\x43\x84\xf7\x76\xc2\x5b\x3c\x2a\x0c\x2d\x65\xa6\x0b\x69\xd7\xc1\xdc\x71\xd2\x6a\xae\xc4\x68\x29\xc3\xfc\x7b\x73\xa3\x0e\x33\xed\xd8\x6e\x2a\x18\x4d\xee\xc9\x39\x27\x27\x49\x9a\x42\xb1\x47\x18\x54\x2d\x4a\x32\x3b\x5d\xc1\x4e\xd7\x08\x3b\xb2\xe0\xfc\x78\xe7\xa4\x51\xd2\x2a\x70\xba\x41\x68\x65\xf9\x22\x2b\x84\x11\xd9\x5b\xec\x40\x2b\x4d\x8d\x74\xba\x04\xe3\xdb\x01\x63\x4f\xe8\xde\x5a\xae\x18\x40\x59\xee\xa1\x42\x83\x56\x3a\x54\x50\x4b\x53\xf5\x7e\xbe\x88\x27\xa9\x7f\xac\xeb\x88\x6a\x71\x13\x06\x0e\x71\xb4\xa6\x0c\xfc\x27\x7a\xd2\x16\x0b\xda\x04\xce\x82\xf9\xc6\xe1\xc8\xd3\x3f\xe6\xf7\x41\x22\x78\x12\x79\xef\xc9\x35\x19\xd0\x1d\x58\x6c\xbd\x27\x34\x2c\x26\x3b\x58\xd3\x25\x44\x30\x41\x32\xf7\x92\x89\x31\x62\xfa\x0c\xfc\x93\x5c\xa0\x93\x55\xa8\xde\x36\x2d\x59\xc7\xf2\x87\x07\xe9\xf6\xd9\x88\x4a\x56\xb0\x91\x0d\xce\xbd\xe3\x31\x80\xc7\xf6\x93\xc5\x82\xb3\x5b\xb6\xc7\xe5\xd1\x1a\xff\x2d\xd9\x0a\xb5\x1f\xb3\xc4\xf1\xe6\x28\x55\xad\xcd\x35\x6b\x0c\x1e\xf7\x73\x4a\x70\x82\x8e\x36\xcf\x27\x2f\xa6\x38\xd7\x97\x2c\x0f\x42\x53\x3a\xfc\xf9\x9b\xfa\x23\x60\x89\x5c\xfa\xcd\x1a\xb8\xe1\xf7\x4e\x0e\xf2\xeb\x23\x72\xbe\xc3\x09\xd9\x4a\x3c\x93\x92\xe2\xca\xde\xce\x79\x7f\x04\xf9\xc3\x7a\x4a\x7b\x96\xe5\x7b\xb2\xcd\xb7\xbf\x1c\x29\xf5\xfa\x3b\x83\xff\x4a\x9d\x12\xe2\x54\xbb\xbe\xe5\x15\x86\x8b\xc3\x16\xbb\xd2\xea\xd6\x89\xf8\x18\xbf\x07\x00\x00\xff\xff\xaa\x9d\x6f\x24\x62\x03\x00\x00")
+var _timeVdlConfig = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xac\x53\x51\xcb\x9b\x30\x14\x7d\xd6\x5f\x71\xf1\x69\x83\x8f\x08\xdb\x9b\xb0\x87\x31\xe1\xe3\x1b\xc3\x0e\x2a\xdb\xf3\xc5\x44\x9b\x4d\x73\x25\x46\xcb\x28\xfd\xef\xcb\x8d\x5a\xda\xae\x6e\x0c\xbe\x42\xa3\xc9\x3d\x39\xe7\x78\x6e\x92\xa6\x50\x1e\x14\x4c\xb2\x15\x15\x99\x5a\x37\x50\xeb\x56\x41\x4d\x16\x9c\x5f\x1f\x1c\x1a\x89\x56\x82\xd3\x9d\x82\x1e\xab\x9f\xd8\x28\x98\x91\xa3\x55\x03\x68\xa9\xa9\x43\xa7\x2b\x30\x7e\x9c\x54\xec\x09\xdd\xaf\x9e\x2b\x06\x14\x56\x07\x68\x94\x51\x16\x9d\x92\xd0\xa2\x69\x46\xbf\x5f\xc4\x8b\xd4\x07\xd6\x75\x44\xad\xf8\x14\x16\x4e\x71\xf4\x4c\x19\xf8\x47\xf4\x5d\x5b\x55\x52\x11\x38\x4b\xe6\x9b\x97\x23\x4f\xff\x2d\xff\x12\x24\x82\x27\x91\x8f\x9e\x5c\x93\x01\x3d\x80\x55\xbd\xf7\xa4\x0c\x8b\xe1\x00\xcf\x74\x0b\x11\x4c\x90\xac\xb3\x64\x61\x8c\x98\x3e\x03\xff\x4b\x6e\xd0\xc9\x53\xa8\xbe\x74\x3d\x59\xc7\xf2\xa7\xaf\xe8\x0e\xd9\x8c\x4a\x9e\xa0\xc0\x4e\xad\xb3\xf3\x39\x80\xe7\xf1\x0f\x8b\x25\x67\xb7\x6d\x8f\xcb\xb3\x35\x7e\xdb\xb2\x15\x6a\xaf\x66\x89\xe3\xcd\x15\xca\x56\x9b\x47\xd6\x18\x3c\xf7\x73\x49\x70\x81\xce\x36\xaf\x37\x6f\xa6\xb8\xd6\xb7\x2c\x4f\x42\x53\x3a\xbd\x7b\x9f\xfa\x23\x60\x89\x5c\xfa\x8f\x6f\xe0\x81\xff\x9f\x71\xc2\xbf\x1f\x91\xeb\x0e\x27\x64\x1b\xf1\x83\x24\x8a\x07\xbd\x5d\xf3\xbe\x07\xf9\xc3\x7a\x49\x7b\x95\xdd\x1f\x75\xed\xfe\x43\xb7\xd8\x33\xc5\x8b\x0f\xd4\x4e\xd8\xde\xe9\x15\x7b\xd6\xb8\xe1\xe7\x7b\xb8\xcb\x77\x6f\x1c\x49\x79\x7c\x9b\xc1\x47\x29\x2f\x1d\xe0\xae\x0d\x63\xcf\x09\x86\x8b\xc9\x11\x0c\x95\xd5\xbd\x13\xf1\x39\xfe\x1d\x00\x00\xff\xff\x9f\x4d\xa5\xfd\xc2\x03\x00\x00")
 
 func timeVdlConfigBytes() ([]byte, error) {
 	return bindataRead(
@@ -177,7 +177,7 @@
 	return a, nil
 }
 
-var _vdltoolConfigVdl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xe4\x58\xcf\x6f\x14\xb9\x12\x3e\x67\xfe\x0a\x8b\xcb\x03\x34\xcc\xbc\xf7\xa4\xbd\xec\x9e\xb2\x04\xa2\xac\x22\x84\x20\xcb\x1e\x10\x07\x4f\x77\xf5\x8c\x49\xb7\x3d\xd8\xee\x24\xa3\x15\xff\xfb\x7e\x55\xb6\xfb\xc7\x24\x80\xf6\xc7\x89\xe5\x10\xf5\xb8\xed\xaa\xaf\xbe\xfa\xaa\x5c\xcd\x7a\xad\x9e\xbb\xfd\xc1\x9b\xed\x2e\xaa\xff\xff\xf7\x7f\x3f\xa8\xab\x1d\xa9\x77\xda\xea\xda\xf4\x9d\x3a\xed\xe3\xce\xf9\xb0\x52\xa7\x6d\xab\x64\x53\x50\x9e\x02\xf9\x1b\xaa\x57\x0b\x1c\xfe\x35\x90\x72\x8d\x8a\x3b\x13\x54\x70\xbd\xaf\x48\x55\xae\x26\x85\x9f\x5b\x77\x43\xde\x52\xad\x36\x07\xa5\xd5\xcf\x6f\xcf\x9e\x85\x78\x68\x89\x4f\xb5\xa6\x22\x8b\x93\x71\xa7\xa3\xaa\xb4\x55\x1b\x52\x8d\xeb\x6d\xad\x8c\xc5\x22\xa9\xcb\x8b\xe7\x2f\x5e\xbd\x7d\xa1\x1a\xd3\xd2\x6a\xc1\x47\x5e\xeb\xea\x5a\x6f\x49\xdd\xd4\x6d\x74\xae\x55\x35\x35\xc6\x52\x50\xf1\xb0\xc7\xdf\x3e\x24\x3f\x7c\x16\x3b\x94\x6c\x31\x31\x50\xdb\x2c\x61\xb3\x6a\xfb\xda\xd8\x2d\xbf\x66\x5b\x8d\xf3\x1d\x1c\x03\x37\xf6\xae\x2a\x67\x1b\xb3\x15\x57\x61\xb5\xd8\xcf\xfd\x88\xef\xe7\x69\x47\xd8\x53\x65\x1a\xc3\x4e\x77\x1c\x26\x2f\xf6\x5e\x47\xe3\x2c\x9b\x9c\x39\x5f\x29\x10\x09\x12\x8c\x20\x34\x95\x6e\xdb\x03\x9b\xf2\xb4\x67\xfe\x6c\x24\x89\xd5\xed\xf9\xb4\x6e\xd5\xa3\x11\xc9\xa3\x04\x85\x5f\x93\xae\x76\x62\x32\x53\x9b\xc1\xc1\xf8\x0b\xbc\x61\x7b\x47\x01\x28\xd3\xed\x41\xae\x89\xed\x81\x1f\x9d\x8f\x21\xe5\x66\x72\x72\xb5\x5d\xa9\x83\xeb\x55\xa7\x0f\x80\xd3\x10\x80\xbb\x6c\x4a\x90\xe7\x68\x73\x26\xee\x01\x53\xb7\x06\x9a\xe8\xa3\xa2\xbb\x23\x57\xcc\x70\x31\xb2\xe0\xbc\x0c\xc4\x45\xdf\x57\x51\xfd\xbe\x38\x81\x9b\x73\xb2\x97\xda\x6e\x7b\xa0\x11\x2d\x45\x6f\xaa\x98\x28\x0d\x24\x49\x11\x01\x6d\xc9\x52\xe6\xb6\x2d\xdb\x81\xfe\xa2\x19\x76\x9a\x20\xf6\xa8\xdb\xc7\xc3\x52\x81\x60\x15\xfa\x3d\xe3\x00\xb5\xc3\x11\xa5\x3d\xf1\x3b\x77\x8b\xd5\xe8\x58\x68\xd9\x32\x0b\xf8\x64\x06\x06\x46\xdf\x4f\x16\x3e\x2c\xc4\x7e\xf9\xf9\x2c\xa7\xbf\x9a\x67\x3e\xb0\x15\xa7\xca\xbf\x73\x97\x62\x5e\x9c\xfc\xa2\x6f\x74\x5e\xe4\xc7\xe9\x72\xa8\xbc\xd9\x47\x35\x3e\xe6\x97\x9f\x45\x6d\x13\x08\x8a\x6c\xdf\x09\xd8\x44\xd0\xb5\x75\xb7\xf6\x2b\xfc\x24\xd6\x8f\x0d\x30\xf1\xe7\x2e\xb9\x9e\x02\x28\xfe\xdc\x3d\x7d\x6f\x9d\x7a\x38\xda\xe2\xc1\x3d\x94\xd9\xdf\x8c\xa7\x2b\xf7\x0a\x1b\x6f\xe8\x4a\xca\x72\x5e\x31\x9d\xde\xef\x59\x23\x8d\x77\x1d\x3a\xc2\xbb\xb3\x4b\x68\x09\xe9\x11\x93\xc8\x0d\xea\x55\x31\x4e\x98\xb2\x62\x24\xbd\x19\x4a\x26\x21\x18\x0b\xcb\x23\xb7\x10\x9f\xd4\xbe\x46\xef\x20\x1d\x0e\x6c\xa7\x20\x26\x31\x85\xea\x77\xde\x53\x05\x9d\xfe\x84\xbd\x4c\x0a\xce\x56\x3d\xd6\x2c\x6b\xb7\x48\x30\xe9\x23\xd7\x49\x48\xad\x89\xc5\x33\xca\x5c\xcc\xdd\xee\x4c\xa4\xd6\x84\xa4\x9f\xf5\xfa\x0b\x91\xf3\xc9\x8e\xb4\x8d\xd2\x19\x02\xda\x9d\xf6\xc6\x05\x1c\x27\x8e\x58\xfe\x02\x06\x5a\x9f\xa9\x8d\x43\x37\x02\xd3\x39\x76\x09\x5a\x82\x42\x09\xa2\x50\xbd\x24\x7c\xa9\x36\xa8\x39\xae\x5b\x4b\x1c\x2f\xa8\x47\xcc\xda\xd7\xc2\xe3\x9c\x23\xf1\xc9\xd4\x8a\xbd\xca\x75\x7b\x2c\x6f\x4c\x6b\xe2\xa1\x34\x00\xce\x07\x1f\x8c\xa6\x1b\xda\xca\xd0\x53\xcf\x4a\x57\x63\x56\xaf\x78\x07\x0c\xa6\xe8\x39\x5f\x33\x83\x09\xd7\x2d\xda\x02\x07\xcb\x66\x87\xfa\x4a\x42\x05\xa9\xbd\xb4\x7a\x1a\x21\x97\x48\x27\xce\x47\x32\xf9\x02\xba\xa6\x43\xba\x56\x44\x35\xd2\x45\xf1\x68\x75\x47\x65\x59\xc0\x33\x53\x8f\xf5\xb5\x4e\x09\xc0\xaf\x27\x4b\x4e\x10\x9a\x66\xd7\x87\x28\xd6\x36\x25\xac\xe1\x6e\xe1\x7e\x5a\x22\xd6\x21\xb8\xca\x08\x58\x6e\x6b\xe5\xfd\xb4\xa5\xce\x81\x4d\x6b\x0f\x24\xe3\x3c\x0a\x34\xa1\xa3\x3b\x56\x85\xad\x04\xa2\x86\x0b\xe3\x53\x37\xb3\xb8\x07\x83\xa4\xa5\xb7\x95\xf4\x8c\x9c\x17\x7e\x21\x5d\x73\x43\xf1\x96\x28\xc1\x13\x8a\x99\xf8\x49\x0d\x84\xa5\xac\xdc\x1a\x34\x39\xdd\xc7\xa4\x17\xbe\x52\x14\xff\x15\x6b\x8c\xfa\x0d\x6d\x19\x82\x4f\x42\x1c\x22\x02\xfb\xc5\xb3\x50\x18\xc6\x90\x4e\x19\x7f\xbe\x19\x67\xf4\x16\x42\x99\xfa\x97\xce\xfd\x28\xbb\x95\xd8\x81\x18\x5c\x11\xfb\xe3\x3b\x7e\xbb\x54\x56\x3d\x4d\x0b\x4f\x14\x79\x9f\xc5\x32\x6e\x7f\x89\x8a\x1f\x0e\x3c\xcd\x27\x8e\x0e\xdc\xaf\x21\x64\xfe\x3d\xd7\xa6\xdd\x7e\x38\x77\xbc\x34\x34\x2c\x41\x56\x13\xb7\xb1\x4d\x66\x1f\x3d\x58\xe4\x60\x6c\xba\xdd\x45\xbe\x47\xd9\xd5\x83\x6a\x64\x76\x79\x4b\x48\xf6\xca\xb8\xf5\xdd\x1a\xf7\xe0\xba\x35\x9b\x35\x58\x5c\xa3\xd9\xc6\x5a\x47\xbd\xce\x09\xe0\x62\xa2\x3b\x8d\x8b\x75\xec\xb0\x09\xc1\xac\xfb\x15\xb6\xa6\x60\xb2\xf6\x21\xbc\x79\x51\xf0\x4c\x82\x44\xe9\xfa\x58\xcd\x72\xc3\xa5\xda\x98\x98\xf1\xf4\xa9\x07\x3b\x68\x17\x75\x6d\xf2\xc0\x90\x6f\xf7\x65\xee\xb1\x69\xf4\xc9\xad\xa3\x8c\x3a\x6c\x67\xa8\xb9\xd6\x41\x2b\x83\xf0\x25\xd7\xdc\x85\x92\xb2\x74\x1b\xdc\xcc\x52\x32\x3f\x6c\x37\x56\x8c\x5d\x24\xa7\xd0\x4f\x89\x1f\xae\xa6\x6f\xa4\xef\x65\xe8\xc3\xfc\xf1\x45\x12\x72\x5c\xc3\xe4\x76\x25\x99\x39\x29\xb6\xde\x23\xed\xe9\x79\x48\x7c\xfa\x39\x49\xfd\xe0\x67\x9a\xf8\x21\x4b\x79\xfb\x2c\x4f\xaf\x35\x94\x90\xf3\x54\xc2\xdb\x6b\xa9\x14\x74\xfc\xde\x9a\x4f\x3d\xdf\x2a\xa6\x46\x37\x1d\xef\xae\xe4\x04\x50\xc7\x76\x25\x86\x26\x14\xbc\x62\x4a\x1f\xe8\x54\x03\x87\xc5\xa2\xc4\xcb\xa7\x91\xed\xb3\x5e\x54\x72\xee\x52\x3b\xb0\xd2\x1e\x96\xe9\xe2\x8a\xb3\xe9\x51\x7d\x44\x4b\x13\x83\x1b\x8d\x4e\x9f\x1d\xb0\x99\xd4\x82\x79\x9c\xdb\xa4\xc9\x08\x06\x83\xeb\x08\x83\x5f\x86\x56\x9b\x06\x73\x1e\xac\x2b\xd3\x3c\x18\x8e\xaa\x1d\x05\xfb\x1f\xbe\xad\x78\x56\x3a\xc2\x83\x60\x25\xb8\x1c\x6c\x4a\xc6\x38\xd4\x4c\xae\xf9\x8f\x3c\xf4\x7c\x75\x74\x98\x1e\xfb\xa7\x87\x87\x34\xe0\xfc\x5b\xc7\x87\x21\xfa\xef\x77\x80\x70\x7e\xbb\xfa\xe8\x6a\xbd\x62\xaf\x62\xef\x3b\x99\x1e\x74\x2c\xdf\x94\xf7\x66\x85\x74\xeb\x6f\x58\xc8\xe9\x76\xa7\x3a\x0b\x33\x55\xdb\x04\xd0\xea\x1b\xb7\x68\xae\xdf\x51\x73\xd8\xf0\x46\x5a\xc9\x9f\xaa\x36\x21\x32\x95\x9c\x98\x92\x2f\x9d\x69\xc9\xf1\x86\x23\x75\x4f\x3c\x7d\x53\xdb\xa3\x3b\x3e\x50\x66\xa5\xa6\x95\xef\x44\x84\xcd\xbd\x0d\x6a\x39\x8c\xa4\x4f\x11\x88\x93\xa5\x22\x88\x74\x99\xa1\x5f\xe0\x73\x7b\x4b\x7e\x2c\x8e\xca\xf5\x6d\xcd\x9c\xf2\x66\x14\x40\xde\x20\x80\xaa\x16\x70\xa0\xf3\x11\xff\x8e\xf8\x9b\xab\xdb\x88\x0c\xc4\xe7\x3d\x96\x97\xe9\x2b\xbb\x21\x1d\xfb\xf2\xc1\xc9\xff\x2b\xc1\x34\xe9\x18\xf9\x63\x9d\x4d\x8d\x49\xc5\x7a\xd1\x20\x7f\xd6\xbe\x1c\x67\x8c\x25\xd7\x42\xfa\x36\x17\xa2\x4f\xab\x8a\x42\xb8\x44\xea\x87\x13\x39\xff\xb0\xc1\x40\x26\x1b\xb8\xdc\x22\xc3\x65\xd9\x1f\xbd\xc3\x6e\x6e\x05\xc7\xc9\x4a\x63\xe0\xb8\x2d\x15\x40\x29\xe4\x11\xb0\xb3\x43\x6a\x78\x38\xfa\x2b\x05\x37\x28\x68\x5a\x66\xc8\x42\xba\xa2\xfe\x6e\x99\x1d\xcb\xec\xbe\xee\xc7\x7b\x6b\xfa\xd5\x7d\x74\x7b\xe5\x6f\xf3\x6f\xde\x61\x73\x13\xe5\x26\xfb\xbc\xf8\x23\x00\x00\xff\xff\xb3\x86\x67\x23\x51\x13\x00\x00")
+var _vdltoolConfigVdl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xe4\x59\xdf\x6f\x1c\xb7\x11\x7e\xb6\xfe\x0a\x42\x28\x50\x27\xb8\xdc\xb6\x29\xfa\xd2\x3e\xb9\x92\x2d\x28\x30\x14\xc3\x92\x93\x02\x46\x1e\x78\xbb\xbc\x3b\x5a\x7b\xcb\x0d\xc9\xbd\xd3\xa1\xc8\xff\xde\x6f\x66\xc8\x5d\xee\x49\xb6\x91\x36\x4f\xb6\x1f\x84\xbd\x5d\x72\x7e\x7e\xf3\xcd\x90\xae\x2a\x75\xe1\xfa\xa3\xb7\x9b\x6d\x54\xdf\xff\xe5\xaf\x7f\x57\x77\x5b\xa3\x7e\xd2\x9d\x6e\xec\xb0\x53\x2f\x86\xb8\x75\x3e\x2c\xd5\x8b\xb6\x55\xbc\x28\x28\x6f\x82\xf1\x7b\xd3\x2c\xcf\xb0\xf9\x5d\x30\xca\xad\x55\xdc\xda\xa0\x82\x1b\x7c\x6d\x54\xed\x1a\xa3\xf0\x73\xe3\xf6\xc6\x77\xa6\x51\xab\xa3\xd2\xea\x5f\xb7\x97\xdf\x85\x78\x6c\x0d\xed\x6a\x6d\x6d\x3a\xec\x8c\x5b\x1d\x55\xad\x3b\xb5\x32\x6a\xed\x86\xae\x51\xb6\xc3\x4b\xa3\x5e\x5f\x5f\xbc\xbc\xb9\x7d\xa9\xd6\xb6\x35\xcb\x33\xda\xf2\x46\xd7\xf7\x7a\x63\xd4\xbe\x69\xa3\x73\xad\x6a\xcc\xda\x76\x26\xa8\x78\xec\xf1\x77\x08\xa2\x87\xf6\x62\x85\xe2\x25\x36\x06\xd3\xae\x17\x90\x59\xb7\x43\x63\xbb\x0d\x7d\x26\x59\x6b\xe7\x77\x50\x0c\xbb\xb1\x76\x59\xbb\x6e\x6d\x37\xac\x2a\x2c\xcf\xfa\xb9\x1e\xd6\x7d\x21\x2b\x42\x6f\x6a\xbb\xb6\xa4\x74\x4b\x6e\xd2\xcb\xc1\xeb\x68\x5d\x47\x22\x67\xca\x97\x0a\x81\x44\x10\x2c\x5b\x68\x6b\xdd\xb6\x47\x12\xe5\x4d\x4f\xf1\xeb\xa2\x61\x5f\x5d\x4f\xbb\x75\xab\xce\x27\x4b\xce\xc5\x14\xfa\x6c\x74\xbd\x65\x91\x29\xb4\xc9\x38\x08\x7f\x89\x2f\x24\xef\xc4\x01\x65\x77\x3d\x82\x6b\x63\x7b\xa4\x47\xe7\x63\x90\xdc\x14\x3b\x97\x9b\xa5\x3a\xba\x41\xed\xf4\x11\xe6\xac\x0d\x0c\x77\x49\x14\x5b\x9e\xbc\x4d\x99\x78\x64\x98\x3a\x58\x60\x62\x88\xca\x3c\x9c\xa8\xa2\x08\x67\x21\x67\x94\x97\x31\x70\xd1\x0f\x75\x54\xff\x39\x7b\x06\x35\x57\xa6\x7b\xad\xbb\xcd\x00\x6b\x18\x4b\xd1\xdb\x3a\x4a\x48\x83\xe1\xa4\x30\x80\x36\xa6\x33\x29\xb6\x6d\x5e\x0e\xeb\xaf\xd7\xe3\x4a\x1b\x58\x9e\xd9\xf5\xf1\xb8\x50\x08\xb0\x0a\x43\x4f\x76\x20\xb4\xe3\x16\xa5\xbd\xa1\x6f\xee\x80\xb7\xd1\x11\xd0\x92\x64\x02\xf0\xb3\x99\x31\x10\xfa\xbe\x78\xf1\xcb\x19\xcb\xcf\x3f\xbf\x4b\xe9\xaf\xe7\x99\x0f\x24\xc5\xa9\xfc\xef\xca\x89\xcf\x67\xcf\x7e\xd0\x7b\x9d\x5e\xd2\x63\xf9\x3a\xd4\xde\xf6\x51\x4d\x8f\xf9\xe3\xed\xc1\xae\xa3\xec\xe1\xc7\xf4\xfe\x37\x46\x61\x61\x9a\x32\xdd\xb0\x63\x27\x24\x70\xf7\x9d\x3b\x74\x9f\x88\x9b\x64\xe3\x54\x00\x25\xe4\xca\x89\x49\xa5\x61\xc9\x8e\xac\xd6\x3d\x82\xff\xc6\xa9\xa7\x83\x91\x15\xb9\xa7\x12\xff\xb3\xf5\xe6\xce\xdd\x60\xe1\xde\xdc\x71\xd5\xce\x0b\x6a\xa7\xfb\x9e\x20\xb4\xf6\x6e\x07\xc2\xf8\xe9\xf2\x35\xa0\x86\xec\xb1\x48\xa4\x0e\xe5\xac\xc8\x5c\x88\xea\x58\x88\x7c\x19\x2b\x4a\x2c\x98\xea\xce\x23\xf5\xc0\x26\x53\x83\x06\xb5\x18\x1d\x8e\x24\x27\x5b\x6c\x58\x14\xc8\xc1\x79\x6f\x6a\xc0\xf8\x9f\x58\x4b\xb1\xc1\xde\x7a\xc0\xbb\x8e\xa0\x9d\x11\x2a\xf0\x49\x65\x14\x84\xb9\x08\x5b\x53\x15\xb0\xb8\xc3\xd6\x46\xd3\xda\x20\xf0\xaa\xaa\x8f\x78\x4e\x3b\x77\x46\x77\x91\x89\x23\x80\x0d\xb5\xb7\x2e\x60\xbb\x21\x8f\xf9\x2f\xcc\x00\x33\xda\xc6\x3a\x90\x15\x22\x9d\x7c\x67\xa7\xd9\x29\x54\x28\xea\xd8\x73\xde\x17\x6a\x85\x92\xa4\xb2\xee\x0c\xf9\x8b\xd0\xc3\x67\xed\x1b\x8e\xe3\x3c\x46\xac\x93\x42\xcb\xf2\x6a\xb7\xeb\xf1\x7a\x65\x5b\x1b\x8f\x99\x1f\x28\x1f\xb4\x31\xda\xdd\xc8\x3a\x23\xe5\x5e\x66\xd2\xa3\xa8\xde\xd1\x0a\x08\x14\xef\x29\x5f\x33\x81\x62\xd7\x01\xac\x41\xce\x92\xd8\xb1\xfc\x04\xaf\x08\xea\xc0\x9d\xc0\x4c\x26\x67\x4f\x0b\xe5\x53\x30\xa9\x3f\xdd\x9b\xa3\x74\x1d\x46\x0d\x93\x2c\x1e\x3b\xbd\x33\xf9\x35\x1b\x4f\x91\x7a\xae\xef\xb5\x24\x00\xbf\xbe\x59\x50\x82\xc0\xa9\xbb\x21\x44\x96\xb6\xca\x6e\x8d\xad\x87\xe8\x36\x7b\xac\x43\x70\xb5\x65\x63\x89\xf5\xf2\xf7\x92\x71\xe7\x86\x95\x25\x88\x20\x63\x3f\xea\x54\xac\x33\x0f\x84\x8a\xae\x66\x13\x35\x54\x58\x2f\x64\xd7\xa1\x4d\x06\x4e\xcb\xd0\xd5\x4c\x29\x29\x2f\xf4\x81\x49\x75\x65\xe2\xc1\x18\x31\x8f\x43\x4c\x81\x2f\x6a\x20\x2c\xf8\xcd\xc1\x82\x03\xf5\x10\x05\x2f\xd4\x71\x14\xfd\x65\x69\x64\xf5\x5b\xb3\x21\x13\xbc\x00\x71\xf4\x08\xd1\xcf\x9a\x39\x84\x61\x72\xe9\x05\xd9\x9f\x1a\xe7\x2c\xbc\x39\xa0\x14\xfa\x57\xce\xfd\x83\x57\x2b\x96\x03\x30\xb8\x0c\xf6\xe7\x0f\xf4\x75\xa1\x3a\xf5\xad\xbc\xf8\x46\x19\xef\x13\x58\xa6\xe5\xaf\x50\xf1\xe3\x86\x6f\xd3\x8e\x93\x0d\x8f\x6b\x08\x99\x7f\x4f\xb5\xd9\x6d\x7e\xb9\x72\xf4\x6a\x24\x2c\xb6\xac\x31\xc4\x66\xab\x14\x7d\x50\x34\xc3\xc1\x76\xd2\xfc\x19\xbe\x27\xd9\xd5\x23\x6a\x78\xb4\xb9\x35\x48\xf6\xd2\xba\xea\xa1\x42\x9b\xac\x5a\xbb\xaa\x10\xc5\x0a\x9c\x1b\x1b\x1d\x75\x95\x12\x40\xc5\x64\x1e\x34\xfa\xee\x44\xb4\x62\xc1\x8c\xfd\x72\xb4\x4a\x63\x12\xf6\x01\xbc\x79\x51\xd0\xc8\x82\x44\xe9\xe6\x14\xcd\xdc\x00\xa5\x36\x0a\x31\xde\xfc\x3a\x20\x3a\xa0\x8b\xa6\xb1\x69\x9e\x48\xcd\x7f\x91\x38\x56\x26\xa3\x44\x1d\x79\x12\x22\x39\x63\xcd\xb5\x0e\x58\x19\x81\xcf\xb9\x26\x16\x12\x64\xe9\x36\xb8\x99\x24\x11\x3f\x2e\xb7\x1d\x0b\xbb\x16\xa5\xc0\x4f\xf6\x1f\xaa\xca\x2f\xcc\x7b\xc9\xf4\x71\x3c\xf9\x68\x10\x92\x5f\xe3\x60\x77\xc7\x99\x79\x96\x65\xbd\x47\xda\xe5\x79\x4c\xbc\xfc\x2c\x52\x3f\xea\x29\x13\x3f\x66\x29\x2d\x9f\xe5\xe9\x8d\x06\x12\x52\x9e\xb2\x7b\xbd\xe6\x4a\x01\xe3\x0f\x9d\xfd\x75\xa0\xae\x62\x1b\xb0\xe9\xd4\xbb\x44\x09\x4c\x9d\xe8\x8a\x05\x15\x21\xb8\xa1\x90\x3e\xc1\x54\x63\x0c\xb3\x44\xf6\x97\x76\x23\xdb\x97\x03\xa3\xe4\xca\x09\x1d\x74\x4c\x0f\x0b\x69\x5c\x71\x36\x5c\xaa\x0f\xa0\x34\x16\xb8\xd2\x60\xfa\xa4\x80\xc4\x08\x05\xd3\xb4\xb7\x92\xc1\x09\x02\x83\xdb\x19\xcc\x85\xc9\xb4\xc6\xae\x31\x06\x42\xba\xb2\xeb\x27\xdd\x51\x8d\x33\xa1\xfb\x33\x75\x2b\x1a\xa5\x4e\xec\x81\xb3\xec\x5c\x72\x56\x92\x31\xcd\x3c\x45\x9b\xff\x40\x33\xd1\x27\x47\x87\x72\xdb\x1f\x3d\x3c\xc8\x9c\xf3\xb5\x8e\x0f\xa3\xf7\x5f\xee\x00\xe1\xfc\x66\xf9\xc1\x35\x7a\x49\x5a\x59\xde\x17\x32\x3d\xe8\x98\x8f\x9c\x8f\x66\x05\xe9\xfa\x2b\x02\xb2\x74\x77\xd3\x24\x60\x4a\xb5\x15\x06\x2d\x3f\xd3\x45\x53\xfd\x4e\x98\xc3\x82\xb7\x4c\x25\xbf\xab\xda\x38\x90\x52\x72\x2c\x8a\x0f\x42\x65\xc9\xd1\x82\x13\x74\x17\x9a\x3e\x8b\xed\x49\x1d\x6d\xc8\xb3\xd2\xba\xe5\x63\x24\xdc\x26\x6e\x03\x5a\x8e\x53\xd0\x4b\x0b\x58\xc9\x42\x19\x80\x74\x91\x4c\xbf\xc6\x69\x7c\x63\xfc\x54\x1c\xb5\x1b\xda\x86\x62\x4a\x8b\x51\x00\x69\x01\x1b\x54\xb7\x30\x07\x38\x9f\xec\xdf\x1a\x3a\x7a\xed\x56\x0c\x03\xd6\xf9\x28\xca\x0b\x39\x84\xaf\x8d\x8e\x43\x3e\x8f\xd2\xa5\x05\x85\x49\xc7\x48\x67\x79\x12\x35\x25\x15\xef\x33\x06\xe9\xd4\xfb\x6a\x9a\x31\x16\x54\x0b\x72\x74\xe7\x40\xbf\xa8\x6b\x13\xc2\x6b\xa4\x7e\xdc\x91\xf2\x0f\x19\x64\x48\xb1\x80\xca\x2d\x92\xb9\x04\xfb\x93\x6f\x58\x4d\x54\x70\x9a\x2c\x19\x03\xa7\x65\x52\x00\xb9\x90\x27\x83\x5d\x37\xa6\x86\x86\xa3\xff\xa5\xe0\x46\x04\x95\x65\x86\x2c\x48\x8b\xfa\x7f\xcb\xec\x14\x66\x8f\x71\x3f\xf5\xad\xf2\x50\x7e\xd2\xbd\xd2\xd1\xfd\xb3\x3d\x6c\x2e\x22\x77\x32\x51\x51\x1c\xed\x0b\xe9\x81\xcf\xfe\x4f\x0b\x4e\xd7\x4b\xc5\x3d\x0e\xc9\xb9\x71\x31\x5d\xa1\x61\xe0\xe9\x6d\x94\xea\x28\xa5\xcb\xf5\x52\xe0\xed\x5a\x6d\x90\xd4\x6e\x0c\xdb\x73\x09\x72\xd8\x26\xb0\xf3\x15\x90\xf1\x47\x6e\x7c\x14\xe7\xde\x6b\x24\xb7\x66\xda\xa3\xe6\x4e\x3c\xc3\xbd\x01\x50\xa1\x0b\x87\x47\x49\x14\x0f\x76\xae\x19\xe4\x96\x2f\xf1\xd6\x64\x35\x30\xdb\xca\x9d\x85\xe3\x6e\xe8\x5d\x6f\x3c\xf5\xd8\xae\x01\xad\x51\xbf\xc9\xd3\xda\x8a\x2e\x03\x51\x68\x58\x9b\x0e\x3f\x24\x10\x1b\x3e\xa0\xd5\x86\x6a\xed\xa1\xf6\xe0\xfc\x7d\xa8\x44\x5d\xa0\x80\xd0\x92\x9f\x69\x56\x11\xa5\x98\xa2\x18\x35\x44\x54\x5a\xae\xae\x68\x52\x82\x03\xe7\x6c\xa9\xec\x3c\x4f\x97\x90\x0e\xbd\x0d\x53\xb7\xfa\xe1\xdd\xed\x5d\xbe\x27\x2c\x9d\xbb\x2d\x9c\x53\x89\x8f\xbd\x73\x7c\x61\xc5\x4d\x94\x20\x9c\xfb\xfb\x72\x56\xb1\x24\xca\xf2\x2a\xb5\xd5\xfb\x89\xc3\xe4\x9a\x8f\x72\xc3\x02\xfe\xcd\xf4\x9f\x7c\xac\xa2\xf6\x1b\x13\xb3\xc5\xef\x56\xc6\x43\xe4\x85\x06\xa7\x42\x1a\xf4\x57\xef\x02\x62\x56\x69\xed\x5d\x57\x0d\xf8\x0c\x39\x35\x3e\xd3\x19\x65\x21\x55\x5e\x7b\xf0\x0d\x3b\xf2\xa9\xc5\x15\xb8\x6b\x59\xbe\x2b\x82\xc3\x8c\xc1\x36\x63\xda\xe4\x01\x33\xc5\x89\x84\x9e\x17\x46\x9d\x2f\x29\xf2\xac\x95\xfb\x51\x24\xd5\xd8\x7d\x2c\x1c\x4d\x5b\x73\x11\x13\x6c\x2d\x4d\x4e\x0e\x98\x83\x1e\xf6\x0b\x1b\xc2\xb0\xca\xef\x29\xfd\x9a\xd0\xe3\x63\x4e\x43\xa1\x73\x96\x92\x85\x1a\x5a\x74\x7d\xf8\x0b\x3c\xb5\x26\xd2\xb9\xf9\x2c\x9d\x93\x68\x9e\x80\x05\xfe\x63\x87\x64\x06\x8c\x91\xeb\x6d\xc5\x53\x31\xa5\xcb\xd1\x18\x15\x32\x20\x39\x43\x65\xf1\x5d\x4b\x42\x1b\x47\x63\x71\x86\x1c\x07\xa0\x73\x2b\xd7\x1c\xc7\xbe\xac\x57\xad\xb4\xc3\x42\xd0\xc8\xed\x14\x0a\x76\x63\x21\xee\x37\x72\x33\xcb\x96\x18\xfc\x1a\x7a\xe1\x34\xf3\x10\xbd\xc6\x19\x0d\xa6\xa1\x01\x85\x50\xf5\xf7\x1b\x69\x65\xea\xf9\x85\xdb\x15\xe9\xbb\x35\x7e\x8f\xa2\x0d\x6f\xbc\x5b\xdb\xc8\xd0\x9b\xce\x92\xf3\x8f\x0c\xbd\x3f\xc1\x96\xb7\x3f\xfe\x78\xf7\x18\x06\x69\x6d\xd5\xf3\xe2\x6f\x72\x85\x25\xc7\x89\x24\x18\x60\x14\xae\x1d\x05\x1f\x50\x9f\xa5\x64\x4e\x3b\x59\x8f\xc4\x88\xb1\xd4\xb7\xba\x66\x78\x96\x88\x13\xac\xa4\x02\x6b\xdd\x86\x72\x54\xd0\x41\xaa\xac\xa9\x15\xe6\xd0\x93\x2e\x3e\xad\xef\xbf\xff\x1b\x27\x9e\xef\x7a\x31\x5e\xcb\x41\x26\x4a\x8e\xf3\x7f\x6c\x5c\x38\x98\x3f\xb2\x88\xcc\x98\x86\xd8\x4f\xd2\xcf\x84\x34\x8a\x1b\x43\x21\xff\x75\xb1\x97\xb4\x95\xe2\x72\x5c\x27\x91\xa9\x15\xcc\xa8\xfe\x8f\x3e\xcf\xc8\x2d\xed\x57\x7b\xa0\x99\xdc\xff\x32\x4f\x34\x37\xb7\x97\x78\x87\x43\x0d\x9e\x48\x24\x4d\xa1\x7e\xaf\xdb\xaf\xf2\x2c\x23\xc4\xf2\xfb\x0f\x33\xbf\x9d\xfd\x37\x00\x00\xff\xff\xa4\xc2\x9a\xf1\xe2\x1c\x00\x00")
 
 func vdltoolConfigVdlBytes() ([]byte, error) {
 	return bindataRead(
diff --git a/lib/vdl/codegen/swift/generate.go b/lib/vdl/codegen/swift/generate.go
new file mode 100644
index 0000000..29046ed
--- /dev/null
+++ b/lib/vdl/codegen/swift/generate.go
@@ -0,0 +1,179 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package swift implements Swift code generation from compiled VDL packages.
+package swift
+
+import (
+	"bytes"
+	"log"
+	"path"
+	"strings"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/build"
+	"v.io/x/ref/lib/vdl/compile"
+	"v.io/x/ref/lib/vdl/vdlutil"
+)
+
+const (
+	// The data passed into every template must include a FileDoc field, which
+	// contains the comment for each generated file; e.g. the boilerplate copyright
+	// header.
+	header = `{{.FileDoc}}
+	// This file was auto-generated by the vanadium vdl tool.
+	`
+
+	// fileTmpl is the template to produce a Swift generated file
+	fileTmpl = header + `// Source: {{ .Source }}
+{{ range $import := .ImportedModules }}
+import {{ $import }}
+{{ end }}
+{{ range $tdef := .Tdefs }}
+{{ $tdef }}
+{{ end }}`
+)
+
+// pkgPathXlator is the function used to translate a VDL package path
+// into a Swift package path.  If nil, no translation takes place.
+var pkgPathXlator func(vdlPath string) (swiftPath string)
+
+// SetPkgPathXlator sets the function used to translate a VDL package
+// path into a Swift package path.
+func SetPkgPathXlator(xlator func(vdlPath string) string) {
+	pkgPathXlator = xlator
+}
+
+// swiftGenPkgPath returns the Swift package path given the VDL package path.
+func swiftGenPkgPath(vdlPkgPath string) string {
+	if pkgPathXlator == nil {
+		return vdlPkgPath
+	}
+	return pkgPathXlator(vdlPkgPath)
+}
+
+// SwiftFileInfo stores the name and contents of the generated Swift file.
+type SwiftFileInfo struct {
+	Data   []byte
+	Dir    string
+	Name   string
+	Module string
+}
+
+type swiftContext struct {
+	env *compile.Env
+	pkg *compile.Package
+	// genPathToDir allows us to lookup the filesystem dir for any pkg.GenPath
+	genPathToDir map[string]string
+	// srcDirs is the combination of VDLROOT & VDLPATHs to provide a set of
+	// root source directories. These directories provide a stop condition when
+	// traversing a package's path's parents. In particular, we do this when
+	// looking for a vdl.config to that specifies a SwiftModule.
+	srcDirs map[string]bool
+
+	// Cache
+	memoizedTypeNames map[*compile.TypeDef]string
+}
+
+// Generate generates Swift files for all VDL files in the provided package,
+// returning the list of generated Swift files as a slice. We generate Swift
+// files to match the original VDL file layout, with the exception that
+// constants are smushed into a <PackageName>.swift that consolidates the
+// errors, package documentation (if any), and constants for a given package
+// into a struct. This package struct provides a similar context to what
+// would be provided by an import in VDL or Java.
+// TODO(azinman): Run Swift formatters on the generated files.
+func Generate(pkg *compile.Package, env *compile.Env, genPathToDir map[string]string) (ret []SwiftFileInfo) {
+	srcDirs := map[string]bool{}
+	for _, dir := range build.SrcDirs(env.Errors) {
+		srcDirs[dir] = true
+	}
+
+	ctx := &swiftContext{env, pkg, genPathToDir, srcDirs, map[*compile.TypeDef]string{}}
+	validateSwiftConfig(ctx)
+	// One file for pkg documentation (if any), metadata, errors and constants.
+	if pkgData := genSwiftPackageFile(pkg, ctx); pkgData != "" {
+		ret = append(ret, SwiftFileInfo{
+			Data:   []byte(pkgData),
+			Name:   ctx.swiftPackageName(pkg) + "Package.swift",
+			Module: ctx.swiftModule(pkg),
+		})
+	}
+	for _, file := range pkg.Files {
+		if len(file.TypeDefs) == 0 {
+			// Nothing to generate
+			continue
+		}
+		// Separate file for all typedefs.
+		tdefs := []string{}
+		for _, tdef := range file.TypeDefs {
+			switch tdef.Type.Kind() {
+			case vdl.Enum:
+				tdefs = append(tdefs, genSwiftEnumTdef(tdef, ctx))
+			case vdl.Union:
+				tdefs = append(tdefs, genSwiftUnionTdef(tdef, ctx))
+			case vdl.Struct:
+				tdefs = append(tdefs, genSwiftStructTdef(tdef, ctx))
+			default:
+				tdefs = append(tdefs, genSwiftPrimitiveTdef(tdef, ctx))
+			}
+		}
+		// TODO(zinman): loop through file.Interfaces for RPC generation
+		source := path.Join(ctx.genPathToDir[pkg.GenPath], file.BaseName)
+		vdlRoot, err := ctx.vdlRootForFilePath(source)
+		if err != nil {
+			log.Fatalf("vdl: couldn't find vdl root for path %v: %v", source, err)
+		}
+		source = strings.TrimPrefix(source, vdlRoot+"/")
+		data := struct {
+			FileDoc         string
+			ImportedModules []string
+			Tdefs           []string
+			PackagePath     string
+			Source          string
+		}{
+			FileDoc:         pkg.FileDoc,
+			ImportedModules: ctx.importedModules(file.TypeDefs),
+			Tdefs:           tdefs,
+			PackagePath:     swiftGenPkgPath(pkg.GenPath),
+			Source:          source,
+		}
+		var buf bytes.Buffer
+		err = parseTmpl("swift file", fileTmpl).Execute(&buf, data)
+		if err != nil {
+			log.Fatalf("vdl: couldn't execute union template: %v", err)
+		}
+		baseName := strings.Replace(file.BaseName, path.Ext(file.BaseName), "", 1)
+		ret = append(ret, SwiftFileInfo{
+			Data:   buf.Bytes(),
+			Name:   ctx.swiftPackageName(pkg) + vdlutil.FirstRuneToUpper(baseName) + ".swift",
+			Module: ctx.swiftModule(pkg),
+		})
+	}
+	return
+}
+
+// The native types feature is hard to use correctly.  E.g. the wire type
+// must be statically registered in Swift vdl package in order for the
+// wire<->native conversion to work, which is hard to ensure.
+//
+// Restrict the feature to these whitelisted VDL packages for now.
+var nativeTypePackageWhitelist = map[string]bool{
+	"time": true,
+}
+
+func validateSwiftConfig(ctx *swiftContext) {
+	vdlconfig := path.Join(ctx.pkg.GenPath, "vdl.config")
+	// Validate native type configuration.  Since native types are hard to use, we
+	// restrict them to a built-in whitelist of packages for now.
+	if len(ctx.pkg.Config.Swift.WireToNativeTypes) > 0 && !nativeTypePackageWhitelist[ctx.pkg.Path] {
+		ctx.env.Errors.Errorf("%s: Swift.WireToNativeTypes is restricted to whitelisted VDL packages", vdlconfig)
+	}
+	// Look for a Swift module by walking up... if none found then panic
+	if ctx.swiftModule(ctx.pkg) == "" {
+		log.Fatalf("Could not find a swift module for package %v/%v; make sure to have a file named swiftmodule "+
+			"defined at the root that is a text file that ONLY contains the name of your Swift module.",
+			ctx.pkg.Path, ctx.pkg.Name)
+	}
+}
diff --git a/lib/vdl/codegen/swift/tmpl_enum.go b/lib/vdl/codegen/swift/tmpl_enum.go
new file mode 100644
index 0000000..07d8f19
--- /dev/null
+++ b/lib/vdl/codegen/swift/tmpl_enum.go
@@ -0,0 +1,73 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"bytes"
+	"log"
+
+	"v.io/x/ref/lib/vdl/compile"
+)
+
+const enumTmpl = `{{ .Doc }}///
+/// Auto-generated from {{.VdlTypeName}}
+{{ .AccessModifier }} enum {{ .Name }} : String, VdlEnum {
+    /// Vdl type for {@link {{ .Name }}}.
+    {{ .AccessModifier }} static let vdlTypeName = "{{ .VdlTypeName }}"
+
+	{{ range $index, $label := .EnumLabels }}
+	{{ $label.Doc }}
+	case {{ $label.Name }} = "{{ $label.Name }}"
+    {{ end }}
+
+    {{ .AccessModifier }} var vdlName: String {
+    	return self.rawValue
+    }
+
+    {{ .AccessModifier }} var description: String {
+    	return vdlName
+    }
+
+    {{ .AccessModifier }} var debugDescription: String {
+    	return "{{ .Name }}.\(description)"
+    }
+}`
+
+type enumLabel struct {
+	Doc  string
+	Name string
+}
+
+// genSwiftEnumFile generates the Swift class file for the provided user-defined enum type.
+func genSwiftEnumTdef(tdef *compile.TypeDef, ctx *swiftContext) string {
+	labels := make([]enumLabel, tdef.Type.NumEnumLabel())
+	for i := 0; i < tdef.Type.NumEnumLabel(); i++ {
+		labels[i] = enumLabel{
+			Doc:  swiftDoc(tdef.LabelDoc[i], tdef.LabelDocSuffix[i]),
+			Name: tdef.Type.EnumLabel(i),
+		}
+	}
+	data := struct {
+		AccessModifier string
+		Doc            string
+		EnumLabels     []enumLabel
+		Name           string
+		VdlTypeName    string
+		VdlTypeString  string
+	}{
+		AccessModifier: swiftAccessModifier(tdef),
+		Doc:            swiftDoc(tdef.Doc, tdef.DocSuffix),
+		EnumLabels:     labels,
+		Name:           ctx.swiftTypeName(tdef),
+		VdlTypeName:    tdef.Type.Name(),
+		VdlTypeString:  tdef.Type.String(),
+	}
+	var buf bytes.Buffer
+	err := parseTmpl("swift enum", enumTmpl).Execute(&buf, data)
+	if err != nil {
+		log.Fatalf("vdl: couldn't execute enum template: %v", err)
+	}
+	return formatSwiftCode(buf.String())
+}
diff --git a/lib/vdl/codegen/swift/tmpl_package.go b/lib/vdl/codegen/swift/tmpl_package.go
new file mode 100644
index 0000000..8d315c7
--- /dev/null
+++ b/lib/vdl/codegen/swift/tmpl_package.go
@@ -0,0 +1,273 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"path"
+	"path/filepath"
+	"strings"
+
+	"v.io/x/ref/lib/vdl/compile"
+	"v.io/x/ref/lib/vdl/vdlutil"
+)
+
+const packageTmpl = header + `// Source: {{ .Source }}
+{{ range $module := .ImportedModules }}
+import {{ $module }}
+{{ end }}
+
+{{ if .IsModuleRoot }}
+{{ if .Doc }}
+{{ .Doc }}
+{{ .AccessModifier }} enum Docs {}
+{{ end }} {{/* if .Doc */}}
+{{ else }}
+{{ .Doc }}
+{{ .AccessModifier }} enum {{ .PackageName }} {
+{{ end }} {{/* if .IsModuleRoot */}}
+
+  {{ range $file := .ConstFiles }}
+  /* The following constants originate in file: {{ $file.Filename }} */
+  {{ range $const := $file.Consts }}
+  {{ $const.Doc }}
+  {{ $const.AccessModifier }} {{ if not $.IsModuleRoot }}static {{ end }}let {{ $const.Name }}: {{ $const.Type }} = {{ $const.Value }}
+  {{ end }} {{/* end range $file.Consts */}}
+  {{ end }} {{/* range .ConstFiles */}}
+
+  {{ range $file := .ErrorFiles }}
+  /* The following errors originate in file: {{ $file.Filename }} */
+  {{ range $error := $file.Errors }}
+  {{ $error.Doc }}
+  {{ $error.AccessModifier }} {{ if not $.IsModuleRoot }}static {{ end }}let {{ $error.Name }} = VError(
+    identity: {{ $error.ID }},
+    action: ErrorAction.{{ $error.ActionName }},
+    msg: {{ $error.EnglishFmt }},
+    stacktrace: nil)
+  {{ end }} {{/* end range $file.Errors */}}
+  {{ end }} {{/* range .ErrorFiles */}}
+
+{{ if not .IsModuleRoot }}
+} {{/* closes the enum { */}}
+{{ end }}`
+
+type constTmplDef struct {
+	AccessModifier string
+	Doc            string
+	Type           string
+	Name           string
+	Value          string
+}
+
+type constsInFile struct {
+	Filename        string
+	Consts          []constTmplDef
+	ImportedModules []string
+}
+
+func shouldGenerateConstFile(pkg *compile.Package) bool {
+	for _, file := range pkg.Files {
+		if len(file.ConstDefs) > 0 {
+			return true
+		}
+	}
+	return false
+}
+
+func parseConstants(pkg *compile.Package, ctx *swiftContext) []constsInFile {
+	if !shouldGenerateConstFile(pkg) {
+		return nil
+	}
+
+	files := []constsInFile{}
+	for _, file := range pkg.Files {
+		if len(file.ConstDefs) == 0 {
+			continue
+		}
+		consts := make([]constTmplDef, len(file.ConstDefs))
+		tdefs := []*compile.TypeDef{}
+		for j, cnst := range file.ConstDefs {
+			consts[j].AccessModifier = swiftAccessModifierForName(cnst.Name)
+			consts[j].Doc = swiftDoc(cnst.Doc, cnst.DocSuffix)
+			consts[j].Type = ctx.swiftType(cnst.Value.Type())
+			consts[j].Name = vdlutil.FirstRuneToUpper(cnst.Name)
+			consts[j].Value = swiftConstVal(cnst.Value, ctx)
+			if tdef := ctx.env.FindTypeDef(cnst.Value.Type()); tdef != nil && tdef.Name != "" {
+				tdefs = append(tdefs, tdef)
+			}
+		}
+
+		files = append(files, constsInFile{
+			Filename:        file.BaseName,
+			Consts:          consts,
+			ImportedModules: ctx.importedModules(tdefs),
+		})
+	}
+	return files
+}
+
+// highestConstAccessModifier scans across many const definitions looking at
+// their access modifier to determine the access modifier for the package
+// that contains them. For example, if package foo contains two consts,
+// one internal and the other public, the package itself must be public
+// in order to access the public variable. If, instead, the package only
+// contained internal consts, then the package has no need to be public.
+func highestConstAccessModifier(constFiles []constsInFile) string {
+	if len(constFiles) == 0 {
+		// This is only for documentation at this point. Keep it public for others to read.
+		// TODO(zinman): Search for the highest level of any emitted type across the entire
+		// package to determine if this would be the only publicly visible artifact.
+		return "public"
+	}
+	levels := map[string]int{"private": 0, "internal": 1, "public": 2}
+	modifiers := map[int]string{0: "private", 1: "internal", 2: "public"}
+	highest := levels["private"]
+	for _, file := range constFiles {
+		for _, cnst := range file.Consts {
+			level, ok := levels[cnst.AccessModifier]
+			if !ok {
+				panic(fmt.Sprintf("Invalid access modifier: %v", cnst.AccessModifier))
+			}
+			if level > highest {
+				highest = level
+			}
+		}
+	}
+	return modifiers[highest]
+}
+
+type errorTmplDef struct {
+	AccessModifier string
+	ActionName     string
+	Doc            string
+	EnglishFmt     string
+	ID             string
+	Name           string
+}
+
+type errorsInFile struct {
+	Filename string
+	Errors   []errorTmplDef
+}
+
+func shouldGenerateErrorFile(pkg *compile.Package) bool {
+	for _, file := range pkg.Files {
+		if len(file.ErrorDefs) > 0 {
+			return true
+		}
+	}
+	return false
+}
+
+func parseErrors(pkg *compile.Package, ctx *swiftContext) []errorsInFile {
+	if !shouldGenerateErrorFile(pkg) {
+		return nil
+	}
+	errorFiles := []errorsInFile{}
+	for _, file := range pkg.Files {
+		if len(file.ErrorDefs) == 0 {
+			continue
+		}
+		errors := []errorTmplDef{}
+		for _, err := range file.ErrorDefs {
+			englishFmt := "nil"
+			if err.English != "" {
+				englishFmt = swiftQuoteString(err.English)
+			}
+			errors = append(errors, errorTmplDef{
+				AccessModifier: swiftAccessModifierForName(err.Name),
+				ActionName:     err.RetryCode.String(),
+				Doc:            swiftDoc(err.Doc, err.DocSuffix),
+				EnglishFmt:     englishFmt,
+				ID:             swiftQuoteString(err.ID),
+				Name:           vdlutil.FirstRuneToUpper(err.Name) + "Error",
+			})
+		}
+		errorFiles = append(errorFiles, errorsInFile{
+			Filename: file.BaseName,
+			Errors:   errors,
+		})
+	}
+	return errorFiles
+}
+
+func getDocFile(pkg *compile.Package) *compile.File {
+	for _, file := range pkg.Files {
+		if file.PackageDef.Doc != "" {
+			return file
+		}
+	}
+	return nil
+}
+
+func importedModulesForPkg(ctx *swiftContext, constFiles []constsInFile, errorFiles []errorsInFile) []string {
+	modules := map[string]bool{}
+	for _, constFile := range constFiles {
+		for _, module := range constFile.ImportedModules {
+			modules[module] = true
+		}
+	}
+	if ctx.swiftModule(ctx.pkg) != V23SwiftFrameworkName && errorFiles != nil && len(errorFiles) > 0 {
+		// We're going to define VErrors and we aren't generating for VandiumCore,
+		// so we must import it since that's where VError is defined
+		modules[V23SwiftFrameworkName] = true
+	}
+	return flattenImportedModuleSet(modules)
+}
+
+// genPackageFileSwift generates the Swift package info file, iif any package
+// comments were specified in the package's VDL files OR constants OR errors.
+func genSwiftPackageFile(pkg *compile.Package, ctx *swiftContext) string {
+	constFiles := parseConstants(pkg, ctx)
+	errorFiles := parseErrors(pkg, ctx)
+	doc := ""
+	docFile := getDocFile(pkg)
+	if docFile != nil {
+		doc = swiftDoc(docFile.PackageDef.Doc, docFile.PackageDef.DocSuffix)
+	}
+	// If everything is zero value then return
+	if len(constFiles) == 0 && len(errorFiles) == 0 && doc == "" {
+		return ""
+	}
+	source := path.Join(ctx.genPathToDir[pkg.GenPath], pkg.Files[0].BaseName)
+	vdlRoot, err := ctx.vdlRootForFilePath(source)
+	if err != nil {
+		log.Fatalf("vdl: couldn't find vdl root for path %v: %v", source, err)
+	}
+	source = strings.TrimPrefix(source, vdlRoot+"/")
+	source = filepath.Dir(source)
+	data := struct {
+		AccessModifier  string
+		ConstFiles      []constsInFile
+		Doc             string
+		ErrorFiles      []errorsInFile
+		FileDoc         string
+		IsModuleRoot    bool
+		ImportedModules []string
+		PackageName     string
+		PackagePath     string
+		Source          string
+	}{
+		AccessModifier:  highestConstAccessModifier(constFiles),
+		ConstFiles:      constFiles,
+		Doc:             doc,
+		ErrorFiles:      errorFiles,
+		FileDoc:         pkg.FileDoc,
+		IsModuleRoot:    ctx.swiftPackageName(pkg) == "",
+		ImportedModules: importedModulesForPkg(ctx, constFiles, errorFiles),
+		PackageName:     ctx.swiftPackageName(pkg),
+		PackagePath:     swiftGenPkgPath(pkg.GenPath),
+		Source:          source,
+	}
+	var buf bytes.Buffer
+	err = parseTmpl("swift package", packageTmpl).Execute(&buf, data)
+	if err != nil {
+		log.Fatalf("vdl: couldn't execute package template: %v", err)
+	}
+
+	return formatSwiftCode(buf.String())
+}
diff --git a/lib/vdl/codegen/swift/tmpl_primitive.go b/lib/vdl/codegen/swift/tmpl_primitive.go
new file mode 100644
index 0000000..c78c382
--- /dev/null
+++ b/lib/vdl/codegen/swift/tmpl_primitive.go
@@ -0,0 +1,75 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"bytes"
+	"log"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/compile"
+)
+
+const primitiveTmpl = `{{ .Doc }}///
+/// Auto-generated from {{.VdlTypeName}}
+{{ .AccessModifier }} struct {{.Name}} : VdlPrimitive {{ if .IsHashable }}, Hashable {{ end }} {
+  /// Vdl type for {@link {{.Name}}}.
+  {{ .AccessModifier }} static let vdlTypeName = "{{.VdlTypeName}}"
+
+  // Conform to RawRepresentable for the underlying Type
+  {{ .AccessModifier }} associatedtype RawValue = {{.RawValue}}
+  {{ .AccessModifier }} let rawValue: RawValue
+
+  /// Creates a new instance of {@link {{.Name}}} with the given value.
+  {{ .AccessModifier }} init(rawValue: {{.RawValue}}) {
+    self.rawValue = rawValue
+  }
+
+  {{ .AccessModifier }} var debugDescription: String {
+    return "{{ .Name }}(\(self.rawValue))"
+  }
+
+  {{ if .IsHashable }}
+  {{ .AccessModifier }} var hashValue: Int {
+    return self.rawValue.hashValue
+  }
+  {{ end }}
+}
+
+{{ if .IsHashable }}
+{{ .AccessModifier }} func ==(lhs: {{.Name}}, rhs: {{.Name}}) -> Bool {
+	return lhs.rawValue == rhs.rawValue
+}{{ end }}`
+
+// genSwiftPrimitiveFile generates the Swift class file for the provided user-defined type.
+func genSwiftPrimitiveTdef(tdef *compile.TypeDef, ctx *swiftContext) string {
+	data := struct {
+		AccessModifier string
+		Doc            string
+		IsHashable     bool
+		Name           string
+		Source         string
+		RawValue       string
+		VdlTypeName    string
+		VdlTypeKind    string
+		VdlTypeString  string
+	}{
+		AccessModifier: swiftAccessModifier(tdef),
+		Doc:            swiftDoc(tdef.Doc, tdef.DocSuffix),
+		IsHashable:     isTypeHashable(tdef.Type, make(map[*vdl.Type]bool)),
+		Name:           ctx.swiftTypeName(tdef),
+		Source:         tdef.File.BaseName,
+		RawValue:       ctx.swiftBuiltInType(tdef.Type),
+		VdlTypeName:    tdef.Type.Name(),
+		VdlTypeKind:    tdef.Type.Kind().String(),
+		VdlTypeString:  tdef.Type.String(),
+	}
+	var buf bytes.Buffer
+	err := parseTmpl("swift primitive", primitiveTmpl).Execute(&buf, data)
+	if err != nil {
+		log.Fatalf("vdl: couldn't execute primitive template: %v", err)
+	}
+	return formatSwiftCode(buf.String())
+}
diff --git a/lib/vdl/codegen/swift/tmpl_struct.go b/lib/vdl/codegen/swift/tmpl_struct.go
new file mode 100644
index 0000000..130fc19
--- /dev/null
+++ b/lib/vdl/codegen/swift/tmpl_struct.go
@@ -0,0 +1,175 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of self source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"bytes"
+	"log"
+
+	"fmt"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/compile"
+)
+
+const structTmpl = `{{ .Doc }}///
+/// Auto-generated from {{.VdlTypeName}}
+{{ .AccessModifier }} class {{.Name}} : VdlStruct, CustomDebugStringConvertible {{ if .IsHashable }}, Hashable {{ end }}{
+    /// Vdl type for {@link {{.Name}}}.
+    {{ .AccessModifier }} static let vdlTypeName = "{{.VdlTypeName}}"
+
+    {{/* Field declarations */}}
+    {{ range $index, $field := .Fields }}
+    /// "{{$field.VdlName}}" index {{$index}}
+    var {{$field.Name}}: {{$field.Type}}
+    {{ end }}
+
+    {{ .AccessModifier }} init({{ range $index, $field := .Fields }}{{ if gt $index 0 }},{{ end }}
+        {{$field.Name}}: {{$field.Type}}{{end}}) {
+
+      {{range $field := .Fields}}self.{{$field.Name}} = {{$field.Name}}
+      {{end}}{{/* range $field */}}
+    }
+    {{ if .IsHashable }}
+    {{ .AccessModifier }} var hashValue: Int {
+      var result = 1
+      let prime = 31
+      {{ range $field := .Fields }}result = prime * result + Int({{$field.HashcodeComputation}})
+      {{ end }}
+      return result
+    }
+    {{ end }}
+
+    {{ .AccessModifier }} var description: String {
+      return "{{ .VdlTypeName }}"
+    }
+
+    {{ .AccessModifier }} var debugDescription: String {
+      var result = "[{{ .VdlTypeName }} "
+      {{ range $index, $field := .Fields }}
+      {{ if gt $index 0 }}result += ", "{{ end }}
+      {{ if .IsAny }}
+      result += "{{$field.Name}}:" + (({{$field.Name}} as? CustomDebugStringConvertible)?.debugDescription ?? "\({{$field.Name}})")
+      {{ else }}
+      result += "{{$field.Name}}:" + {{$field.Name}}.debugDescription
+      {{ end }}{{/* IsAny */}}
+      {{ end }}{{/* range over fields */}}
+      return result + "]"
+    }
+}
+
+{{ if .IsHashable }}
+{{ .AccessModifier }} func ==(lhs: {{.Name}}, rhs: {{.Name}}) -> Bool {
+	{{ range $field := .Fields }}
+	{{ if $field.IsOptional }}
+	switch (lhs.{{$field.Name}}, rhs.{{$field.Name}}) {
+		case (nil, nil): break
+		case (nil, _): return false
+		case (_, nil): return false
+		case let (lfield?, rfield?):
+		 	if lfield != rfield {
+		 	  return false
+		 	}
+		default: break
+	}
+	{{ else }}
+	if lhs.{{$field.Name}} != rhs.{{$field.Name}} {
+		return false
+	}
+	{{ end }} {{/* optional comparison */}}
+	{{ end }} {{/* range over fields */}}
+	return true
+}{{ end }}`
+
+type structDefinitionField struct {
+	AccessModifier      string
+	Class               string
+	Doc                 string
+	HashcodeComputation string
+	IsAny               bool
+	IsOptional          bool
+	Name                string
+	Type                string
+	VdlName             string
+}
+
+func swiftFieldArgStr(tdef *compile.TypeDef, ctx *swiftContext) string {
+	var buf bytes.Buffer
+	for i := 0; i < tdef.Type.NumField(); i++ {
+		if i > 0 {
+			buf.WriteString(", ")
+		}
+		fld := tdef.Type.Field(i)
+		buf.WriteString(ctx.swiftType(fld.Type))
+		buf.WriteString(" ")
+		buf.WriteString(swiftVariableName(tdef, fld))
+	}
+	return buf.String()
+}
+
+// genSwiftStructFile generates the Swift class file for the provided user-defined type.
+func genSwiftStructTdef(tdef *compile.TypeDef, ctx *swiftContext) string {
+	isHashable := isTypeHashable(tdef.Type, make(map[*vdl.Type]bool))
+	fields := make([]structDefinitionField, tdef.Type.NumField())
+	for i := 0; i < tdef.Type.NumField(); i++ {
+		fld := tdef.Type.Field(i)
+		hashComp := ""
+		if isHashable {
+			var err error
+			hashComp, err = ctx.swiftHashCode("self."+swiftVariableName(tdef, fld), fld.Type)
+			if err != nil {
+				panic(fmt.Sprintf("Unable to compute hashcode: %v", err))
+			}
+		}
+		fields[i] = structDefinitionField{
+			AccessModifier:      swiftAccessModifierForName(fld.Name),
+			Class:               ctx.swiftType(fld.Type),
+			Doc:                 swiftDoc(tdef.FieldDoc[i], tdef.FieldDocSuffix[i]),
+			HashcodeComputation: hashComp,
+			IsAny:               fld.Type.Kind() == vdl.Any,
+			IsOptional:          fld.Type.Kind() == vdl.Optional,
+			Name:                swiftVariableName(tdef, fld),
+			Type:                ctx.swiftType(fld.Type),
+			VdlName:             fld.Name,
+		}
+	}
+
+	// Determine if we can create a hashValue out of this. A hashValue implies
+	// equality and access to primitives in a useful way. With Any types we cannot
+	// do this. One plausible hack is to use "\(x)", but if for some reason the
+	// underlying type doesn't convey enough information in its forced string
+	// conversion then we're not properly comparing.
+	data := struct {
+		AccessModifier string
+		Doc            string
+		Fields         []structDefinitionField
+		FieldsAsArgs   string
+		IsHashable     bool
+		Name           string
+		Source         string
+		VdlTypeName    string
+		VdlTypeString  string
+	}{
+		AccessModifier: swiftAccessModifier(tdef),
+		Doc:            swiftDoc(tdef.Doc, tdef.DocSuffix),
+		Fields:         fields,
+		FieldsAsArgs:   swiftFieldArgStr(tdef, ctx),
+		IsHashable:     isHashable,
+		Name:           ctx.swiftTypeName(tdef),
+		Source:         tdef.File.BaseName,
+		VdlTypeName:    tdef.Type.Name(),
+		VdlTypeString:  tdef.Type.String(),
+	}
+	var buf bytes.Buffer
+	err := parseTmpl("swift struct", structTmpl).Execute(&buf, data)
+	if err != nil {
+		log.Fatalf("vdl: couldn't execute struct template: %v", err)
+	}
+	return formatSwiftCode(buf.String())
+}
diff --git a/lib/vdl/codegen/swift/tmpl_union.go b/lib/vdl/codegen/swift/tmpl_union.go
new file mode 100644
index 0000000..2fb34d7
--- /dev/null
+++ b/lib/vdl/codegen/swift/tmpl_union.go
@@ -0,0 +1,146 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/compile"
+)
+
+const unionTmpl = `{{ .Doc }}///
+/// Auto-generated from {{.VdlTypeName}}
+{{ .AccessModifier }} enum {{.Name}} : VdlUnion {{ if .IsHashable }}, Hashable {{ end }} {
+  /// Vdl type for {@link {{.Name}}}.
+  {{ .AccessModifier }} static let vdlTypeName = "{{.VdlTypeName}}"
+
+  {{ range $index, $field := .Fields }}
+  {{ $field.Doc }}
+  /// GeneratedFromVdl(name = "{{$field.VdlName}}", index = {{$index}})
+  case {{$field.Name}}(elem:{{$field.Type}})
+  {{ end }}
+
+  {{ if .IsHashable }}
+  {{ .AccessModifier }} var hashValue: Int {
+    switch self {
+    {{ range $field := .Fields }}
+    case let .{{ $field.Name }}(elem): return {{$field.HashcodeComputation}}
+    {{ end }}
+    }
+  }
+  {{ end }}
+
+  {{ .AccessModifier }} var vdlName: String {
+    switch self {
+    {{ range $field := .Fields }}
+    case .{{ $field.Name }}: return "{{$field.VdlName}}"
+    {{ end }}
+    }
+  }
+
+  {{ .AccessModifier }} var description: String {
+    return vdlName
+  }
+
+  {{ .AccessModifier }} var debugDescription: String {
+    switch self {
+    {{ range $field := .Fields }}
+    {{ if .IsAny }}
+    case let .{{ $field.Name }}(elem): return "{{$field.VdlName}}(\(elem))"
+    {{ else }}
+    case let .{{ $field.Name }}(elem): return "{{$field.VdlName}}(\(elem.debugDescription))"
+    {{ end }}{{/* IsAny */}}
+    {{ end }}{{/* range */}}
+    }
+  }
+}
+
+{{ if .IsHashable }}
+{{ .AccessModifier }} func ==(lhs: {{.Name}}, rhs: {{.Name}}) -> Bool {
+  switch (lhs, rhs) {
+  {{ $EnumName := .Name }}
+  {{ range $field := .Fields }}
+  case ({{$EnumName}}.{{ $field.Name }}(let lElem), {{$EnumName}}.{{ $field.Name }}(let rElem)):
+  {{ if $field.IsOptional }}
+    switch (lElem, rElem) {
+    case (nil, nil): return true
+    case (nil, _): return false
+    case (_, nil): return false
+    case let (lfield?, rfield?): return lfield == rfield
+    default: return false
+    }
+  {{ else }}
+    return lElem == rElem
+  {{ end }} {{/* optional comparison */}}
+  {{ end }}
+  default: return false
+  }
+}{{ end }}`
+
+type unionDefinitionField struct {
+	AccessModifier      string
+	Class               string
+	Doc                 string
+	HashcodeComputation string
+	IsAny               bool
+	IsOptional          bool
+	Name                string
+	Type                string
+	VdlName             string
+}
+
+// genSwiftUnionFile generates the Swift class file for the provided user-defined union type.
+func genSwiftUnionTdef(tdef *compile.TypeDef, ctx *swiftContext) string {
+	fields := make([]unionDefinitionField, tdef.Type.NumField())
+	isHashable := isTypeHashable(tdef.Type, make(map[*vdl.Type]bool))
+	for i := 0; i < tdef.Type.NumField(); i++ {
+		fld := tdef.Type.Field(i)
+		hashComp := ""
+		if isHashable {
+			var err error
+			hashComp, err = ctx.swiftHashCode("elem", fld.Type)
+			if err != nil {
+				panic(fmt.Sprintf("Unable to compute hashcode: %v", err))
+			}
+		}
+		fields[i] = unionDefinitionField{
+			AccessModifier:      swiftAccessModifierForName(fld.Name),
+			Class:               ctx.swiftType(fld.Type),
+			Doc:                 swiftDoc(tdef.FieldDoc[i], tdef.FieldDocSuffix[i]),
+			HashcodeComputation: hashComp,
+			IsAny:               fld.Type.Kind() == vdl.Any,
+			IsOptional:          fld.Type.Kind() == vdl.Optional,
+			Name:                swiftCaseName(tdef, fld),
+			Type:                ctx.swiftType(fld.Type),
+			VdlName:             fld.Name,
+		}
+	}
+	data := struct {
+		AccessModifier string
+		Doc            string
+		Fields         []unionDefinitionField
+		IsHashable     bool
+		Name           string
+		Source         string
+		VdlTypeName    string
+	}{
+		AccessModifier: swiftAccessModifier(tdef),
+		Doc:            swiftDoc(tdef.Doc, tdef.DocSuffix),
+		Fields:         fields,
+		IsHashable:     isHashable,
+		Name:           ctx.swiftTypeName(tdef),
+		Source:         tdef.File.BaseName,
+		VdlTypeName:    tdef.Type.Name(),
+	}
+	var buf bytes.Buffer
+	err := parseTmpl("swift union", unionTmpl).Execute(&buf, data)
+	if err != nil {
+		log.Fatalf("vdl: couldn't execute union template: %v", err)
+	}
+	return formatSwiftCode(buf.String())
+}
diff --git a/lib/vdl/codegen/swift/util_doc.go b/lib/vdl/codegen/swift/util_doc.go
new file mode 100644
index 0000000..315211c
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_doc.go
@@ -0,0 +1,45 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"bufio"
+	"strings"
+)
+
+// swiftDoc transforms the provided VDL doc and a doc suffix into the SwiftDoc format.
+func swiftDoc(doc, suffix string) string {
+	if doc == "" && suffix == "" {
+		return ""
+	}
+	if doc == "" {
+		doc = suffix
+	} else if suffix != "" {
+		doc = doc + "\n" + suffix
+	}
+	ret := ""
+	reader := bufio.NewReader(strings.NewReader(doc))
+	hitContent := false
+	for {
+		line, err := reader.ReadString('\n')
+		if err != nil {
+			// A purely empty comment gets ignored
+			if !hitContent {
+				ret = ""
+			}
+			return ret
+		}
+		line = strings.TrimSpace(line)
+		if strings.HasPrefix(line, "//") {
+			// Three consequtive slashes is the format for Swiftdoc. Add the additional beyond what the line starts with.
+			ret += "/"
+			ret += line
+			ret += "\n"
+			if !hitContent && line != "//" {
+				hitContent = true
+			}
+		}
+	}
+}
diff --git a/lib/vdl/codegen/swift/util_doc_test.go b/lib/vdl/codegen/swift/util_doc_test.go
new file mode 100644
index 0000000..28939da
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_doc_test.go
@@ -0,0 +1,37 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import "testing"
+
+func TestDoc(t *testing.T) {
+	tests := []struct {
+		Name   string
+		Doc    string
+		Suffix string
+		Want   string
+	}{
+		{"Empty", "", "", ""},
+		{"Basic", "// Package signature defines types representing interface and method signatures.\n", "",
+			"/// Package signature defines types representing interface and method signatures.\n"},
+		{"New line required", "// a", "", ""},
+		{"Empty comment is ignored", "//\n", "", ""},
+		{"Single-line whitespace only comment is ignored", "//   \n", "", ""},
+		{"Multi-line whitespace only comment is ignored", "//   \n//   \n", "", ""},
+		{"Empty comment line is respected", "// a\n//\n// b\n", "", "/// a\n///\n/// b\n"},
+		{"Multiline respected", "// a\n// b\n", "", "/// a\n/// b\n"},
+		{"Whitespace preserved", "//  a\n//b\n", "", "///  a\n///b\n"},
+		{"Non-commments ignored", "a\n", "", ""},
+		{"Suffix is exchangable", "", "// a\n", "/// a\n"},
+		{"Suffix is used", "// a\n", "// a suffix\n", "/// a\n/// a suffix\n"},
+		{"Just VDL's // is supported", "/* a */\n", "", ""},
+		{"/// goes to ////", "///\n", "", "////\n"},
+	}
+	for _, test := range tests {
+		if got, want := swiftDoc(test.Doc, test.Suffix), test.Want; got != want {
+			t.Errorf("%s\n GOT %s\nWANT %s", test.Name, got, want)
+		}
+	}
+}
diff --git a/lib/vdl/codegen/swift/util_file.go b/lib/vdl/codegen/swift/util_file.go
new file mode 100644
index 0000000..3bc8505
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_file.go
@@ -0,0 +1,29 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"errors"
+	"path/filepath"
+	"strings"
+)
+
+func (ctx *swiftContext) vdlRootForFilePath(absolutePath string) (string, error) {
+	if !strings.HasPrefix(absolutePath, "/") {
+		return "", errors.New("Path not absolute or unsupported file system")
+	}
+	dir := filepath.Dir(absolutePath)
+	for {
+		if ctx.srcDirs[dir] == true {
+			return dir, nil
+		} else if dir == "/" || dir == "" {
+			return "", errors.New("Hit the root before any vdl paths were found")
+		}
+		// Go up a level
+		s := strings.Split(dir, "/")
+		s = s[:len(s)-1]
+		dir = "/" + filepath.Join(s...)
+	}
+}
diff --git a/lib/vdl/codegen/swift/util_file_test.go b/lib/vdl/codegen/swift/util_file_test.go
new file mode 100644
index 0000000..246123c
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_file_test.go
@@ -0,0 +1,59 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"errors"
+	"testing"
+
+	"v.io/x/ref/lib/vdl/compile"
+)
+
+func newVdlRootTestSwiftContext(srcDirs []string) *swiftContext {
+	srcDirsSet := map[string]bool{}
+	for _, srcDir := range srcDirs {
+		srcDirsSet[srcDir] = true
+	}
+	ctx := swiftContext{nil, nil, map[string]string{}, srcDirsSet, map[*compile.TypeDef]string{}}
+	return &ctx
+}
+
+func TestVdlRootForFilePath(t *testing.T) {
+	tests := []struct {
+		Name         string
+		AbsolutePath string
+		Ctx          *swiftContext
+		WantRoot     string
+		WantErr      error
+	}{
+		{"Must be absolute path", "not/absolute", newVdlRootTestSwiftContext(nil), "", errors.New("Path not absolute or unsupported file system")},
+		{"Basic",
+			"/home/user/vanadium/release/go/src/v.io/v23/syncbase/syncbase.vdl",
+			newVdlRootTestSwiftContext([]string{"/home/user/vanadium/release/go/src/v.io/v23"}),
+			"/home/user/vanadium/release/go/src/v.io/v23", nil},
+		{"Basic two places",
+			"/home/user/vanadium/release/go/src/v.io/v23/syncbase/syncbase.vdl",
+			newVdlRootTestSwiftContext([]string{"/home/user/vanadium/release/go/src/v.io/v23", "/home/users/vanadium/third-party"}),
+			"/home/user/vanadium/release/go/src/v.io/v23", nil},
+		{"Longest path wins",
+			"/home/user/vanadium/release/go/src/v.io/v23/services/syncbase/syncbase.vdl",
+			newVdlRootTestSwiftContext([]string{"/home/user/vanadium/release/go/src/v.io/v23", "/home/user/vanadium/release/go/src/v.io/v23/services"}),
+			"/home/user/vanadium/release/go/src/v.io/v23/services", nil},
+		{"Vdlroot NOT found",
+			"/home/user/vanadium/release/go/src/v.io/v23/services/syncbase/syncbase.vdl",
+			newVdlRootTestSwiftContext([]string{"/somewhere/else"}),
+			"", errors.New("Hit the root before any vdl paths were found")},
+	}
+	for _, test := range tests {
+		gotRoot, gotErr := test.Ctx.vdlRootForFilePath(test.AbsolutePath)
+		if gotRoot != test.WantRoot {
+			t.Errorf("%s\n GOT %s\nWANT %s", test.Name, gotRoot, test.WantRoot)
+		}
+		// Errors can be nil in want or what's producted. Test if they're not both nil or not nil (XOR), or if is not expected IF we want an error
+		if (gotErr != nil) != (test.WantErr != nil) || (test.WantErr != nil && gotErr.Error() != test.WantErr.Error()) {
+			t.Errorf("%s\n GOT ERROR %v\nWANT ERROR %v", test.Name, gotErr, test.WantErr)
+		}
+	}
+}
diff --git a/lib/vdl/codegen/swift/util_generate.go b/lib/vdl/codegen/swift/util_generate.go
new file mode 100644
index 0000000..b7ed092
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_generate.go
@@ -0,0 +1,96 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"regexp"
+	"strings"
+)
+
+var (
+	// File-wide
+	reCeilNewlines *regexp.Regexp
+	// Per line
+	reIsClosingBracket     *regexp.Regexp
+	reIsComment            *regexp.Regexp
+	reIsSwiftdoc           *regexp.Regexp
+	reOnlyWhitespaceRegexp *regexp.Regexp
+)
+
+type parseState int
+
+const (
+	stateClosingBracket parseState = iota
+	stateCode
+	stateComment
+	stateNull
+	stateSwiftdoc
+	stateWhitespace
+)
+
+func init() {
+	// File-wide
+	reCeilNewlines = regexp.MustCompile("(?m)(\\n([ ]|\t)*){2,}")
+	// Per line
+	reIsClosingBracket = regexp.MustCompile("^\\s*}$")
+	reIsComment = regexp.MustCompile("\\s*(//|/\\*)")
+	reIsSwiftdoc = regexp.MustCompile("\\s*(///|//:)")
+	reOnlyWhitespaceRegexp = regexp.MustCompile("^\\s*$")
+}
+
+// categorizeLine examines a line of Swift and categorizes it into a few rough buckets
+func categorizeLine(line string) parseState {
+	switch {
+	case reIsClosingBracket.MatchString(line):
+		return stateClosingBracket
+	case reIsSwiftdoc.MatchString(line):
+		return stateSwiftdoc
+	case reIsComment.MatchString(line):
+		return stateComment
+	case reOnlyWhitespaceRegexp.MatchString(line):
+		return stateWhitespace
+	}
+	return stateCode
+}
+
+// formatSwiftCode takes generated Swift code and cleans & reformats it
+// like gofmt to match the appropriate Swift style.
+// TODO(zinman) Integrate a proper Swift formatter
+func formatSwiftCode(code string) string {
+	// Across file
+	code = strings.TrimSpace(code)
+	code = reCeilNewlines.ReplaceAllStringFunc(code, func(lines string) string {
+		splitUp := strings.Split(lines, "\n")
+		if splitUp[len(splitUp)-1] == "" {
+			return "\n\n"
+		}
+		return "\n\n" + splitUp[len(splitUp)-1]
+	})
+	// Per line
+	lines := strings.Split(code, "\n")
+	cleanedLines := []string{}
+	for i := 0; i < len(lines); i++ {
+		line := lines[i]
+		line = strings.TrimRight(line, " ")
+		state := categorizeLine(line)
+		stateAbove := stateNull
+		if len(cleanedLines) > 0 {
+			stateAbove = categorizeLine(cleanedLines[len(cleanedLines)-1])
+		}
+		switch state {
+		case stateWhitespace:
+			if stateAbove == stateSwiftdoc {
+				// Parent was a Swift-doc comment, so kill extra space by ignoring this
+				continue
+			}
+		case stateSwiftdoc:
+			if strings.TrimSpace(line) == "///" && (stateAbove == stateWhitespace || stateAbove == stateNull) {
+				continue
+			}
+		}
+		cleanedLines = append(cleanedLines, line)
+	}
+	return strings.Join(cleanedLines, "\n")
+}
diff --git a/lib/vdl/codegen/swift/util_namespace.go b/lib/vdl/codegen/swift/util_namespace.go
new file mode 100644
index 0000000..3588f26
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_namespace.go
@@ -0,0 +1,200 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package swift implements Swift code generation from compiled VDL packages.
+package swift
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/build"
+	"v.io/x/ref/lib/vdl/compile"
+	"v.io/x/ref/lib/vdl/vdlutil"
+)
+
+const V23SwiftFrameworkName = "VanadiumCore"
+
+var (
+	memoizedSwiftModule = map[string]string{}
+	memoizedPackageName = map[*compile.Package]string{}
+)
+
+func (ctx *swiftContext) pkgIsSameModule(pkg *compile.Package) bool {
+	pkgModule := ctx.swiftModule(pkg)
+	ctxModule := ctx.swiftModule(ctx.pkg)
+	return pkgModule == ctxModule
+}
+
+func (ctx *swiftContext) swiftModule(pkg *compile.Package) string {
+	fileDir := ctx.genPathToDir[pkg.GenPath]
+	if fileDir == "" {
+		if pkg.GenPath == "_builtin" {
+			return ""
+		}
+		panic(fmt.Sprintf("Unable to find source directory for genPath ", pkg.GenPath))
+	}
+	if !strings.HasPrefix(fileDir, "/") {
+		if strings.HasPrefix(pkg.GenPath, "v.io/v23/vdlroot") {
+			panic("You must have the VDLROOT env var to generate VanadiumCore swift files")
+		}
+		panic(fmt.Sprintf("Unsupported file system for dir path: %v", fileDir))
+	}
+	if swiftModule, ok := memoizedSwiftModule[fileDir]; ok {
+		return swiftModule
+	}
+	_, module := ctx.findSwiftModule(pkg)
+	memoizedSwiftModule[fileDir] = module
+	return module
+}
+
+func (ctx *swiftContext) findSwiftModule(pkg *compile.Package) (path string, module string) {
+	fileDir := ctx.genPathToDir[pkg.GenPath]
+	for {
+		configPath := filepath.Join(fileDir, "swiftmodule")
+		module, err := ioutil.ReadFile(configPath)
+		if err == nil && module != nil {
+			return fileDir, strings.TrimSpace(string(module))
+		}
+		foundInSrcDirs := ctx.srcDirs[fileDir]
+		if foundInSrcDirs && strings.Contains(fileDir, "v.io/v23/vdlroot") {
+			// Special case VDLROOT which will be in a srcDir (so normally
+			// it would stop here), but the swiftmodule file is defined below it.
+			foundInSrcDirs = false
+		}
+		if fileDir == "/" || fileDir == "" || foundInSrcDirs {
+			// We're at the root, nothing else to check.
+			return "", ""
+		}
+		// Go up a level
+		s := strings.Split(fileDir, "/")
+		s = s[:len(s)-1]
+		fileDir = "/" + filepath.Join(s...)
+	}
+}
+
+// swiftPackageName returns a Swift package name that is a mashup of this
+// package name and its path ancestors. It traverses towards the root package
+// until it finds the Swift Module, and concatenates the child paths.
+// For example, v.io/v23/syncbase/nosql => SyncbaseNosql where v23 forms the root.
+// If no Swift Module is found, we presume the entire path is valid and the
+// entirety becomes concatenated using the pkg.Path. This exception allows
+// for third-party code to conservatively work (since we can assume nothing
+// about the root package we don't want to throw away information) and
+// vdlroot's packages to be correctly named (signature => signature).
+func (ctx *swiftContext) swiftPackageName(pkg *compile.Package) string {
+	if name, ok := memoizedPackageName[pkg]; ok {
+		return name
+	}
+	// Remove the package path of the swift module from our pkg.Path
+	// First find that package path
+	moduleDir, _ := ctx.findSwiftModule(pkg)
+	modulePkgPath := "__INVALID__"
+	if moduleDir != "" {
+		// moduleDir is the full path to our swiftmodule file
+		// find the VDLROOT/VDLPATH that contains this
+		srcDirs := build.SrcDirs(ctx.env.Errors)
+		for _, dir := range srcDirs {
+			if strings.HasPrefix(moduleDir, dir) {
+				// We found the VDLPATH/VDLROOT that corresponds to this SwiftModule.
+				// So lop off the VDLPATH. For example:
+				// Before moduleDir = /Users/aaron/v23/release/go/src/v.io/v23/services
+				// Before dir (srcDir) = /Users/aaron/v23/release/go/src
+				modulePkgPath = strings.TrimPrefix(moduleDir, dir)
+				modulePkgPath = strings.TrimPrefix(modulePkgPath, "/")
+				// After: modulePkgPath = v.io/v23/services
+				break
+			}
+		}
+		if modulePkgPath == "__INVALID__" {
+			log.Fatalf("Could not find pkg path for module in dir %v", moduleDir)
+		}
+	}
+	// Remove module package path, for example:
+	// Before pkg.Path = v.io/v23/services/syncbase
+	// Before modulePkgPath = v.io/v23/services
+	modulePkgPath = strings.TrimPrefix(pkg.Path, modulePkgPath)
+	modulePkgPath = strings.TrimPrefix(modulePkgPath, "/")
+	// After modulePkgPath = syncbase
+	// CamelCaseThePath
+	name := ""
+	for _, pkg := range strings.Split(modulePkgPath, "/") {
+		// Remove any periods (e.g. v.io/ -> Vio)
+		pkg = strings.Replace(pkg, ".", "", -1)
+		name = name + vdlutil.FirstRuneToUpper(pkg)
+	}
+	memoizedPackageName[pkg] = name
+	return name
+}
+
+func (ctx *swiftContext) importedModules(tdefs []*compile.TypeDef) []string {
+	// Find the transitive closure of tdefs' dependencies.
+	walkedTdefs := map[*compile.TypeDef]bool{}
+	modules := map[string]bool{}
+	for _, tdef := range tdefs {
+		walkTdef(tdef, ctx.env, walkedTdefs)
+	}
+	// Extract the modules that aren't the same as the context's
+	for tdef := range walkedTdefs {
+		module := ctx.swiftModule(tdef.File.Package)
+		if module != "" && !ctx.pkgIsSameModule(tdef.File.Package) {
+			modules[module] = true
+			continue
+		}
+	}
+	if ctx.swiftModule(ctx.pkg) != V23SwiftFrameworkName {
+		// Make sure VanadiumCore is imported as that's where we define VError, VdlPrimitive, etc
+		modules[V23SwiftFrameworkName] = true
+	}
+	return flattenImportedModuleSet(modules)
+}
+
+func walkTdef(tdef *compile.TypeDef, env *compile.Env, seen map[*compile.TypeDef]bool) {
+	// If this typedef has a native type, then we can ignore the import because
+	// that information is replaced anyway.
+	pkg := tdef.File.Package
+	if _, ok := pkg.Config.Swift.WireToNativeTypes[tdef.Name]; ok {
+		return
+	}
+	seen[tdef] = true
+	switch tdef.Type.Kind() {
+	case vdl.Struct, vdl.Union:
+		for i := 0; i < tdef.Type.NumField(); i++ {
+			fld := tdef.Type.Field(i)
+			if innerTdef := env.FindTypeDef(fld.Type); innerTdef != nil {
+				walkTdef(innerTdef, env, seen)
+			}
+		}
+
+	case vdl.List, vdl.Array, vdl.Map, vdl.Optional:
+		if innerTdef := env.FindTypeDef(tdef.Type.Elem()); innerTdef != nil {
+			walkTdef(innerTdef, env, seen)
+		}
+	}
+	switch tdef.Type.Kind() {
+	case vdl.Map, vdl.Set:
+		if innerTdef := env.FindTypeDef(tdef.Type.Key()); innerTdef != nil {
+			walkTdef(innerTdef, env, seen)
+		}
+	}
+}
+
+func flattenImportedModuleSet(modules map[string]bool) []string {
+	imports := make([]string, len(modules))
+	i := 0
+	for moduleName := range modules {
+		if moduleName != "" {
+			imports[i] = moduleName
+			i++
+		}
+	}
+	// Make it deterministic
+	sort.Strings(imports)
+	return imports
+}
diff --git a/lib/vdl/codegen/swift/util_namespace_test.go b/lib/vdl/codegen/swift/util_namespace_test.go
new file mode 100644
index 0000000..7066451
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_namespace_test.go
@@ -0,0 +1,475 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package swift implements Swift code generation from compiled VDL packages.
+package swift
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+
+	"v.io/x/lib/gosh"
+	"v.io/x/ref/lib/vdl/build"
+	"v.io/x/ref/lib/vdl/compile"
+	"v.io/x/ref/lib/vdl/internal/vdltest"
+)
+
+const (
+	pkgAFile1 = `package a
+
+const ABool = true
+
+type StructA struct {
+	X bool
+}`
+
+	pkgBFile1 = `package b
+
+const BBool = true
+
+type StructB struct {
+	X bool
+}`
+
+	pkgCFile1 = `package c
+
+import "v.io/v23/a"
+
+const CBool = a.ABool
+
+type (
+	StructC struct {
+		X bool
+		Y a.StructA
+	}
+
+	SelfContainedStructC struct {
+		X bool
+	}
+
+	UnionC union {
+		X bool
+		Y a.StructA
+	}
+
+	MapCKey map[a.StructA]string
+	MapCValue map[string]a.StructA
+	ArrayC [5]a.StructA
+	ListC []a.StructA
+	SetC set[a.StructA]
+)
+`
+)
+
+type moduleConfig struct {
+	Name string
+	Path string
+}
+
+type pkgConfig struct {
+	Name  string
+	Path  string
+	Files map[string]string
+}
+
+func createTmpVdlPath(t *testing.T, modules []moduleConfig, pkgs []pkgConfig) (string, func()) {
+	oldVdlPath := os.Getenv("VDLPATH")
+	sh := gosh.NewShell(nil)
+	tempDir := sh.MakeTempDir()
+	os.Setenv("VDLPATH", tempDir)
+	for _, module := range modules {
+		if strings.HasPrefix(module.Path, "/") {
+			sh.Cleanup()
+			t.Fatalf("module.Path must be relative")
+		}
+		sh.Cmd("mkdir", "-p", filepath.Join(tempDir, module.Path)).Run()
+		moduleConfigPath := filepath.Join(tempDir, module.Path, "swiftmodule")
+		err := ioutil.WriteFile(moduleConfigPath, []byte(module.Name), 0644)
+		if err != nil {
+			sh.Cleanup()
+			t.Fatalf("Unable to create temp vdl.config file: %v", err)
+		}
+	}
+	for _, pkg := range pkgs {
+		if strings.HasPrefix(pkg.Path, "/") {
+			sh.Cleanup()
+			t.Errorf("pkg.Path must be relative")
+		}
+		sh.Cmd("mkdir", "-p", filepath.Join(tempDir, pkg.Path)).Run()
+		for file, contents := range pkg.Files {
+			vdlPath := filepath.Join(tempDir, pkg.Path, file)
+			err := ioutil.WriteFile(vdlPath, []byte(contents), 0644)
+			if err != nil {
+				sh.Cleanup()
+				t.Fatalf("Unable to create temp vdl file at %v: %v", vdlPath, err)
+			}
+		}
+	}
+	return tempDir, func() {
+		sh.Cleanup()
+		os.Setenv("VDLPATH", oldVdlPath)
+	}
+}
+
+func createPackagesAndSwiftContext(t *testing.T, modules []moduleConfig, pkgs []pkgConfig, ctxPath string) ([]*compile.Package, *swiftContext, func()) {
+	vdlPath, cleanup := createTmpVdlPath(t, modules, pkgs)
+	built := make([]*compile.Package, len(pkgs))
+	i := 0
+	env := compile.NewEnv(-1)
+	genPathToDir := map[string]string{}
+	for _, pkg := range pkgs {
+		buildPkg := vdltest.FakeBuildPackage(pkg.Name, pkg.Path, pkg.Files)
+		built[i] = build.BuildPackage(buildPkg, env)
+		built[i].GenPath = built[i].Path
+		genPathToDir[built[i].GenPath] = filepath.Join(vdlPath, pkg.Path)
+		i++
+	}
+	// Find ctxPkgPath
+	var ctxPkg *compile.Package = nil
+	for _, pkg := range built {
+		if pkg.Path == ctxPath {
+			ctxPkg = pkg
+			break
+		}
+	}
+	if ctxPkg == nil {
+		cleanup()
+		t.Fatalf("Could not find test context pkg %v", ctxPath)
+	}
+	ctx := swiftContext{
+		env,
+		ctxPkg,
+		genPathToDir,
+		map[string]bool{vdlPath: true},
+		map[*compile.TypeDef]string{},
+	}
+	return built, &ctx, cleanup
+}
+
+func TestPkgIsSameModule(t *testing.T) {
+	tests := []struct {
+		name    string
+		modules []moduleConfig
+		pkgs    []pkgConfig
+		pkgPath string
+		ctxPath string
+		expect  bool
+	}{
+		{"only one module",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/b",
+			true},
+		{"two modules, in same module",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}, moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/b",
+			true},
+		{"in diff module",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}, moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/b",
+			"v.io/v23/services/c",
+			false},
+	}
+	for _, test := range tests {
+		pkgs, ctx, cleanup := createPackagesAndSwiftContext(t, test.modules, test.pkgs, test.ctxPath)
+		// Find test pkgPath
+		var testPkg *compile.Package = nil
+		for _, pkg := range pkgs {
+			if pkg.Path == test.pkgPath {
+				testPkg = pkg
+				break
+			}
+		}
+		if testPkg == nil {
+			cleanup()
+			t.Errorf("Could not find test pkg")
+			return
+		}
+		if ctxModule, pkgModule := ctx.swiftModule(ctx.pkg), ctx.swiftModule(testPkg); ctxModule == "" || pkgModule == "" {
+			cleanup()
+			t.Errorf("%s\n ctx or pkg module is nil", test.name)
+			return
+		}
+		if got, want := ctx.pkgIsSameModule(testPkg), test.expect; got != want {
+			t.Errorf("%s\n GOT %v\nWANT %v", test.name, got, want)
+		}
+		cleanup()
+	}
+}
+
+func TestSwiftModule(t *testing.T) {
+	tests := []struct {
+		name    string
+		modules []moduleConfig
+		pkgs    []pkgConfig
+		ctxPath string
+		expect  string
+	}{
+		{"no modules",
+			[]moduleConfig{},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			""},
+		{"only one module",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			V23SwiftFrameworkName},
+		{"two modules (VanadiumCore)",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}, moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/a",
+			V23SwiftFrameworkName},
+		{"two modules (VanadiumServices)",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}, moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"VanadiumServices"},
+		{"not in path",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23/a"}, moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/b", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/b",
+			""},
+	}
+	for _, test := range tests {
+		_, ctx, cleanup := createPackagesAndSwiftContext(t, test.modules, test.pkgs, test.ctxPath)
+		if got, want := ctx.swiftModule(ctx.pkg), test.expect; got != want {
+			t.Errorf("%s\n GOT %v\nWANT %v", test.name, got, want)
+		}
+		cleanup()
+	}
+}
+
+func TestPackageName(t *testing.T) {
+	tests := []struct {
+		name    string
+		modules []moduleConfig
+		pkgs    []pkgConfig
+		ctxPath string
+		pkgPath string
+		expect  string
+	}{
+		{"no modules",
+			[]moduleConfig{},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a",
+			"VioV23A"},
+		{"removes module path",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a",
+			"A"},
+		{"root is empty name",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23/a"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a",
+			""},
+		{"path not in module",
+			[]moduleConfig{moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a",
+			"VioV23A"},
+		{"path in module",
+			[]moduleConfig{moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/services/c",
+			"C"},
+		{"two modules (VanadiumServices)",
+			[]moduleConfig{moduleConfig{V23SwiftFrameworkName, "v.io/v23"}, moduleConfig{"VanadiumServices", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/services/c",
+			"C"},
+	}
+	for _, test := range tests {
+		pkgs, ctx, cleanup := createPackagesAndSwiftContext(t, test.modules, test.pkgs, test.ctxPath)
+		// Find test pkgPath
+		var testPkg *compile.Package = nil
+		for _, pkg := range pkgs {
+			if pkg.Path == test.pkgPath {
+				testPkg = pkg
+				break
+			}
+		}
+		if testPkg == nil {
+			cleanup()
+			t.Errorf("Could not find test pkg")
+			return
+		}
+		if got, want := ctx.swiftPackageName(testPkg), test.expect; got != want {
+			t.Errorf("%s\n GOT %v\nWANT %v", test.name, got, want)
+		}
+		cleanup()
+	}
+}
+
+func TestImportedModules(t *testing.T) {
+	tests := []struct {
+		name              string
+		modules           []moduleConfig
+		pkgs              []pkgConfig
+		ctxPath           string
+		tdefQualifiedPath string
+		expect            string
+	}{
+		{"no modules",
+			[]moduleConfig{},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a.StructA",
+			""},
+		{"one module",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"b", "v.io/v23/b", map[string]string{"file1.vdl": pkgBFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a.StructA",
+			""},
+		{"path not in module",
+			[]moduleConfig{moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/a",
+			"v.io/v23/a.StructA",
+			""},
+		{"path in module",
+			[]moduleConfig{moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.SelfContainedStructC",
+			""},
+		{"cross module union field",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.UnionC",
+			"VanadiumC"},
+		{"cross module struct field",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.StructC",
+			"VanadiumC"},
+		{"cross module map key",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.MapCKey",
+			"VanadiumC"},
+		{"cross module map value",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.MapCValue",
+			"VanadiumC"},
+		{"cross module array",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.ArrayC",
+			"VanadiumC"},
+		{"cross module list",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.ListC",
+			"VanadiumC"},
+		{"cross module set",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.SetC",
+			"VanadiumC"},
+		{"non-cross module",
+			[]moduleConfig{moduleConfig{"VanadiumC", "v.io/v23"}, moduleConfig{"VanadiumS", "v.io/v23/services"}},
+			[]pkgConfig{pkgConfig{"a", "v.io/v23/a", map[string]string{"file1.vdl": pkgAFile1}},
+				pkgConfig{"c", "v.io/v23/services/c", map[string]string{"file1.vdl": pkgCFile1}}},
+			"v.io/v23/services/c",
+			"v.io/v23/services/c.SelfContainedStructC",
+			"VanadiumC"},
+	}
+	for _, test := range tests {
+		pkgs, ctx, cleanup := createPackagesAndSwiftContext(t, test.modules, test.pkgs, test.ctxPath)
+		// Find test tdef
+		var testTdef *compile.TypeDef = nil
+		for _, pkg := range pkgs {
+			if strings.HasPrefix(test.tdefQualifiedPath, pkg.Path) {
+				for _, tdef := range pkg.TypeDefs() {
+					if strings.HasSuffix(test.tdefQualifiedPath, tdef.Name) {
+						testTdef = tdef
+						break
+					}
+				}
+				for _, cdef := range pkg.ConstDefs() {
+					tdef := ctx.env.FindTypeDef(cdef.Value.Type())
+					if strings.HasSuffix(test.tdefQualifiedPath, cdef.Name) {
+						testTdef = tdef
+						break
+					}
+				}
+
+				break
+			}
+		}
+		if testTdef == nil {
+			cleanup()
+			t.Errorf("Could not find tdef %v", test.tdefQualifiedPath)
+			return
+		}
+		got := ctx.importedModules([]*compile.TypeDef{testTdef})
+		// Remove VanadiumCore if we aren't expecting it as it's always imported
+		foundCore := false
+		gotModule := ""
+		for _, module := range got {
+			if module == V23SwiftFrameworkName {
+				foundCore = true
+			} else {
+				gotModule = module
+			}
+		}
+		if !foundCore {
+			t.Errorf("Couldn't find expected core import %v", V23SwiftFrameworkName)
+		}
+		if gotModule != test.expect {
+			t.Errorf("%s\n GOT %v\nWANT %v", test.name, gotModule, test.expect)
+		}
+		cleanup()
+	}
+}
diff --git a/lib/vdl/codegen/swift/util_template.go b/lib/vdl/codegen/swift/util_template.go
new file mode 100644
index 0000000..68e131b
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_template.go
@@ -0,0 +1,24 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"text/template"
+)
+
+var tmplCache = map[string]*template.Template{}
+
+// parseTmpl parses a template and caches the parsed value.
+// Each template body must be associated with a unique name.
+func parseTmpl(name string, body string) *template.Template {
+	if tmpl, ok := tmplCache[name]; ok {
+		return tmpl
+	}
+
+	tmpl := template.Must(template.New(name).Parse(body))
+
+	tmplCache[name] = tmpl
+	return tmpl
+}
diff --git a/lib/vdl/codegen/swift/util_type.go b/lib/vdl/codegen/swift/util_type.go
new file mode 100644
index 0000000..8b84c61
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_type.go
@@ -0,0 +1,239 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"fmt"
+	"log"
+	"unicode"
+	"unicode/utf8"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/compile"
+	"v.io/x/ref/lib/vdl/vdlutil"
+)
+
+// swiftBuiltInType returns the type name for the provided built in type
+// definition, forcing the use of a swift class (e.g., swift.lang.Integer) if so
+// desired.  This method also returns a boolean value indicating whether the
+// returned type is a class.
+//
+// All swift integers (byte, short, int, long) are signed.  We
+// translate signed vdl integers int{16,32,64} into their
+// swift equivalents.  We translate unsigned vdl integers
+// uint{16,32,64} into our class-based representation
+// VdlUint{16,32,64}.
+//
+// According to this rule, we should translate signed
+// vdl int8 into swift byte, and unsigned vdl byte into
+// swift VdlUint8.  However we flip the rule, and
+// actually translate vdl int8 into swift VdlInt8, and
+// vdl byte into swift byte.  We do this because we want the
+// common usage of vdl []byte to translate into swift byte[].
+func (ctx *swiftContext) swiftBuiltInType(typ *vdl.Type) string {
+	if typ == nil {
+		return "Void"
+	}
+	switch typ.Kind() {
+	case vdl.Bool:
+		return "Bool"
+	case vdl.Byte:
+		return "UInt8"
+	case vdl.Int8:
+		return "Int8"
+	case vdl.Uint16:
+		return "UInt16"
+	case vdl.Int16:
+		return "Int16"
+	case vdl.Uint32:
+		return "UInt32"
+	case vdl.Int32:
+		return "Int32"
+	case vdl.Uint64:
+		return "UInt64"
+	case vdl.Int64:
+		return "Int64"
+	case vdl.Float32:
+		return "Float"
+	case vdl.Float64:
+		return "Double"
+	case vdl.String:
+		return "String"
+	case vdl.TypeObject:
+		return "VdlTypeObject"
+	case vdl.Any:
+		return "Any"
+	case vdl.List, vdl.Array:
+		return fmt.Sprintf("[%v]", ctx.swiftType(typ.Elem()))
+	case vdl.Map:
+		return fmt.Sprintf("[%v : %v]", ctx.swiftType(typ.Key()), ctx.swiftType(typ.Elem()))
+	case vdl.Set:
+		return fmt.Sprintf("Set<%v>", ctx.swiftType(typ.Key()))
+	default:
+		panic("Unsupported built in type")
+	}
+}
+
+func (ctx *swiftContext) swiftTypeName(tdef *compile.TypeDef) string {
+	if name, ok := ctx.memoizedTypeNames[tdef]; ok {
+		return name
+	}
+	var name string
+	if tdef.File == compile.BuiltInFile {
+		name = ctx.swiftBuiltInType(tdef.Type)
+	} else {
+		// A typeName is created by walking concatenating a package path with the type name
+		// into a camel cased symbol. For example Value in v.io/v23/syncbase/nosql would be
+		// SyncbaseNosqlValue (because v23 defines a swift module we stop just before that).
+		// Convienently the Swift package name already does the package path part, so we
+		// can just append to that. In cases where we're at the root of our Swift module,
+		// the package name will be a zero value and so we correctly end up with just our
+		// tdef.Name.
+		name = ctx.swiftPackageName(tdef.File.Package) + vdlutil.FirstRuneToUpper(tdef.Name)
+		if !ctx.pkgIsSameModule(tdef.File.Package) {
+			name = ctx.swiftModule(tdef.File.Package) + "." + name
+		}
+	}
+	ctx.memoizedTypeNames[tdef] = name
+	return name
+}
+
+// swiftAccessModifier returns the Swift access modifier given the type.
+func swiftAccessModifier(tdef *compile.TypeDef) string {
+	if tdef.Exported {
+		return "public"
+	}
+	return "internal"
+}
+
+// accessModifierForName returns the Swift access modifier given the name.
+// It follows VDL naming conventions, indicating that an uppercase name
+// denotes a public type and a lowercase name a package-protected type.
+func swiftAccessModifierForName(name string) string {
+	r, _ := utf8.DecodeRuneInString(name)
+	if unicode.IsUpper(r) {
+		return "public"
+	}
+	return "internal"
+}
+
+func swiftNativeType(t *vdl.Type, env *compile.Env) (string, bool) {
+	if t == vdl.ErrorType {
+		// TODO(zinman) Verify this can never be a user-defined error,
+		// and determine if we need to prepend the v23 namespace here
+		// or if that adjustment will be higher up the stack.
+		switch t.Kind() {
+		case vdl.Optional:
+			return "VError?", true
+		case vdl.Struct:
+			return "VError", true
+		default:
+			panic(fmt.Sprintf("Unexpected vdl.Type.Kind() for ErrorType: %v", t.Kind()))
+		}
+	}
+	if tdef := env.FindTypeDef(t); tdef != nil {
+		pkg := tdef.File.Package
+		if native, ok := pkg.Config.Swift.WireToNativeTypes[tdef.Name]; ok {
+			// There is a Swift native type configured for this defined type.
+			return native, true
+		}
+	}
+	return "", false
+}
+
+// swiftCaseName returns the Swift name of a field translated as a Enum case.
+func swiftVariableName(tdef *compile.TypeDef, fld vdl.Field) string {
+	// Check if reserved
+	return vdlutil.FirstRuneToLower(fld.Name)
+}
+
+// swiftCaseName returns the Swift name of a field.
+func swiftCaseName(tdef *compile.TypeDef, fld vdl.Field) string {
+	// Check if reserved
+	return vdlutil.FirstRuneToUpper(fld.Name)
+}
+
+func (ctx *swiftContext) swiftType(t *vdl.Type) string {
+	if t == nil {
+		return ctx.swiftBuiltInType(nil) //, forceClass)
+	}
+
+	if native, ok := swiftNativeType(t, ctx.env); ok {
+		return native
+	}
+	if tdef := ctx.env.FindTypeDef(t); tdef != nil {
+		return ctx.swiftTypeName(tdef)
+	}
+	switch t.Kind() {
+	case vdl.Array, vdl.List:
+		val := fmt.Sprintf("[%s]", ctx.swiftType(t.Elem()))
+		return val
+	case vdl.Set:
+		return fmt.Sprintf("%s<%s>", "Set", ctx.swiftType(t.Key()))
+	case vdl.Map:
+		return fmt.Sprintf("[%s : %s]", ctx.swiftType(t.Key()), ctx.swiftType(t.Elem()))
+	case vdl.Optional:
+		return fmt.Sprintf("%s?", ctx.swiftType(t.Elem()))
+	default:
+		log.Fatalf("vdl: swiftType unhandled type %v %v", t.Kind(), t)
+		return ""
+	}
+}
+
+// swiftHashCode returns the swift code for the hashCode() computation for a given type.
+func (ctx *swiftContext) swiftHashCode(name string, ty *vdl.Type) (string, error) {
+	if def := ctx.env.FindTypeDef(ty); def != nil && def.File == compile.BuiltInFile {
+		switch ty.Kind() {
+		case vdl.Bool:
+			return fmt.Sprintf("%s.hashValue", name), nil
+		case vdl.Byte, vdl.Uint16, vdl.Int16:
+			return "Int(" + name + ")", nil
+		case vdl.Uint32, vdl.Int32:
+			return name, nil
+		case vdl.Uint64, vdl.Int64:
+			return fmt.Sprintf("%s.hashValue", name), nil
+		case vdl.Float32:
+			return fmt.Sprintf("Float(%s).hashValue", name), nil
+		case vdl.Float64:
+			return fmt.Sprintf("Double(%s).hashValue", name), nil
+		}
+	}
+
+	if !isTypeHashable(ty, make(map[*vdl.Type]bool)) {
+		return "", fmt.Errorf("Any is not supported with hashCode")
+	}
+
+	switch ty.Kind() {
+	case vdl.Optional:
+		return fmt.Sprintf("(%s?.hashValue ?? 0)", name), nil
+	// Primitives are going to access the rawValue inside this box
+	case vdl.Bool, vdl.Byte, vdl.Uint16, vdl.Int16, vdl.Uint32, vdl.Int32, vdl.Uint64, vdl.Int64, vdl.Float32, vdl.Float64:
+		return fmt.Sprintf("%s.rawValue.hashValue", name), nil
+	}
+	return fmt.Sprintf("%s.hashValue", name), nil
+}
+
+// isTypeHashable returns true if the type provided is hashable in Swift.
+// Part of the difficulty in Swift is that as of 2.1 we can't create extensions
+// with protocol conformance (Hashable, Equatable) AND type constraints (where Element : Hashable)
+// Thus we can't extend Array AND require its elements to conform to Hashable as follows:
+// ILLEGAL => extension Array : Hashable where Element : Hashable
+//
+// Returns false for Any, arrays, maps, and sets. Returns true for primitives,
+// strings, enums. Optional, structs, and unions are only hashable if all of their
+// contents are hashable.
+func isTypeHashable(ty *vdl.Type, seen map[*vdl.Type]bool) bool {
+	return !ty.ContainsKind(vdl.WalkAll, vdl.Any, vdl.Array, vdl.List, vdl.Set, vdl.Map, vdl.TypeObject)
+}
+
+func bitlen(kind vdl.Kind) int {
+	switch kind {
+	case vdl.Float32:
+		return 32
+	case vdl.Float64:
+		return 64
+	}
+	panic(fmt.Errorf("vdl: bitLen unhandled kind %v", kind))
+}
diff --git a/lib/vdl/codegen/swift/util_val.go b/lib/vdl/codegen/swift/util_val.go
new file mode 100644
index 0000000..d0d1582
--- /dev/null
+++ b/lib/vdl/codegen/swift/util_val.go
@@ -0,0 +1,142 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package swift
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+
+	"v.io/v23/vdl"
+	"v.io/x/ref/lib/vdl/compile"
+)
+
+// swiftConstVal returns the value string for the provided constant value.
+func swiftConstVal(v *vdl.Value, ctx *swiftContext) (ret string) {
+	ret = swiftVal(v, ctx)
+	if tdef := ctx.env.FindTypeDef(v.Type()); tdef != nil && tdef.File != compile.BuiltInFile { // User-defined type.
+		switch tdef.Type.Kind() {
+		case vdl.Union:
+			ret = fmt.Sprintf("%s.%s", ctx.swiftType(v.Type()), ret)
+		case vdl.Struct:
+			ret = fmt.Sprintf("%s(%s)", ctx.swiftType(v.Type()), ret)
+		case vdl.Enum:
+			return
+		default:
+			ret = fmt.Sprintf("%s(rawValue: %s)", ctx.swiftType(v.Type()), ret)
+		}
+	}
+	return
+}
+
+// swiftVal returns the value string for the provided Value.
+func swiftVal(v *vdl.Value, ctx *swiftContext) string {
+	switch v.Kind() {
+	case vdl.Any:
+		// TODO(azinman) Don't exactly know what to do here to generate the inference code... so instead come back to this
+		// but it doesn't seem to get triggered in the v23 VDL gen code base anyway?
+		panic("Don't know how to handle Any type in a given Value")
+	case vdl.Bool:
+		switch v.Bool() {
+		case true:
+			return "true"
+		case false:
+			return "false"
+		}
+	case vdl.Byte:
+		return "UInt8(0x" + strconv.FormatUint(v.Uint(), 16) + ")"
+	case vdl.Int8:
+		return "Int8(" + strconv.FormatInt(v.Int(), 10) + ")"
+	case vdl.Uint16:
+		return "UInt16(" + strconv.FormatUint(v.Uint(), 10) + ")"
+	case vdl.Int16:
+		return "Int16(" + strconv.FormatInt(v.Int(), 10) + ")"
+	case vdl.Uint32:
+		return "UInt32(" + strconv.FormatUint(v.Uint(), 10) + ")"
+	case vdl.Int32:
+		return "Int32(" + strconv.FormatInt(v.Int(), 10) + ")"
+	case vdl.Uint64:
+		return "UInt64(" + strconv.FormatUint(v.Uint(), 10) + ")"
+	case vdl.Int64:
+		return "Int64(" + strconv.FormatInt(v.Int(), 10) + ")"
+	case vdl.Float32, vdl.Float64:
+		c := strconv.FormatFloat(v.Float(), 'g', -1, bitlen(v.Kind()))
+		if strings.Index(c, ".") == -1 {
+			c += ".0"
+		}
+		if v.Kind() == vdl.Float32 {
+			return "Float(" + c + ")"
+		} else {
+			return "Double(" + c + ")"
+		}
+	case vdl.String:
+		in := v.RawString()
+		return swiftQuoteString(in)
+	case vdl.Enum:
+		return fmt.Sprintf("%s.%s", ctx.swiftType(v.Type()), v.EnumLabel())
+	case vdl.Array, vdl.List:
+		ret := "["
+		for i := 0; i < v.Len(); i++ {
+			if i > 0 {
+				ret = ret + ", "
+			}
+			ret = ret + swiftConstVal(v.Index(i), ctx)
+		}
+		return ret + "]"
+	case vdl.Map:
+		ret := "["
+		for _, key := range vdl.SortValuesAsString(v.Keys()) {
+			keyStr := swiftConstVal(key, ctx)
+			elemStr := swiftConstVal(v.MapIndex(key), ctx)
+			ret = fmt.Sprintf("%s%s:%s, ", ret, keyStr, elemStr)
+		}
+		return ret + "]"
+	case vdl.Union:
+		index, value := v.UnionField()
+		name := v.Type().Field(index).Name
+		elemStr := swiftConstVal(value, ctx)
+		return fmt.Sprintf("%s(elem: %s)", name, elemStr)
+	case vdl.Set:
+		ret := "Set("
+		for _, key := range vdl.SortValuesAsString(v.Keys()) {
+			ret = fmt.Sprintf("%s, %s", ret, swiftConstVal(key, ctx))
+		}
+		return ret + ")"
+	case vdl.Struct:
+		tdef := ctx.env.FindTypeDef(v.Type())
+		if tdef == nil {
+			panic("No plausible way to define a Swift struct constructor without the tdef")
+		}
+		var ret string
+		for i := 0; i < v.Type().NumField(); i++ {
+			if i > 0 {
+				ret = ret + ", "
+			}
+			fldValue := v.StructField(i)
+			fld := tdef.Type.Field(i)
+			ret = fmt.Sprintf("%v%v: %v", ret, swiftVariableName(tdef, fld), swiftConstVal(fldValue, ctx))
+		}
+		return ret
+	case vdl.TypeObject:
+		// TODO(zinman) Support TypeObjects once we have vdlType support
+		return fmt.Sprintf("VdlTypeObject(type: nil)")
+	case vdl.Optional:
+		if v.Elem() != nil {
+			return swiftConstVal(v.Elem(), ctx)
+		} else {
+			return "nil"
+		}
+	}
+	panic(fmt.Errorf("vdl: swiftVal unhandled type %v %v", v.Kind(), v.Type()))
+}
+
+func swiftQuoteString(str string) string {
+	// This accounts for Swift string interpolation \(likeThis) because
+	// vdl will already error if you create a const string that contains
+	// \( and not \\(
+	// In the future this may change and we might need to explicitly add
+	// the escapes.
+	return strconv.Quote(str)
+}