mirror of
https://github.com/glebarez/go-sqlite.git
synced 2025-10-04 23:42:40 +08:00
switch windows to CRT, throw out old virtual
This commit is contained in:
@@ -1,494 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cznic/virtual"
|
||||
)
|
||||
|
||||
func caller(s string, va ...interface{}) {
|
||||
if s == "" {
|
||||
s = strings.Repeat("%v ", len(va))
|
||||
}
|
||||
_, fn, fl, _ := runtime.Caller(2)
|
||||
fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl)
|
||||
fmt.Fprintf(os.Stderr, s, va...)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
_, fn, fl, _ = runtime.Caller(1)
|
||||
fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
|
||||
func dbg(s string, va ...interface{}) {
|
||||
if s == "" {
|
||||
s = strings.Repeat("%v ", len(va))
|
||||
}
|
||||
_, fn, fl, _ := runtime.Caller(1)
|
||||
fmt.Fprintf(os.Stderr, "# dbg %s:%d: ", path.Base(fn), fl)
|
||||
fmt.Fprintf(os.Stderr, s, va...)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
|
||||
func TODO(...interface{}) string { //TODOOK
|
||||
_, fn, fl, _ := runtime.Caller(1)
|
||||
return fmt.Sprintf("# TODO: %s:%d:\n", path.Base(fn), fl) //TODOOK
|
||||
}
|
||||
|
||||
func use(...interface{}) {}
|
||||
|
||||
func init() {
|
||||
use(caller, dbg, TODO) //TODOOK
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
var (
|
||||
// Add "-tags virtual.profile" to the command.
|
||||
profileAll = flag.Bool("profile", false, "")
|
||||
profileFunctions = flag.Bool("profile_functions", false, "")
|
||||
profileInstructions = flag.Bool("profile_instructions", false, "")
|
||||
profileLines = flag.Bool("profile_lines", false, "")
|
||||
profileRate = flag.Int("profile_rate", 1000, "")
|
||||
recsPerSec = flag.Bool("recs_per_sec_as_mbps", false, "Show records per second as MB/s.")
|
||||
)
|
||||
|
||||
func tempDB(t testing.TB) (string, *sql.DB) {
|
||||
dir, err := ioutil.TempDir("", "sqlite-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
db, err := sql.Open(driverName, filepath.Join(dir, "tmp.db"))
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return dir, db
|
||||
}
|
||||
|
||||
func TestScalar(t *testing.T) {
|
||||
dir, db := tempDB(t)
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
t1 := time.Date(2017, 4, 20, 1, 2, 3, 56789, time.UTC)
|
||||
t2 := time.Date(2018, 5, 21, 2, 3, 4, 98765, time.UTC)
|
||||
r, err := db.Exec(`
|
||||
create table t(i int, f double, b bool, s text, t time);
|
||||
insert into t values(12, 3.14, ?, "foo", ?), (34, 2.78, ?, "bar", ?);
|
||||
`,
|
||||
true, t1,
|
||||
false, t2,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
n, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if g, e := n, int64(2); g != e {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
|
||||
rows, err := db.Query("select * from t")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
type rec struct {
|
||||
i int
|
||||
f float64
|
||||
b bool
|
||||
s string
|
||||
t string
|
||||
}
|
||||
var a []rec
|
||||
for rows.Next() {
|
||||
var r rec
|
||||
if err := rows.Scan(&r.i, &r.f, &r.b, &r.s, &r.t); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a = append(a, r)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if g, e := len(a), 2; g != e {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
|
||||
if g, e := a[0], (rec{12, 3.14, true, "foo", t1.String()}); g != e {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
|
||||
if g, e := a[1], (rec{34, 2.78, false, "bar", t2.String()}); g != e {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlob(t *testing.T) {
|
||||
dir, db := tempDB(t)
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
b1 := []byte(time.Now().String())
|
||||
b2 := []byte("\x00foo\x00bar\x00")
|
||||
if _, err := db.Exec(`
|
||||
create table t(b blob);
|
||||
insert into t values(?), (?);
|
||||
`, b1, b2,
|
||||
); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rows, err := db.Query("select * from t")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
type rec struct {
|
||||
b []byte
|
||||
}
|
||||
var a []rec
|
||||
for rows.Next() {
|
||||
var r rec
|
||||
if err := rows.Scan(&r.b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
a = append(a, r)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if g, e := len(a), 2; g != e {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
|
||||
if g, e := a[0].b, b1; !bytes.Equal(g, e) {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
|
||||
if g, e := a[1].b, b2; !bytes.Equal(g, e) {
|
||||
t.Fatal(g, e)
|
||||
}
|
||||
}
|
||||
|
||||
func profile(t testing.TB, d time.Duration, w io.Writer, format string, arg ...interface{}) {
|
||||
rate := vm.ProfileRate
|
||||
if rate == 0 {
|
||||
rate = 1
|
||||
}
|
||||
if len(vm.ProfileFunctions)+len(vm.ProfileLines)+len(vm.ProfileInstructions) != 0 {
|
||||
fmt.Fprintf(w, "# %v\n", os.Args[1:])
|
||||
}
|
||||
if len(vm.ProfileFunctions) != 0 {
|
||||
fmt.Fprintf(w, format, arg...)
|
||||
type u struct {
|
||||
virtual.PCInfo
|
||||
n int
|
||||
}
|
||||
var s int64
|
||||
var a []u
|
||||
var wi int
|
||||
for k, v := range vm.ProfileFunctions {
|
||||
a = append(a, u{k, v})
|
||||
s += int64(v)
|
||||
if n := len(k.Name.String()); n > wi {
|
||||
wi = n
|
||||
}
|
||||
}
|
||||
sort.Slice(a, func(i, j int) bool {
|
||||
if a[i].n < a[j].n {
|
||||
return true
|
||||
}
|
||||
|
||||
if a[i].n > a[j].n {
|
||||
return false
|
||||
}
|
||||
|
||||
return a[i].Name < a[j].Name
|
||||
})
|
||||
fmt.Fprintf(w, "---- Profile functions, %v samples in %v, %.3f MIPS, %v/sample\n", s, d, float64(s)/1e6*float64(rate)*float64(time.Second)/float64(d), time.Duration(float64(d)/float64(s)))
|
||||
if x, ok := t.(*testing.B); ok {
|
||||
fmt.Fprintf(w, "\t%v samples/1 [samples/b.N]\n", s/int64(x.N))
|
||||
}
|
||||
var c int64
|
||||
for i := len(a) - 1; i >= 0; i-- {
|
||||
c += int64(a[i].n)
|
||||
fmt.Fprintf(
|
||||
w,
|
||||
"%*v\t%10v%10.2f%%%10.2f%%\n",
|
||||
-wi, a[i].Name, a[i].n,
|
||||
100*float64(a[i].n)/float64(s),
|
||||
100*float64(c)/float64(s),
|
||||
)
|
||||
}
|
||||
}
|
||||
if len(vm.ProfileLines) != 0 {
|
||||
fmt.Fprintf(w, format, arg...)
|
||||
type u struct {
|
||||
virtual.PCInfo
|
||||
n int
|
||||
}
|
||||
var s int64
|
||||
var a []u
|
||||
for k, v := range vm.ProfileLines {
|
||||
a = append(a, u{k, v})
|
||||
s += int64(v)
|
||||
}
|
||||
sort.Slice(a, func(i, j int) bool {
|
||||
if a[i].n < a[j].n {
|
||||
return true
|
||||
}
|
||||
|
||||
if a[i].n > a[j].n {
|
||||
return false
|
||||
}
|
||||
|
||||
if a[i].Name < a[j].Name {
|
||||
return true
|
||||
}
|
||||
|
||||
if a[i].Name > a[j].Name {
|
||||
return false
|
||||
}
|
||||
|
||||
return a[i].Line < a[j].Line
|
||||
})
|
||||
fmt.Fprintf(w, "---- Profile lines, %v samples in %v, %.3f MIPS, %v/sample\n", s, d, float64(s)/1e6*float64(rate)*float64(time.Second)/float64(d), time.Duration(float64(d)/float64(s)))
|
||||
if x, ok := t.(*testing.B); ok {
|
||||
fmt.Fprintf(w, "\t%v samples/1 [samples/b.N]\n", s/int64(x.N))
|
||||
}
|
||||
var c int64
|
||||
for i := len(a) - 1; i >= 0; i-- {
|
||||
c += int64(a[i].n)
|
||||
fmt.Fprintf(
|
||||
w,
|
||||
"%v:%v:\t%10v%10.2f%%%10.2f%%\n",
|
||||
a[i].Name, a[i].Line, a[i].n,
|
||||
100*float64(a[i].n)/float64(s),
|
||||
100*float64(c)/float64(s),
|
||||
)
|
||||
}
|
||||
}
|
||||
if len(vm.ProfileInstructions) != 0 {
|
||||
fmt.Fprintf(w, format, arg...)
|
||||
type u struct {
|
||||
virtual.Opcode
|
||||
n int
|
||||
}
|
||||
var s int64
|
||||
var a []u
|
||||
var wi int
|
||||
for k, v := range vm.ProfileInstructions {
|
||||
a = append(a, u{k, v})
|
||||
s += int64(v)
|
||||
if n := len(k.String()); n > wi {
|
||||
wi = n
|
||||
}
|
||||
}
|
||||
sort.Slice(a, func(i, j int) bool {
|
||||
if a[i].n < a[j].n {
|
||||
return true
|
||||
}
|
||||
|
||||
if a[i].n > a[j].n {
|
||||
return false
|
||||
}
|
||||
|
||||
return a[i].Opcode < a[j].Opcode
|
||||
})
|
||||
fmt.Fprintf(w, "---- Profile instructions, %v samples in %v, %.3f MIPS, %v/sample\n", s, d, float64(s)/1e6*float64(rate)*float64(time.Second)/float64(d), time.Duration(float64(d)/float64(s)))
|
||||
if x, ok := t.(*testing.B); ok {
|
||||
fmt.Fprintf(w, "\t%v samples/1 [samples/b.N]\n", s/int64(x.N))
|
||||
}
|
||||
var c int64
|
||||
for i := len(a) - 1; i >= 0; i-- {
|
||||
c += int64(a[i].n)
|
||||
fmt.Fprintf(
|
||||
w,
|
||||
"%*s%10v%10.2f%%\t%10.2f%%\n",
|
||||
-wi, a[i].Opcode, a[i].n,
|
||||
100*float64(a[i].n)/float64(s),
|
||||
100*float64(c)/float64(s),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsertMemory(b *testing.B) {
|
||||
db, err := sql.Open(driverName, "file::memory:")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
}()
|
||||
|
||||
if _, err := db.Exec(`
|
||||
create table t(i int);
|
||||
begin;
|
||||
`); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := db.Prepare("insert into t values(?)")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
if *profileAll || *profileFunctions {
|
||||
vm.ProfileFunctions = map[virtual.PCInfo]int{}
|
||||
}
|
||||
if *profileAll || *profileLines {
|
||||
vm.ProfileLines = map[virtual.PCInfo]int{}
|
||||
}
|
||||
if *profileAll || *profileInstructions {
|
||||
vm.ProfileInstructions = map[virtual.Opcode]int{}
|
||||
}
|
||||
vm.ProfileRate = int(*profileRate)
|
||||
t0 := time.Now()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := s.Exec(int64(i)); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
b.StopTimer()
|
||||
if *recsPerSec {
|
||||
b.SetBytes(1e6)
|
||||
}
|
||||
d := time.Since(t0)
|
||||
if _, err := db.Exec(`commit;`); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
profile(b, d, os.Stderr, "==== BenchmarkInsertMemory b.N %v\n", b.N)
|
||||
}
|
||||
|
||||
func BenchmarkNextMemory(b *testing.B) {
|
||||
db, err := sql.Open(driverName, "file::memory:")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
}()
|
||||
|
||||
if _, err := db.Exec(`
|
||||
create table t(i int);
|
||||
begin;
|
||||
`); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := db.Prepare("insert into t values(?)")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
defer s.Close()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := s.Exec(int64(i)); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
if _, err := db.Exec("commit"); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
r, err := db.Query("select * from t")
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
|
||||
defer r.Close()
|
||||
|
||||
if *profileAll || *profileFunctions {
|
||||
vm.ProfileFunctions = map[virtual.PCInfo]int{}
|
||||
}
|
||||
if *profileAll || *profileLines {
|
||||
vm.ProfileLines = map[virtual.PCInfo]int{}
|
||||
}
|
||||
if *profileAll || *profileInstructions {
|
||||
vm.ProfileInstructions = map[virtual.Opcode]int{}
|
||||
}
|
||||
vm.ProfileRate = int(*profileRate)
|
||||
t0 := time.Now()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if !r.Next() {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
b.StopTimer()
|
||||
if *recsPerSec {
|
||||
b.SetBytes(1e6)
|
||||
}
|
||||
d := time.Since(t0)
|
||||
profile(b, d, os.Stderr, "==== BenchmarkNextMemory b.N %v\n", b.N)
|
||||
}
|
||||
|
||||
// https://github.com/cznic/sqlite/issues/11
|
||||
func TestIssue11(t *testing.T) {
|
||||
const N = 6570
|
||||
dir, db := tempDB(t)
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
if _, err := db.Exec(`
|
||||
CREATE TABLE t1 (t INT);
|
||||
BEGIN;
|
||||
`,
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i := 0; i < N; i++ {
|
||||
if _, err := db.Exec("INSERT INTO t1 (t) VALUES (?)", i); err != nil {
|
||||
t.Fatalf("#%v: %v", i, err)
|
||||
}
|
||||
}
|
||||
if _, err := db.Exec("COMMIT;"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
// 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.
|
||||
|
||||
//go:generate go run generator_windows.go
|
||||
|
||||
package sqlite
|
@@ -168,6 +168,7 @@ func build(predef string, tus [][]string, opts ...cc.Opt) ([]*cc.TranslationUnit
|
||||
cc.EnableEmptyStructs(),
|
||||
cc.EnableImplicitFuncDef(),
|
||||
cc.EnableNonConstStaticInitExpressions(),
|
||||
cc.EnableWideBitFieldTypes(),
|
||||
cc.ErrLimit(*errLimit),
|
||||
cc.SysIncludePaths([]string{ccir.LibcIncludePath}),
|
||||
}, opts...)...,
|
||||
|
@@ -1,366 +0,0 @@
|
||||
// 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(),
|
||||
)
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1406
sqlite_windows.go
1406
sqlite_windows.go
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user