// HookBuiltin uses the builtin package that provides neccessary // builtin functions for IR generation func (p *Pkg) HookBuiltin(pkg *link8.Pkg) error { var err error se := func(e error) { if err != nil { err = e } } o := func(f string) *FuncSym { sym := pkg.SymbolByName(f) if sym == nil { se(fmt.Errorf("%s missing in builtin", f)) } else if sym.Type != link8.SymFunc { se(fmt.Errorf("%s is not a function", f)) } return &FuncSym{pkg: pkg.Path(), name: f} } p.g.memCopy = o("MemCopy") p.g.memClear = o("MemClear") return err }
func (p *strPool) declare(lib *link8.Pkg) { if lib.Path() != p.pkg { panic("package name mismatch") } ndigit := countDigit(len(p.strs)) nfmt := fmt.Sprintf(":str_%%0%dd", ndigit) for i, s := range p.strs { s.name = fmt.Sprintf(nfmt, i) s.pkg = p.pkg v := link8.NewVar(0) v.Write([]byte(s.str)) lib.DeclareVar(s.name) lib.DefineVar(s.name, v) } }
func (p *datPool) declare(lib *link8.Pkg) { if lib.Path() != p.pkg { panic("package name mismatch") } if len(p.dat) == 0 { return } ndigit := countDigit(len(p.dat)) nfmt := fmt.Sprintf(":dat_%%0%dd", ndigit) for i, d := range p.dat { d.name = fmt.Sprintf(nfmt, i) align := uint32(0) if d.regSizeAlign { align = regSize } v := link8.NewVar(align) v.Write(d.bs) lib.DeclareVar(d.name) lib.DefineVar(d.name, v) } }
func declareBuiltin(b *builder, builtin *link8.Pkg) { path := builtin.Path() e := b.p.HookBuiltin(builtin) if e != nil { b.Errorf(nil, e.Error()) return } o := func(name, as string, t *types.Func) ir.Ref { sym := builtin.SymbolByName(name) if sym == nil { b.Errorf(nil, "builtin symbol %s missing", name) return nil } else if sym.Type != link8.SymFunc { b.Errorf(nil, "builtin symbol %s is not a function", name) return nil } ref := ir.NewFuncSym(path, name, makeFuncSig(t)) obj := &objFunc{name: as, ref: newRef(t, ref)} s := sym8.Make(b.path, as, tast.SymFunc, obj, t, nil) pre := b.scope.Declare(s) if pre != nil { b.Errorf(nil, "builtin symbol %s declare failed", name) return nil } return ref } // TODO: export these as generic function pointer symbols, and convert // them into G functions in g files, rather than inside here in the // compiler. o("PrintInt32", "printInt", types.NewVoidFunc(types.Int)) o("PrintUint32", "printUint", types.NewVoidFunc(types.Uint)) o("PrintChar", "printChar", types.NewVoidFunc(types.Int8)) b.panicFunc = o("Panic", "panic", types.VoidFunc) bi := func(name string) { t := types.NewBuiltInFunc(name) obj := &objFunc{name: name, ref: newRef(t, nil)} s := sym8.Make(b.path, name, tast.SymFunc, obj, t, nil) pre := b.scope.Declare(s) if pre != nil { b.Errorf(nil, "builtin symbol %s declare failed", name) } } bi("len") bi("make") c := func(name string, r *ref) { // TODO: declare these as typed consts obj := &objConst{name, r} s := sym8.Make(b.path, name, tast.SymConst, obj, r.Type(), nil) pre := b.scope.Declare(s) if pre != nil { b.Errorf(nil, "builtin symbol %s declare failed", name) } } c("true", refTrue) c("false", refFalse) c("nil", refNil) t := func(name string, t types.T) { s := sym8.Make(b.path, name, tast.SymType, nil, &types.Type{t}, nil) pre := b.scope.Declare(s) if pre != nil { b.Errorf(nil, "builtin symbol %s declare failed", name) } } t("int", types.Int) t("uint", types.Uint) t("int32", types.Int) t("uint32", types.Uint) t("int8", types.Int8) t("uint8", types.Uint8) t("char", types.Int8) t("byte", types.Uint8) t("bool", types.Bool) t("float", types.Float32) t("string", types.String) // t("ptr", &types.Pointer{types.Uint8}) // t("float32", types.Float32) // t("string", types.String) }