compiler: rename getZeroValue to llvm.ConstNull
It does the same thing but should be more complete, and it probably is faster as well (just one CGo call instead of several).
Этот коммит содержится в:
родитель
8d959b7c63
коммит
10ed3decb0
12 изменённых файлов: 26 добавлений и 106 удалений
|
@ -163,7 +163,7 @@ func (c *Compiler) collapseFormalParamInternal(t llvm.Type, fields []llvm.Value)
|
|||
switch t.TypeKind() {
|
||||
case llvm.StructTypeKind:
|
||||
if len(c.flattenAggregateType(t)) <= MaxFieldsPerParam {
|
||||
value := c.getZeroValue(t)
|
||||
value := llvm.ConstNull(t)
|
||||
for i, subtyp := range t.StructElementTypes() {
|
||||
structField, remaining := c.collapseFormalParamInternal(subtyp, fields)
|
||||
fields = remaining
|
||||
|
|
|
@ -124,7 +124,7 @@ func (c *Compiler) emitSelect(frame *Frame, expr *ssa.Select) llvm.Value {
|
|||
chanSelectStateType := c.getLLVMRuntimeType("chanSelectState")
|
||||
for _, state := range expr.States {
|
||||
ch := c.getValue(frame, state.Chan)
|
||||
selectState := c.getZeroValue(chanSelectStateType)
|
||||
selectState := llvm.ConstNull(chanSelectStateType)
|
||||
selectState = c.builder.CreateInsertValue(selectState, ch, 0, "")
|
||||
switch state.Dir {
|
||||
case types.RecvOnly:
|
||||
|
|
|
@ -563,42 +563,6 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
|
|||
}
|
||||
}
|
||||
|
||||
// Return a zero LLVM value for any LLVM type. Setting this value as an
|
||||
// initializer has the same effect as setting 'zeroinitializer' on a value.
|
||||
// Sadly, I haven't found a way to do it directly with the Go API but this works
|
||||
// just fine.
|
||||
func (c *Compiler) getZeroValue(typ llvm.Type) llvm.Value {
|
||||
switch typ.TypeKind() {
|
||||
case llvm.ArrayTypeKind:
|
||||
subTyp := typ.ElementType()
|
||||
subVal := c.getZeroValue(subTyp)
|
||||
vals := make([]llvm.Value, typ.ArrayLength())
|
||||
for i := range vals {
|
||||
vals[i] = subVal
|
||||
}
|
||||
return llvm.ConstArray(subTyp, vals)
|
||||
case llvm.FloatTypeKind, llvm.DoubleTypeKind:
|
||||
return llvm.ConstFloat(typ, 0.0)
|
||||
case llvm.IntegerTypeKind:
|
||||
return llvm.ConstInt(typ, 0, false)
|
||||
case llvm.PointerTypeKind:
|
||||
return llvm.ConstPointerNull(typ)
|
||||
case llvm.StructTypeKind:
|
||||
types := typ.StructElementTypes()
|
||||
vals := make([]llvm.Value, len(types))
|
||||
for i, subTyp := range types {
|
||||
vals[i] = c.getZeroValue(subTyp)
|
||||
}
|
||||
if typ.StructName() != "" {
|
||||
return llvm.ConstNamedStruct(typ, vals)
|
||||
} else {
|
||||
return c.ctx.ConstStruct(vals, false)
|
||||
}
|
||||
default:
|
||||
panic("unknown LLVM zero inititializer: " + typ.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Is this a pointer type of some sort? Can be unsafe.Pointer or any *T pointer.
|
||||
func isPointer(typ types.Type) bool {
|
||||
if _, ok := typ.(*types.Pointer); ok {
|
||||
|
@ -1132,7 +1096,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) {
|
|||
c.builder.CreateRet(c.getValue(frame, instr.Results[0]))
|
||||
} else {
|
||||
// Multiple return values. Put them all in a struct.
|
||||
retVal := c.getZeroValue(frame.fn.LLVMFn.Type().ElementType().ReturnType())
|
||||
retVal := llvm.ConstNull(frame.fn.LLVMFn.Type().ElementType().ReturnType())
|
||||
for i, result := range instr.Results {
|
||||
val := c.getValue(frame, result)
|
||||
retVal = c.builder.CreateInsertValue(retVal, val, i, "")
|
||||
|
@ -1460,7 +1424,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
} else {
|
||||
buf := c.createEntryBlockAlloca(typ, expr.Comment)
|
||||
if c.targetData.TypeAllocSize(typ) != 0 {
|
||||
c.builder.CreateStore(c.getZeroValue(typ), buf) // zero-initialize var
|
||||
c.builder.CreateStore(llvm.ConstNull(typ), buf) // zero-initialize var
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
@ -1767,7 +1731,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
panic("unknown type in range: " + typ.String())
|
||||
}
|
||||
it, _, _ := c.createTemporaryAlloca(iteratorType, "range.it")
|
||||
c.builder.CreateStore(c.getZeroValue(iteratorType), it)
|
||||
c.builder.CreateStore(llvm.ConstNull(iteratorType), it)
|
||||
return it, nil
|
||||
case *ssa.Select:
|
||||
return c.emitSelect(frame, expr), nil
|
||||
|
@ -2349,12 +2313,12 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value {
|
|||
if expr.Value != nil {
|
||||
panic("expected nil chan constant")
|
||||
}
|
||||
return c.getZeroValue(c.getLLVMType(expr.Type()))
|
||||
return llvm.ConstNull(c.getLLVMType(expr.Type()))
|
||||
case *types.Signature:
|
||||
if expr.Value != nil {
|
||||
panic("expected nil signature constant")
|
||||
}
|
||||
return c.getZeroValue(c.getLLVMType(expr.Type()))
|
||||
return llvm.ConstNull(c.getLLVMType(expr.Type()))
|
||||
case *types.Interface:
|
||||
if expr.Value != nil {
|
||||
panic("expected nil interface constant")
|
||||
|
@ -2389,7 +2353,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value {
|
|||
panic("non-nil map constant")
|
||||
}
|
||||
llvmType := c.getLLVMType(typ)
|
||||
return c.getZeroValue(llvmType)
|
||||
return llvm.ConstNull(llvmType)
|
||||
default:
|
||||
panic("unknown constant: " + expr.String())
|
||||
}
|
||||
|
@ -2581,7 +2545,7 @@ func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
|
|||
unop.X.Type().Underlying().(*types.Pointer).Elem()
|
||||
if c.targetData.TypeAllocSize(x.Type().ElementType()) == 0 {
|
||||
// zero-length data
|
||||
return c.getZeroValue(x.Type().ElementType()), nil
|
||||
return llvm.ConstNull(x.Type().ElementType()), nil
|
||||
} else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
|
||||
// CGo function pointer. The cgo part has rewritten CGo function
|
||||
// pointers as stub global variables of the form:
|
||||
|
|
|
@ -122,7 +122,7 @@ func (c *Compiler) emitDefer(frame *Frame, instr *ssa.Defer) {
|
|||
|
||||
// Make a struct out of the collected values to put in the defer frame.
|
||||
deferFrameType := c.ctx.StructType(valueTypes, false)
|
||||
deferFrame := c.getZeroValue(deferFrameType)
|
||||
deferFrame := llvm.ConstNull(deferFrameType)
|
||||
for i, value := range values {
|
||||
deferFrame = c.builder.CreateInsertValue(deferFrame, value, i, "")
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ func (c *Compiler) makeGCStackSlots() bool {
|
|||
}
|
||||
stackChainStart := c.mod.NamedGlobal("runtime.stackChainStart")
|
||||
if !stackChainStart.IsNil() {
|
||||
stackChainStart.SetInitializer(c.getZeroValue(stackChainStart.Type().ElementType()))
|
||||
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType()))
|
||||
stackChainStart.SetGlobalConstant(true)
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ func (c *Compiler) makeGCStackSlots() bool {
|
|||
panic("stack chain start not found!")
|
||||
}
|
||||
stackChainStartType := stackChainStart.Type().ElementType()
|
||||
stackChainStart.SetInitializer(c.getZeroValue(stackChainStartType))
|
||||
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
|
||||
|
||||
// Iterate until runtime.trackPointer has no uses left.
|
||||
for use := trackPointer.FirstUse(); !use.IsNil(); use = trackPointer.FirstUse() {
|
||||
|
@ -303,7 +303,7 @@ func (c *Compiler) makeGCStackSlots() bool {
|
|||
// Create the stack object at the function entry.
|
||||
c.builder.SetInsertPointBefore(fn.EntryBasicBlock().FirstInstruction())
|
||||
stackObject := c.builder.CreateAlloca(stackObjectType, "gc.stackobject")
|
||||
initialStackObject := c.getZeroValue(stackObjectType)
|
||||
initialStackObject := llvm.ConstNull(stackObjectType)
|
||||
numSlots := (c.targetData.TypeAllocSize(stackObjectType) - c.targetData.TypeAllocSize(c.i8ptrType)*2) / uint64(c.targetData.ABITypeAlignment(c.uintptrType))
|
||||
numSlotsValue := llvm.ConstInt(c.uintptrType, numSlots, false)
|
||||
initialStackObject = llvm.ConstInsertValue(initialStackObject, numSlotsValue, []uint32{1})
|
||||
|
|
|
@ -74,7 +74,7 @@ func (c *Compiler) getTypeCode(typ types.Type) llvm.Value {
|
|||
}
|
||||
if !references.IsNil() {
|
||||
// Set the 'references' field of the runtime.typecodeID struct.
|
||||
globalValue := c.getZeroValue(global.Type().ElementType())
|
||||
globalValue := llvm.ConstNull(global.Type().ElementType())
|
||||
globalValue = llvm.ConstInsertValue(globalValue, references, []uint32{0})
|
||||
if length != 0 {
|
||||
lengthValue := llvm.ConstInt(c.uintptrType, uint64(length), false)
|
||||
|
@ -96,9 +96,9 @@ func (c *Compiler) makeStructTypeFields(typ *types.Struct) llvm.Value {
|
|||
runtimeStructField := c.getLLVMRuntimeType("structField")
|
||||
structGlobalType := llvm.ArrayType(runtimeStructField, typ.NumFields())
|
||||
structGlobal := llvm.AddGlobal(c.mod, structGlobalType, "reflect/types.structFields")
|
||||
structGlobalValue := c.getZeroValue(structGlobalType)
|
||||
structGlobalValue := llvm.ConstNull(structGlobalType)
|
||||
for i := 0; i < typ.NumFields(); i++ {
|
||||
fieldGlobalValue := c.getZeroValue(runtimeStructField)
|
||||
fieldGlobalValue := llvm.ConstNull(runtimeStructField)
|
||||
fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, c.getTypeCode(typ.Field(i).Type()), []uint32{0})
|
||||
fieldName := c.makeGlobalArray([]byte(typ.Field(i).Name()), "reflect/types.structFieldName", c.ctx.Int8Type())
|
||||
fieldName.SetLinkage(llvm.PrivateLinkage)
|
||||
|
@ -380,7 +380,7 @@ func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) llvm.Valu
|
|||
// Continue after the if statement.
|
||||
c.builder.SetInsertPointAtEnd(nextBlock)
|
||||
phi := c.builder.CreatePHI(assertedType, "typeassert.value")
|
||||
phi.AddIncoming([]llvm.Value{c.getZeroValue(assertedType), valueOk}, []llvm.BasicBlock{prevBlock, okBlock})
|
||||
phi.AddIncoming([]llvm.Value{llvm.ConstNull(assertedType), valueOk}, []llvm.BasicBlock{prevBlock, okBlock})
|
||||
|
||||
if expr.CommaOk {
|
||||
tuple := c.ctx.ConstStruct([]llvm.Value{llvm.Undef(assertedType), llvm.Undef(c.ctx.Int1Type())}, false) // create empty tuple
|
||||
|
|
|
@ -289,7 +289,7 @@ func (c *Compiler) OptimizeAllocs() {
|
|||
sizeInWords := (size + uint64(alignment) - 1) / uint64(alignment)
|
||||
allocaType := llvm.ArrayType(c.ctx.IntType(alignment*8), int(sizeInWords))
|
||||
alloca := c.builder.CreateAlloca(allocaType, "stackalloc.alloca")
|
||||
zero := c.getZeroValue(alloca.Type().ElementType())
|
||||
zero := llvm.ConstNull(alloca.Type().ElementType())
|
||||
c.builder.CreateStore(zero, alloca)
|
||||
stackalloc := c.builder.CreateBitCast(alloca, bitcast.Type(), "stackalloc")
|
||||
bitcast.ReplaceAllUsesWith(stackalloc)
|
||||
|
|
|
@ -61,7 +61,7 @@ func (c *Compiler) getGlobal(g *ssa.Global) llvm.Value {
|
|||
llvmType := c.getLLVMType(g.Type().(*types.Pointer).Elem())
|
||||
llvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName)
|
||||
if !info.extern {
|
||||
llvmGlobal.SetInitializer(c.getZeroValue(llvmType))
|
||||
llvmGlobal.SetInitializer(llvm.ConstNull(llvmType))
|
||||
llvmGlobal.SetLinkage(llvm.InternalLinkage)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ func (c *Compiler) emitPointerUnpack(ptr llvm.Value, valueTypes []llvm.Type) []l
|
|||
for i, valueType := range valueTypes {
|
||||
if c.targetData.TypeAllocSize(valueType) == 0 {
|
||||
// This value has length zero, so there's nothing to load.
|
||||
values[i] = c.getZeroValue(valueType)
|
||||
values[i] = llvm.ConstNull(valueType)
|
||||
continue
|
||||
}
|
||||
indices := []llvm.Value{
|
||||
|
|
|
@ -86,7 +86,7 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
|
|||
case !inst.IsAAllocaInst().IsNil():
|
||||
allocType := inst.Type().ElementType()
|
||||
alloca := llvm.AddGlobal(fr.Mod, allocType, fr.pkgName+"$alloca")
|
||||
alloca.SetInitializer(getZeroValue(allocType))
|
||||
alloca.SetInitializer(llvm.ConstNull(allocType))
|
||||
alloca.SetLinkage(llvm.InternalLinkage)
|
||||
fr.locals[inst] = &LocalValue{
|
||||
Underlying: alloca,
|
||||
|
@ -253,7 +253,7 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
|
|||
allocType = llvm.ArrayType(allocType, elementCount)
|
||||
}
|
||||
alloc := llvm.AddGlobal(fr.Mod, allocType, fr.pkgName+"$alloc")
|
||||
alloc.SetInitializer(getZeroValue(allocType))
|
||||
alloc.SetInitializer(llvm.ConstNull(allocType))
|
||||
alloc.SetLinkage(llvm.InternalLinkage)
|
||||
result := &LocalValue{
|
||||
Underlying: alloc,
|
||||
|
@ -312,7 +312,7 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
|
|||
stringType := fr.Mod.GetTypeByName("runtime._string")
|
||||
retPtr := llvm.ConstGEP(global, getLLVMIndices(fr.Mod.Context().Int32Type(), []uint32{0, 0}))
|
||||
retLen := llvm.ConstInt(stringType.StructElementTypes()[1], uint64(len(result)), false)
|
||||
ret := getZeroValue(stringType)
|
||||
ret := llvm.ConstNull(stringType)
|
||||
ret = llvm.ConstInsertValue(ret, retPtr, []uint32{0})
|
||||
ret = llvm.ConstInsertValue(ret, retLen, []uint32{1})
|
||||
fr.locals[inst] = &LocalValue{fr.Eval, ret}
|
||||
|
@ -335,7 +335,7 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
|
|||
sliceType := inst.Type()
|
||||
retPtr := llvm.ConstGEP(global, getLLVMIndices(fr.Mod.Context().Int32Type(), []uint32{0, 0}))
|
||||
retLen := llvm.ConstInt(sliceType.StructElementTypes()[1], uint64(len(result)), false)
|
||||
ret := getZeroValue(sliceType)
|
||||
ret := llvm.ConstNull(sliceType)
|
||||
ret = llvm.ConstInsertValue(ret, retPtr, []uint32{0}) // ptr
|
||||
ret = llvm.ConstInsertValue(ret, retLen, []uint32{1}) // len
|
||||
ret = llvm.ConstInsertValue(ret, retLen, []uint32{2}) // cap
|
||||
|
|
|
@ -16,50 +16,6 @@ func getUses(value llvm.Value) []llvm.Value {
|
|||
return uses
|
||||
}
|
||||
|
||||
// Return a zero LLVM value for any LLVM type. Setting this value as an
|
||||
// initializer has the same effect as setting 'zeroinitializer' on a value.
|
||||
// Sadly, I haven't found a way to do it directly with the Go API but this works
|
||||
// just fine.
|
||||
func getZeroValue(typ llvm.Type) llvm.Value {
|
||||
switch typ.TypeKind() {
|
||||
case llvm.ArrayTypeKind:
|
||||
subTyp := typ.ElementType()
|
||||
subVal := getZeroValue(subTyp)
|
||||
vals := make([]llvm.Value, typ.ArrayLength())
|
||||
for i := range vals {
|
||||
vals[i] = subVal
|
||||
}
|
||||
return llvm.ConstArray(subTyp, vals)
|
||||
case llvm.FloatTypeKind, llvm.DoubleTypeKind:
|
||||
return llvm.ConstFloat(typ, 0.0)
|
||||
case llvm.IntegerTypeKind:
|
||||
return llvm.ConstInt(typ, 0, false)
|
||||
case llvm.PointerTypeKind:
|
||||
return llvm.ConstPointerNull(typ)
|
||||
case llvm.StructTypeKind:
|
||||
types := typ.StructElementTypes()
|
||||
vals := make([]llvm.Value, len(types))
|
||||
for i, subTyp := range types {
|
||||
val := getZeroValue(subTyp)
|
||||
vals[i] = val
|
||||
}
|
||||
if typ.StructName() != "" {
|
||||
return llvm.ConstNamedStruct(typ, vals)
|
||||
} else {
|
||||
return typ.Context().ConstStruct(vals, false)
|
||||
}
|
||||
case llvm.VectorTypeKind:
|
||||
zero := getZeroValue(typ.ElementType())
|
||||
vals := make([]llvm.Value, typ.VectorSize())
|
||||
for i := range vals {
|
||||
vals[i] = zero
|
||||
}
|
||||
return llvm.ConstVector(vals, false)
|
||||
default:
|
||||
panic("interp: unknown LLVM type: " + typ.String())
|
||||
}
|
||||
}
|
||||
|
||||
// getStringBytes loads the byte slice of a Go string represented as a
|
||||
// {ptr, len} pair.
|
||||
func getStringBytes(strPtr Value, strLen llvm.Value) []byte {
|
||||
|
|
|
@ -162,7 +162,7 @@ func (v *MapValue) newBucket() llvm.Value {
|
|||
llvm.ArrayType(v.KeyType, 8), // key type
|
||||
llvm.ArrayType(v.ValueType, 8), // value type
|
||||
}, false)
|
||||
bucketValue := getZeroValue(bucketType)
|
||||
bucketValue := llvm.ConstNull(bucketType)
|
||||
bucket := llvm.AddGlobal(v.Eval.Mod, bucketType, v.PkgName+"$mapbucket")
|
||||
bucket.SetInitializer(bucketValue)
|
||||
bucket.SetLinkage(llvm.InternalLinkage)
|
||||
|
@ -311,7 +311,7 @@ func (v *MapValue) PutString(keyBuf, keyLen, valPtr *LocalValue) {
|
|||
|
||||
keyType := v.Eval.Mod.GetTypeByName("runtime._string")
|
||||
v.KeyType = keyType
|
||||
key := getZeroValue(keyType)
|
||||
key := llvm.ConstNull(keyType)
|
||||
key = llvm.ConstInsertValue(key, keyBuf.Value(), []uint32{0})
|
||||
key = llvm.ConstInsertValue(key, keyLen.Value(), []uint32{1})
|
||||
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче