Make 'int' platform-dependent
Or rather, provide abstraction to make this feature easy to add in the future.
Этот коммит содержится в:
родитель
ea6ec58241
коммит
7be746e2f3
3 изменённых файлов: 14 добавлений и 9 удалений
|
@ -10,7 +10,7 @@ void __go_printstring(string_t *str) {
|
||||||
write(STDOUT_FILENO, str->buf, str->len);
|
write(STDOUT_FILENO, str->buf, str->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __go_printint(int32_t n) {
|
void __go_printint(intgo_t n) {
|
||||||
// Print integer in signed big-endian base-10 notation, for humans to
|
// Print integer in signed big-endian base-10 notation, for humans to
|
||||||
// read.
|
// read.
|
||||||
// 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
|
||||||
|
@ -19,7 +19,7 @@ void __go_printint(int32_t n) {
|
||||||
print("-", 1);
|
print("-", 1);
|
||||||
n = -n;
|
n = -n;
|
||||||
}
|
}
|
||||||
int32_t prevdigits = n / 10;
|
intgo_t prevdigits = n / 10;
|
||||||
if (prevdigits != 0) {
|
if (prevdigits != 0) {
|
||||||
__go_printint(prevdigits);
|
__go_printint(prevdigits);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,4 @@ typedef struct {
|
||||||
uint8_t buf[]; // variable size
|
uint8_t buf[]; // variable size
|
||||||
} string_t;
|
} string_t;
|
||||||
|
|
||||||
void __go_printstring(string_t *str);
|
typedef int32_t intgo_t; // may be 64-bit
|
||||||
void __go_printnl();
|
|
||||||
|
|
16
tgo.go
16
tgo.go
|
@ -29,6 +29,8 @@ type Compiler struct {
|
||||||
ctx llvm.Context
|
ctx llvm.Context
|
||||||
builder llvm.Builder
|
builder llvm.Builder
|
||||||
machine llvm.TargetMachine
|
machine llvm.TargetMachine
|
||||||
|
intType llvm.Type
|
||||||
|
stringLenType llvm.Type
|
||||||
stringType llvm.Type
|
stringType llvm.Type
|
||||||
stringPtrType llvm.Type
|
stringPtrType llvm.Type
|
||||||
printstringFunc llvm.Value
|
printstringFunc llvm.Value
|
||||||
|
@ -50,13 +52,17 @@ func NewCompiler(path, triple string) (*Compiler, error) {
|
||||||
c.ctx = c.mod.Context()
|
c.ctx = c.mod.Context()
|
||||||
c.builder = c.ctx.NewBuilder()
|
c.builder = c.ctx.NewBuilder()
|
||||||
|
|
||||||
|
// Depends on platform (32bit or 64bit), but fix it here for now.
|
||||||
|
c.intType = llvm.Int32Type()
|
||||||
|
c.stringLenType = llvm.Int32Type()
|
||||||
|
|
||||||
// Length-prefixed string.
|
// Length-prefixed string.
|
||||||
c.stringType = llvm.StructType([]llvm.Type{llvm.Int32Type(), llvm.ArrayType(llvm.Int8Type(), 0)}, false)
|
c.stringType = llvm.StructType([]llvm.Type{c.stringLenType, llvm.ArrayType(llvm.Int8Type(), 0)}, false)
|
||||||
c.stringPtrType = llvm.PointerType(c.stringType, 0)
|
c.stringPtrType = llvm.PointerType(c.stringType, 0)
|
||||||
|
|
||||||
printstringType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{c.stringPtrType}, false)
|
printstringType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{c.stringPtrType}, false)
|
||||||
c.printstringFunc = llvm.AddFunction(c.mod, "__go_printstring", printstringType)
|
c.printstringFunc = llvm.AddFunction(c.mod, "__go_printstring", printstringType)
|
||||||
printintType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{llvm.Int32Type()}, false)
|
printintType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{c.intType}, false)
|
||||||
c.printintFunc = llvm.AddFunction(c.mod, "__go_printint", printintType)
|
c.printintFunc = llvm.AddFunction(c.mod, "__go_printint", printintType)
|
||||||
printspaceType := llvm.FunctionType(llvm.VoidType(), nil, false)
|
printspaceType := llvm.FunctionType(llvm.VoidType(), nil, false)
|
||||||
c.printspaceFunc = llvm.AddFunction(c.mod, "__go_printspace", printspaceType)
|
c.printspaceFunc = llvm.AddFunction(c.mod, "__go_printspace", printspaceType)
|
||||||
|
@ -192,7 +198,7 @@ func (c *Compiler) parseBuiltin(instr *ssa.CallCommon, call *ssa.Builtin) error
|
||||||
switch expr.Type() {
|
switch expr.Type() {
|
||||||
case c.stringPtrType:
|
case c.stringPtrType:
|
||||||
c.builder.CreateCall(c.printstringFunc, []llvm.Value{*expr}, "")
|
c.builder.CreateCall(c.printstringFunc, []llvm.Value{*expr}, "")
|
||||||
case llvm.Int32Type():
|
case c.intType:
|
||||||
c.builder.CreateCall(c.printintFunc, []llvm.Value{*expr}, "")
|
c.builder.CreateCall(c.printintFunc, []llvm.Value{*expr}, "")
|
||||||
default:
|
default:
|
||||||
return errors.New("unknown arg type")
|
return errors.New("unknown arg type")
|
||||||
|
@ -252,7 +258,7 @@ func (c *Compiler) parseExpr(expr ssa.Value) (*llvm.Value, error) {
|
||||||
case constant.String:
|
case constant.String:
|
||||||
str := constant.StringVal(expr.Value)
|
str := constant.StringVal(expr.Value)
|
||||||
strVal := c.ctx.ConstString(str, false)
|
strVal := c.ctx.ConstString(str, false)
|
||||||
strLen := llvm.ConstInt(llvm.Int32Type(), uint64(len(str)), false)
|
strLen := llvm.ConstInt(c.stringLenType, uint64(len(str)), false)
|
||||||
strObj := llvm.ConstStruct([]llvm.Value{strLen, strVal}, false)
|
strObj := llvm.ConstStruct([]llvm.Value{strLen, strVal}, false)
|
||||||
ptr := llvm.AddGlobal(c.mod, strObj.Type(), ".str")
|
ptr := llvm.AddGlobal(c.mod, strObj.Type(), ".str")
|
||||||
ptr.SetInitializer(strObj)
|
ptr.SetInitializer(strObj)
|
||||||
|
@ -261,7 +267,7 @@ func (c *Compiler) parseExpr(expr ssa.Value) (*llvm.Value, error) {
|
||||||
return &ptrCast, nil
|
return &ptrCast, nil
|
||||||
case constant.Int:
|
case constant.Int:
|
||||||
n, _ := constant.Int64Val(expr.Value) // TODO: do something with the 'exact' return value?
|
n, _ := constant.Int64Val(expr.Value) // TODO: do something with the 'exact' return value?
|
||||||
val := llvm.ConstInt(llvm.Int32Type(), uint64(n), true)
|
val := llvm.ConstInt(c.intType, uint64(n), true)
|
||||||
return &val, nil
|
return &val, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("todo: unknown constant")
|
return nil, errors.New("todo: unknown constant")
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче