diff options
author | Jan Mercl <0xjnml@gmail.com> | 2017-06-05 20:13:10 +0200 |
---|---|---|
committer | Jan Mercl <0xjnml@gmail.com> | 2017-06-05 20:13:10 +0200 |
commit | 8c183b526ba8f225684f6431836138a9cffae509 (patch) | |
tree | 4afc11a44fe89e0e7081f00085eed90357218fac /generator_windows.go | |
parent | 1a3b0a731a9d2b66fb058caef95c004634b17307 (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.go | 366 |
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(), + ) +} |