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).
This commit is contained in:
Ayke van Laethem
2019-09-15 16:42:31 +02:00
committed by Ron Evans
parent 8d959b7c63
commit 10ed3decb0
12 changed files with 26 additions and 106 deletions
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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:
+7 -43
View File
@@ -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:
+1 -1
View File
@@ -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, "")
}
+3 -3
View File
@@ -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})
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
}
}
+1 -1
View File
@@ -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{
+4 -4
View File
@@ -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
-44
View File
@@ -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 {
+2 -2
View File
@@ -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})