aboutsummaryrefslogtreecommitdiff
path: root/generator_windows.go
diff options
context:
space:
mode:
authorJan Mercl <0xjnml@gmail.com>2017-06-05 20:13:10 +0200
committerJan Mercl <0xjnml@gmail.com>2017-06-05 20:13:10 +0200
commit8c183b526ba8f225684f6431836138a9cffae509 (patch)
tree4afc11a44fe89e0e7081f00085eed90357218fac /generator_windows.go
parent1a3b0a731a9d2b66fb058caef95c004634b17307 (diff)
Release the {cgo,VM}-free Linux/Intel version.
modified: Makefile new file: all_linux_test.go renamed: all_test.go -> all_test_windows.go new file: doc.go new file: generate_linux.go new file: generate_windows.go modified: generator.go new file: generator_windows.go modified: internal/bin/bin_linux_386.go modified: internal/bin/bin_linux_amd64.go modified: main.c modified: sqlite.go modified: sqlite_go18.go new file: sqlite_windows.go
Diffstat (limited to 'generator_windows.go')
-rw-r--r--generator_windows.go366
1 files changed, 366 insertions, 0 deletions
diff --git a/generator_windows.go b/generator_windows.go
new file mode 100644
index 0000000..03bb15e
--- /dev/null
+++ b/generator_windows.go
@@ -0,0 +1,366 @@
+// Copyright 2017 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "compress/gzip"
+ "encoding/gob"
+ "flag"
+ "fmt"
+ "go/format"
+ "go/scanner"
+ "go/token"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+
+ "log"
+
+ "github.com/cznic/cc"
+ "github.com/cznic/ccir"
+ "github.com/cznic/internal/buffer"
+ "github.com/cznic/ir"
+ "github.com/cznic/strutil"
+ "github.com/cznic/virtual"
+ "github.com/cznic/xc"
+)
+
+var (
+ cpp = flag.Bool("cpp", false, "")
+ dict = xc.Dict
+ errLimit = flag.Int("errlimit", 10, "")
+ filter = flag.String("re", "", "")
+ ndebug = flag.Bool("ndebug", false, "")
+ noexec = flag.Bool("noexec", false, "")
+ oLog = flag.Bool("log", false, "")
+ trace = flag.Bool("trc", false, "")
+ yydebug = flag.Int("yydebug", 0, "")
+)
+
+func findRepo(s string) string {
+ s = filepath.FromSlash(s)
+ for _, v := range strings.Split(strutil.Gopath(), string(os.PathListSeparator)) {
+ p := filepath.Join(v, "src", s)
+ fi, err := os.Lstat(p)
+ if err != nil {
+ continue
+ }
+
+ if fi.IsDir() {
+ wd, err := os.Getwd()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if p, err = filepath.Rel(wd, p); err != nil {
+ log.Fatal(err)
+ }
+
+ return p
+ }
+ }
+ return ""
+}
+
+func errStr(err error) string {
+ switch x := err.(type) {
+ case scanner.ErrorList:
+ if len(x) != 1 {
+ x.RemoveMultiples()
+ }
+ var b bytes.Buffer
+ for i, v := range x {
+ if i != 0 {
+ b.WriteByte('\n')
+ }
+ b.WriteString(v.Error())
+ if i == 9 {
+ fmt.Fprintf(&b, "\n\t... and %v more errors", len(x)-10)
+ break
+ }
+ }
+ return b.String()
+ default:
+ return err.Error()
+ }
+}
+
+func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit, *virtual.Binary) {
+ var b buffer.Bytes
+ var lpos token.Position
+ if *cpp {
+ opts = append(opts, cc.Cpp(func(toks []xc.Token) {
+ if len(toks) != 0 {
+ p := toks[0].Position()
+ if p.Filename != lpos.Filename {
+ fmt.Fprintf(&b, "# %d %q\n", p.Line, p.Filename)
+ }
+ lpos = p
+ }
+ for _, v := range toks {
+ b.WriteString(cc.TokSrc(v))
+ }
+ b.WriteByte('\n')
+ }))
+ }
+
+ ndbg := ""
+ if *ndebug {
+ ndbg = "#define NDEBUG 1"
+ }
+ var build [][]ir.Object
+ tus = append(tus, []string{ccir.CRT0Path})
+ var asta []*cc.TranslationUnit
+ for _, src := range tus {
+ model, err := ccir.NewModel()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ ast, err := cc.Parse(
+ fmt.Sprintf(`
+%s
+#define __arch__ %s
+#define __os__ %s
+#include <builtin.h>
+%s
+`, ndbg, runtime.GOARCH, runtime.GOOS, predef),
+ src,
+ model,
+ append([]cc.Opt{
+ cc.AllowCompatibleTypedefRedefinitions(),
+ cc.EnableImplicitFuncDef(),
+ cc.EnableNonConstStaticInitExpressions(),
+ cc.EnableWideBitFieldTypes(),
+ cc.ErrLimit(*errLimit),
+ cc.SysIncludePaths([]string{ccir.LibcIncludePath}),
+ }, opts...)...,
+ )
+ if s := b.Bytes(); len(s) != 0 {
+ log.Printf("\n%s", s)
+ b.Close()
+ }
+ if err != nil {
+ log.Fatal(errStr(err))
+ }
+
+ asta = append(asta, ast)
+ objs, err := ccir.New(ast)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if *oLog {
+ for i, v := range objs {
+ switch x := v.(type) {
+ case *ir.DataDefinition:
+ fmt.Fprintf(&b, "# [%v]: %T %v %v\n", i, x, x.ObjectBase, x.Value)
+ case *ir.FunctionDefinition:
+ fmt.Fprintf(&b, "# [%v]: %T %v %v\n", i, x, x.ObjectBase, x.Arguments)
+ for i, v := range x.Body {
+ fmt.Fprintf(&b, "%#05x\t%v\n", i, v)
+ }
+ default:
+ log.Fatalf("[%v]: %T %v: %v", i, x, x, err)
+ }
+ }
+ }
+ for i, v := range objs {
+ if err := v.Verify(); err != nil {
+ switch x := v.(type) {
+ case *ir.FunctionDefinition:
+ fmt.Fprintf(&b, "# [%v, err]: %T %v %v\n", i, x, x.ObjectBase, x.Arguments)
+ for i, v := range x.Body {
+ fmt.Fprintf(&b, "%#05x\t%v\n", i, v)
+ }
+ log.Fatalf("# [%v]: Verify (A): %v\n%s", i, err, b.Bytes())
+ default:
+ log.Fatalf("[%v]: %T %v: %v", i, x, x, err)
+ }
+ }
+ }
+ build = append(build, objs)
+ }
+
+ linked, err := ir.LinkMain(build...)
+ if err != nil {
+ log.Fatalf("ir.LinkMain: %s\n%s", err, b.Bytes())
+ }
+
+ for _, v := range linked {
+ if err := v.Verify(); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ bin, err := virtual.LoadMain(linked)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return asta, bin
+}
+
+func macros(buf io.Writer, ast *cc.TranslationUnit) {
+ var a []string
+ for k, v := range ast.Macros {
+ if v.Value != nil && v.Type.Kind() != cc.Bool {
+ switch fn := v.DefTok.Position().Filename; {
+ case
+ fn == "builtin.h",
+ fn == "<predefine>",
+ strings.HasPrefix(fn, "predefined_"):
+ // ignore
+ default:
+ a = append(a, string(dict.S(k)))
+ }
+ }
+ }
+ sort.Strings(a)
+ for _, v := range a {
+ m := ast.Macros[dict.SID(v)]
+ if m.Value == nil {
+ log.Fatal("TODO")
+ }
+
+ switch t := m.Type; t.Kind() {
+ case
+ cc.Int, cc.UInt, cc.Long, cc.ULong, cc.LongLong, cc.ULongLong,
+ cc.Float, cc.LongDouble, cc.Bool:
+ fmt.Fprintf(buf, "X%s = %v\n", v, m.Value)
+ case cc.Ptr:
+ switch t := t.Element(); t.Kind() {
+ case cc.Char:
+ fmt.Fprintf(buf, "X%s = %q\n", v, dict.S(int(m.Value.(cc.StringLitID))))
+ default:
+ log.Fatalf("%v", t.Kind())
+ }
+ default:
+ log.Fatalf("%v", t.Kind())
+ }
+ }
+
+ a = a[:0]
+ for _, v := range ast.Declarations.Identifiers {
+ switch x := v.Node.(type) {
+ case *cc.DirectDeclarator:
+ d := x.TopDeclarator()
+ id, _ := d.Identifier()
+ if x.EnumVal == nil {
+ break
+ }
+
+ a = append(a, string(dict.S(id)))
+ default:
+ log.Fatalf("%T", x)
+ }
+ }
+ sort.Strings(a)
+ for _, v := range a {
+ dd := ast.Declarations.Identifiers[dict.SID(v)].Node.(*cc.DirectDeclarator)
+ fmt.Fprintf(buf, "X%s = %v\n", v, dd.EnumVal)
+ }
+}
+
+func main() {
+ const repo = "sqlite.org/sqlite-amalgamation-3180000/"
+
+ log.SetFlags(log.Lshortfile | log.Lmicroseconds)
+ flag.Parse()
+ pth := findRepo(repo)
+ if pth == "" {
+ log.Fatalf("repository not found: %v", repo)
+ return
+ }
+
+ asta, bin := build(
+ `
+ //#define SQLITE_DEBUG 1
+ //#define SQLITE_ENABLE_API_ARMOR 1
+ #define SQLITE_ENABLE_MEMSYS5 1
+ #define SQLITE_USE_URI 1
+ `,
+ [][]string{
+ {"main.c"},
+ {filepath.Join(pth, "sqlite3.c")},
+ },
+ cc.EnableAnonymousStructFields(),
+ cc.IncludePaths([]string{pth}),
+ )
+
+ var b0 bytes.Buffer
+ enc := gob.NewEncoder(&b0)
+ if err := enc.Encode(&bin); err != nil {
+ log.Fatal(err)
+ }
+
+ var b1 bytes.Buffer
+ comp := gzip.NewWriter(&b1)
+ if _, err := comp.Write(b0.Bytes()); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := comp.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ var b2 buffer.Bytes
+ lic, err := ioutil.ReadFile("SQLITE-LICENSE")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ b2.WriteString(`// Code generated by running "go generate". DO NOT EDIT.
+
+/*
+
+`)
+ b2.Write(lic)
+ b2.WriteString(`
+*/
+
+package bin
+
+const (
+`)
+ macros(&b2, asta[0])
+ b2.WriteString(`
+ Data = "`)
+ b := b1.Bytes()
+ for _, v := range b {
+ switch {
+ case v == '\\':
+ b2.WriteString(`\\`)
+ case v == '"':
+ b2.WriteString(`\"`)
+ case v < ' ', v >= 0x7f:
+ fmt.Fprintf(&b2, `\x%02x`, v)
+ default:
+ b2.WriteByte(v)
+ }
+ }
+ b2.WriteString(`"
+)
+`)
+ b3, err := format.Source(b2.Bytes())
+ if err != nil {
+ b3 = b
+ }
+ os.MkdirAll("internal/bin", 0775)
+ if err := ioutil.WriteFile(fmt.Sprintf("internal/bin/bin_%s_%s.go", runtime.GOOS, runtime.GOARCH), b3, 0664); err != nil {
+ log.Fatal(err)
+ }
+
+ log.Printf("code %#08x, text %#08x, data %#08x, bss %#08x, pc2func %v, pc2line %v, symbols %v, gz %v\n",
+ len(bin.Code), len(bin.Text), len(bin.Data), bin.BSS, len(bin.Functions), len(bin.Lines), len(bin.Sym), b1.Len(),
+ )
+}