aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compiler/calls.go2
-rw-r--r--compiler/channel.go2
-rw-r--r--compiler/compiler.go50
-rw-r--r--compiler/defer.go2
-rw-r--r--compiler/gc.go6
-rw-r--r--compiler/interface.go8
-rw-r--r--compiler/optimizer.go2
-rw-r--r--compiler/symbol.go2
-rw-r--r--compiler/wordpack.go2
-rw-r--r--interp/frame.go8
-rw-r--r--interp/utils.go44
-rw-r--r--interp/values.go4
12 files changed, 26 insertions, 106 deletions
diff --git a/compiler/calls.go b/compiler/calls.go
index 406122f53..3cb4c12c7 100644
--- a/compiler/calls.go
+++ b/compiler/calls.go
@@ -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
diff --git a/compiler/channel.go b/compiler/channel.go
index e04d58969..55fb6920d 100644
--- a/compiler/channel.go
+++ b/compiler/channel.go
@@ -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:
diff --git a/compiler/compiler.go b/compiler/compiler.go
index f64b67901..050e7107a 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -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:
diff --git a/compiler/defer.go b/compiler/defer.go
index d929ea576..c408b6e78 100644
--- a/compiler/defer.go
+++ b/compiler/defer.go
@@ -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, "")
}
diff --git a/compiler/gc.go b/compiler/gc.go
index d9679efca..87fed6b16 100644
--- a/compiler/gc.go
+++ b/compiler/gc.go
@@ -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})
diff --git a/compiler/interface.go b/compiler/interface.go
index 4d2995ba6..672f7a17b 100644
--- a/compiler/interface.go
+++ b/compiler/interface.go
@@ -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
diff --git a/compiler/optimizer.go b/compiler/optimizer.go
index d06ce489c..00c2c56fb 100644
--- a/compiler/optimizer.go
+++ b/compiler/optimizer.go
@@ -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)
diff --git a/compiler/symbol.go b/compiler/symbol.go
index 0df2ab6e4..4b8fb08bf 100644
--- a/compiler/symbol.go
+++ b/compiler/symbol.go
@@ -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)
}
}
diff --git a/compiler/wordpack.go b/compiler/wordpack.go
index e553cb9c4..513970a1e 100644
--- a/compiler/wordpack.go
+++ b/compiler/wordpack.go
@@ -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{
diff --git a/interp/frame.go b/interp/frame.go
index 81432ef34..47c59f57e 100644
--- a/interp/frame.go
+++ b/interp/frame.go
@@ -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
diff --git a/interp/utils.go b/interp/utils.go
index 7910ea8a7..3131e819b 100644
--- a/interp/utils.go
+++ b/interp/utils.go
@@ -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 {
diff --git a/interp/values.go b/interp/values.go
index 4a1b9739e..ae62f3ffe 100644
--- a/interp/values.go
+++ b/interp/values.go
@@ -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})