Implement printing of int8/uint8/pointers
Этот коммит содержится в:
родитель
e171f32493
коммит
320c583221
3 изменённых файлов: 80 добавлений и 6 удалений
|
@ -1,12 +1,40 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
func printstring(s string) {
|
func printstring(s string) {
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
putchar(s[i])
|
putchar(s[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printuint8(n uint8) {
|
||||||
|
if TargetBits >= 32 {
|
||||||
|
printuint32(uint32(n))
|
||||||
|
} else {
|
||||||
|
prevdigits := n / 10
|
||||||
|
if prevdigits != 0 {
|
||||||
|
printuint8(prevdigits)
|
||||||
|
}
|
||||||
|
putchar(byte((n % 10) + '0'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printint8(n int8) {
|
||||||
|
if TargetBits >= 32 {
|
||||||
|
printint32(int32(n))
|
||||||
|
} else {
|
||||||
|
if n < 0 {
|
||||||
|
putchar('-')
|
||||||
|
n = -n
|
||||||
|
}
|
||||||
|
printuint8(uint8(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func printuint32(n uint32) {
|
func printuint32(n uint32) {
|
||||||
// TODO: don't recurse, but still be compact (and don't divide/mod
|
// TODO: don't recurse, but still be compact (and don't divide/mod
|
||||||
// more than necessary).
|
// more than necessary).
|
||||||
|
@ -64,3 +92,17 @@ func printitf(msg interface{}) {
|
||||||
print("???")
|
print("???")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printptr(ptr uintptr) {
|
||||||
|
putchar('0')
|
||||||
|
putchar('x')
|
||||||
|
for i := 0; i < int(unsafe.Sizeof(ptr)) * 2; i++ {
|
||||||
|
nibble := byte(ptr >> (unsafe.Sizeof(ptr) * 8 - 4))
|
||||||
|
if nibble < 10 {
|
||||||
|
putchar(nibble + '0')
|
||||||
|
} else {
|
||||||
|
putchar(nibble - 10 + 'a')
|
||||||
|
}
|
||||||
|
ptr <<= 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ package runtime
|
||||||
|
|
||||||
const Compiler = "tgo"
|
const Compiler = "tgo"
|
||||||
|
|
||||||
|
// The bitness of the CPU (e.g. 8, 32, 64). Set by the compiler as a constant.
|
||||||
|
var TargetBits uint8
|
||||||
|
|
||||||
func _panic(message interface{}) {
|
func _panic(message interface{}) {
|
||||||
printstring("panic: ")
|
printstring("panic: ")
|
||||||
printitf(message)
|
printitf(message)
|
||||||
|
|
41
tgo.go
41
tgo.go
|
@ -113,7 +113,12 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
|
||||||
tripleSplit := strings.Split(c.triple, "-")
|
tripleSplit := strings.Split(c.triple, "-")
|
||||||
|
|
||||||
config := loader.Config {
|
config := loader.Config {
|
||||||
// TODO: TypeChecker.Sizes
|
TypeChecker: types.Config{
|
||||||
|
Sizes: &types.StdSizes{
|
||||||
|
int64(c.targetData.PointerSize()),
|
||||||
|
int64(c.targetData.PrefTypeAlignment(c.i8ptrType)),
|
||||||
|
},
|
||||||
|
},
|
||||||
Build: &build.Context {
|
Build: &build.Context {
|
||||||
GOARCH: tripleSplit[0],
|
GOARCH: tripleSplit[0],
|
||||||
GOOS: tripleSplit[2],
|
GOOS: tripleSplit[2],
|
||||||
|
@ -390,11 +395,25 @@ func (c *Compiler) parsePackage(program *ssa.Program, pkg *ssa.Package) error {
|
||||||
global := llvm.AddGlobal(c.mod, llvmType, c.getGlobalName(member))
|
global := llvm.AddGlobal(c.mod, llvmType, c.getGlobalName(member))
|
||||||
if !strings.HasPrefix(member.Name(), "_extern_") {
|
if !strings.HasPrefix(member.Name(), "_extern_") {
|
||||||
global.SetLinkage(llvm.PrivateLinkage)
|
global.SetLinkage(llvm.PrivateLinkage)
|
||||||
initializer, err := c.getZeroValue(llvmType)
|
if c.getGlobalName(member) == "runtime.TargetBits" {
|
||||||
if err != nil {
|
bitness := c.targetData.PointerSize()
|
||||||
return err
|
if bitness < 32 {
|
||||||
|
// Only 8 and 32+ architectures supported at the moment.
|
||||||
|
// On 8 bit architectures, pointers are normally bigger
|
||||||
|
// than 8 bits to do anything meaningful.
|
||||||
|
// TODO: clean up this hack to support 16-bit
|
||||||
|
// architectures.
|
||||||
|
bitness = 8
|
||||||
|
}
|
||||||
|
global.SetInitializer(llvm.ConstInt(llvm.Int8Type(), uint64(bitness), false))
|
||||||
|
global.SetGlobalConstant(true)
|
||||||
|
} else {
|
||||||
|
initializer, err := c.getZeroValue(llvmType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
global.SetInitializer(initializer)
|
||||||
}
|
}
|
||||||
global.SetInitializer(initializer)
|
|
||||||
}
|
}
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
ms := program.MethodSets.MethodSet(member.Type())
|
ms := program.MethodSets.MethodSet(member.Type())
|
||||||
|
@ -714,8 +733,10 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
|
case types.Int8:
|
||||||
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printint8"), []llvm.Value{value}, "")
|
||||||
case types.Uint8:
|
case types.Uint8:
|
||||||
c.builder.CreateCall(c.mod.NamedFunction("runtime.printbyte"), []llvm.Value{value}, "")
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint8"), []llvm.Value{value}, "")
|
||||||
case types.Int, types.Int32: // TODO: assumes a 32-bit int type
|
case types.Int, types.Int32: // TODO: assumes a 32-bit int type
|
||||||
c.builder.CreateCall(c.mod.NamedFunction("runtime.printint32"), []llvm.Value{value}, "")
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printint32"), []llvm.Value{value}, "")
|
||||||
case types.Uint, types.Uint32:
|
case types.Uint, types.Uint32:
|
||||||
|
@ -726,9 +747,17 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
|
||||||
c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint64"), []llvm.Value{value}, "")
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint64"), []llvm.Value{value}, "")
|
||||||
case types.String:
|
case types.String:
|
||||||
c.builder.CreateCall(c.mod.NamedFunction("runtime.printstring"), []llvm.Value{value}, "")
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printstring"), []llvm.Value{value}, "")
|
||||||
|
case types.Uintptr:
|
||||||
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printptr"), []llvm.Value{value}, "")
|
||||||
|
case types.UnsafePointer:
|
||||||
|
ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "")
|
||||||
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printptr"), []llvm.Value{ptrValue}, "")
|
||||||
default:
|
default:
|
||||||
return llvm.Value{}, errors.New("unknown basic arg type: " + fmt.Sprintf("%#v", typ))
|
return llvm.Value{}, errors.New("unknown basic arg type: " + fmt.Sprintf("%#v", typ))
|
||||||
}
|
}
|
||||||
|
case *types.Pointer:
|
||||||
|
ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "")
|
||||||
|
c.builder.CreateCall(c.mod.NamedFunction("runtime.printptr"), []llvm.Value{ptrValue}, "")
|
||||||
default:
|
default:
|
||||||
return llvm.Value{}, errors.New("unknown arg type: " + fmt.Sprintf("%#v", typ))
|
return llvm.Value{}, errors.New("unknown arg type: " + fmt.Sprintf("%#v", typ))
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче