all: remove pointer ElementType calls
This is needed for opaque pointers, which are enabled by default in LLVM 15.
Этот коммит содержится в:
родитель
229746b71e
коммит
62df1d7490
17 изменённых файлов: 82 добавлений и 93 удалений
|
@ -411,7 +411,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||||
return errors.New("global not found: " + globalName)
|
return errors.New("global not found: " + globalName)
|
||||||
}
|
}
|
||||||
name := global.Name()
|
name := global.Name()
|
||||||
newGlobal := llvm.AddGlobal(mod, global.Type().ElementType(), name+".tmp")
|
newGlobal := llvm.AddGlobal(mod, global.GlobalValueType(), name+".tmp")
|
||||||
global.ReplaceAllUsesWith(newGlobal)
|
global.ReplaceAllUsesWith(newGlobal)
|
||||||
global.EraseFromParentAsGlobal()
|
global.EraseFromParentAsGlobal()
|
||||||
newGlobal.SetName(name)
|
newGlobal.SetName(name)
|
||||||
|
@ -1127,7 +1127,7 @@ func setGlobalValues(mod llvm.Module, globals map[string]map[string]string) erro
|
||||||
|
|
||||||
// A strin is a {ptr, len} pair. We need these types to build the
|
// A strin is a {ptr, len} pair. We need these types to build the
|
||||||
// initializer.
|
// initializer.
|
||||||
initializerType := global.Type().ElementType()
|
initializerType := global.GlobalValueType()
|
||||||
if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName() == "" {
|
if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName() == "" {
|
||||||
return fmt.Errorf("%s: not a string", globalName)
|
return fmt.Errorf("%s: not a string", globalName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen i
|
||||||
|
|
||||||
// createUnsafeSliceCheck inserts a runtime check used for unsafe.Slice. This
|
// createUnsafeSliceCheck inserts a runtime check used for unsafe.Slice. This
|
||||||
// function must panic if the ptr/len parameters are invalid.
|
// function must panic if the ptr/len parameters are invalid.
|
||||||
func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, lenType *types.Basic) {
|
func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, elementType llvm.Type, lenType *types.Basic) {
|
||||||
// From the documentation of unsafe.Slice:
|
// From the documentation of unsafe.Slice:
|
||||||
// > At run time, if len is negative, or if ptr is nil and len is not
|
// > At run time, if len is negative, or if ptr is nil and len is not
|
||||||
// > zero, a run-time panic occurs.
|
// > zero, a run-time panic occurs.
|
||||||
|
@ -105,7 +105,7 @@ func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, lenType *types.Bas
|
||||||
|
|
||||||
// Determine the maximum slice size, and therefore the maximum value of the
|
// Determine the maximum slice size, and therefore the maximum value of the
|
||||||
// len parameter.
|
// len parameter.
|
||||||
maxSize := b.maxSliceSize(ptr.Type().ElementType())
|
maxSize := b.maxSliceSize(elementType)
|
||||||
maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false)
|
maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false)
|
||||||
|
|
||||||
// Do the check. By using unsigned greater than for the length check, signed
|
// Do the check. By using unsigned greater than for the length check, signed
|
||||||
|
|
|
@ -20,7 +20,7 @@ const maxFieldsPerParam = 3
|
||||||
type paramInfo struct {
|
type paramInfo struct {
|
||||||
llvmType llvm.Type
|
llvmType llvm.Type
|
||||||
name string // name, possibly with suffixes for e.g. struct fields
|
name string // name, possibly with suffixes for e.g. struct fields
|
||||||
flags paramFlags
|
elemSize uint64 // size of pointer element type, or 0 if this isn't a pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// paramFlags identifies parameter attributes for flags. Most importantly, it
|
// paramFlags identifies parameter attributes for flags. Most importantly, it
|
||||||
|
@ -96,13 +96,7 @@ func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType
|
||||||
// failed to expand this parameter: too many fields
|
// failed to expand this parameter: too many fields
|
||||||
}
|
}
|
||||||
// TODO: split small arrays
|
// TODO: split small arrays
|
||||||
return []paramInfo{
|
return []paramInfo{c.getParamInfo(t, name, goType)}
|
||||||
{
|
|
||||||
llvmType: t,
|
|
||||||
name: name,
|
|
||||||
flags: getTypeFlags(goType),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// expandFormalParamOffsets returns a list of offsets from the start of an
|
// expandFormalParamOffsets returns a list of offsets from the start of an
|
||||||
|
@ -152,7 +146,6 @@ func (b *builder) expandFormalParam(v llvm.Value) []llvm.Value {
|
||||||
// Try to flatten a struct type to a list of types. Returns a 1-element slice
|
// Try to flatten a struct type to a list of types. Returns a 1-element slice
|
||||||
// with the passed in type if this is not possible.
|
// with the passed in type if this is not possible.
|
||||||
func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo {
|
func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo {
|
||||||
typeFlags := getTypeFlags(goType)
|
|
||||||
switch t.TypeKind() {
|
switch t.TypeKind() {
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
var paramInfos []paramInfo
|
var paramInfos []paramInfo
|
||||||
|
@ -183,40 +176,37 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i))
|
subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i))
|
||||||
for i := range subInfos {
|
|
||||||
subInfos[i].flags |= typeFlags
|
|
||||||
}
|
|
||||||
paramInfos = append(paramInfos, subInfos...)
|
paramInfos = append(paramInfos, subInfos...)
|
||||||
}
|
}
|
||||||
return paramInfos
|
return paramInfos
|
||||||
default:
|
default:
|
||||||
return []paramInfo{
|
return []paramInfo{c.getParamInfo(t, name, goType)}
|
||||||
{
|
|
||||||
llvmType: t,
|
|
||||||
name: name,
|
|
||||||
flags: typeFlags,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getTypeFlags returns the type flags for a given type. It will not recurse
|
// getParamInfo collects information about a parameter. For example, if this
|
||||||
// into sub-types (such as in structs).
|
// parameter is pointer-like, it will also store the element type for the
|
||||||
func getTypeFlags(t types.Type) paramFlags {
|
// dereferenceable_or_null attribute.
|
||||||
if t == nil {
|
func (c *compilerContext) getParamInfo(t llvm.Type, name string, goType types.Type) paramInfo {
|
||||||
return 0
|
info := paramInfo{
|
||||||
|
llvmType: t,
|
||||||
|
name: name,
|
||||||
}
|
}
|
||||||
switch t.Underlying().(type) {
|
if goType != nil {
|
||||||
case *types.Pointer:
|
switch underlying := goType.Underlying().(type) {
|
||||||
// Pointers in Go must either point to an object or be nil.
|
case *types.Pointer:
|
||||||
return paramIsDeferenceableOrNull
|
// Pointers in Go must either point to an object or be nil.
|
||||||
case *types.Chan, *types.Map:
|
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMType(underlying.Elem()))
|
||||||
// Channels and maps are implemented as pointers pointing to some
|
case *types.Chan:
|
||||||
// object, and follow the same rules as *types.Pointer.
|
// Channels are implemented simply as a *runtime.channel.
|
||||||
return paramIsDeferenceableOrNull
|
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("channel"))
|
||||||
default:
|
case *types.Map:
|
||||||
return 0
|
// Maps are similar to channels: they are implemented as a
|
||||||
|
// *runtime.hashmap.
|
||||||
|
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("hashmap"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractSubfield extracts a field from a struct, or returns null if this is
|
// extractSubfield extracts a field from a struct, or returns null if this is
|
||||||
|
|
|
@ -862,7 +862,7 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
||||||
if files, ok := c.embedGlobals[member.Name()]; ok {
|
if files, ok := c.embedGlobals[member.Name()]; ok {
|
||||||
c.createEmbedGlobal(member, global, files)
|
c.createEmbedGlobal(member, global, files)
|
||||||
} else if !info.extern {
|
} else if !info.extern {
|
||||||
global.SetInitializer(llvm.ConstNull(global.Type().ElementType()))
|
global.SetInitializer(llvm.ConstNull(global.GlobalValueType()))
|
||||||
global.SetVisibility(llvm.HiddenVisibility)
|
global.SetVisibility(llvm.HiddenVisibility)
|
||||||
if info.section != "" {
|
if info.section != "" {
|
||||||
global.SetSection(info.section)
|
global.SetSection(info.section)
|
||||||
|
@ -1405,7 +1405,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
|
||||||
b.CreateRet(b.getValue(instr.Results[0]))
|
b.CreateRet(b.getValue(instr.Results[0]))
|
||||||
} else {
|
} else {
|
||||||
// Multiple return values. Put them all in a struct.
|
// Multiple return values. Put them all in a struct.
|
||||||
retVal := llvm.ConstNull(b.llvmFn.Type().ElementType().ReturnType())
|
retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType())
|
||||||
for i, result := range instr.Results {
|
for i, result := range instr.Results {
|
||||||
val := b.getValue(result)
|
val := b.getValue(result)
|
||||||
retVal = b.CreateInsertValue(retVal, val, i, "")
|
retVal = b.CreateInsertValue(retVal, val, i, "")
|
||||||
|
@ -1444,7 +1444,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
||||||
elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf")
|
elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf")
|
||||||
elemsPtr := b.CreateBitCast(elemsBuf, b.i8ptrType, "append.srcPtr")
|
elemsPtr := b.CreateBitCast(elemsBuf, b.i8ptrType, "append.srcPtr")
|
||||||
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
|
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
|
||||||
elemType := srcBuf.Type().ElementType()
|
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
||||||
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
||||||
result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new")
|
result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new")
|
||||||
newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
|
newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
|
||||||
|
@ -1497,7 +1497,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
||||||
srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
|
srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
|
||||||
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
|
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
|
||||||
srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
|
srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
|
||||||
elemType := dstBuf.Type().ElementType()
|
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
||||||
dstBuf = b.CreateBitCast(dstBuf, b.i8ptrType, "copy.dstPtr")
|
dstBuf = b.CreateBitCast(dstBuf, b.i8ptrType, "copy.dstPtr")
|
||||||
srcBuf = b.CreateBitCast(srcBuf, b.i8ptrType, "copy.srcPtr")
|
srcBuf = b.CreateBitCast(srcBuf, b.i8ptrType, "copy.srcPtr")
|
||||||
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
||||||
|
@ -1637,7 +1637,8 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
||||||
b.uintptrType,
|
b.uintptrType,
|
||||||
b.uintptrType,
|
b.uintptrType,
|
||||||
}, false))
|
}, false))
|
||||||
b.createUnsafeSliceCheck(ptr, len, argTypes[1].Underlying().(*types.Basic))
|
elementType := b.getLLVMType(argTypes[0].Underlying().(*types.Pointer).Elem())
|
||||||
|
b.createUnsafeSliceCheck(ptr, len, elementType, argTypes[1].Underlying().(*types.Basic))
|
||||||
if len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
|
if len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
|
||||||
// Too small, zero-extend len.
|
// Too small, zero-extend len.
|
||||||
len = b.CreateZExt(len, b.uintptrType, "")
|
len = b.CreateZExt(len, b.uintptrType, "")
|
||||||
|
@ -1712,7 +1713,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||||
// Eventually we might be able to eliminate this special case
|
// Eventually we might be able to eliminate this special case
|
||||||
// entirely. For details, see:
|
// entirely. For details, see:
|
||||||
// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
|
// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
|
||||||
calleeType = llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false)
|
calleeType = llvm.FunctionType(callee.GlobalValueType().ReturnType(), nil, false)
|
||||||
callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType, b.funcPtrAddrSpace))
|
callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType, b.funcPtrAddrSpace))
|
||||||
}
|
}
|
||||||
case *ssa.MakeClosure:
|
case *ssa.MakeClosure:
|
||||||
|
@ -3095,7 +3096,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
|
||||||
}
|
}
|
||||||
case token.MUL: // *x, dereference pointer
|
case token.MUL: // *x, dereference pointer
|
||||||
valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())
|
valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())
|
||||||
if b.targetData.TypeAllocSize(x.Type().ElementType()) == 0 {
|
if b.targetData.TypeAllocSize(valueType) == 0 {
|
||||||
// zero-length data
|
// zero-length data
|
||||||
return llvm.ConstNull(valueType), nil
|
return llvm.ConstNull(valueType), nil
|
||||||
} else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
|
} else if strings.HasSuffix(unop.X.String(), "$funcaddr") {
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type {
|
||||||
return c.ctx.StructType([]llvm.Type{c.i8ptrType, c.rawVoidFuncType}, false)
|
return c.ctx.StructType([]llvm.Type{c.i8ptrType, c.rawVoidFuncType}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRawFuncType returns a LLVM function pointer type for a given signature.
|
// getRawFuncType returns a LLVM function type for a given signature.
|
||||||
func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type {
|
func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type {
|
||||||
// Get the return type.
|
// Get the return type.
|
||||||
var returnType llvm.Type
|
var returnType llvm.Type
|
||||||
|
|
|
@ -86,7 +86,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||||
if _, ok := typ.Underlying().(*types.Pointer); !ok {
|
if _, ok := typ.Underlying().(*types.Pointer); !ok {
|
||||||
ptrTo = c.getTypeCode(types.NewPointer(typ))
|
ptrTo = c.getTypeCode(types.NewPointer(typ))
|
||||||
}
|
}
|
||||||
globalValue := llvm.ConstNull(global.Type().ElementType())
|
globalValue := llvm.ConstNull(global.GlobalValueType())
|
||||||
if !references.IsNil() {
|
if !references.IsNil() {
|
||||||
globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "")
|
globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "")
|
||||||
}
|
}
|
||||||
|
@ -533,7 +533,7 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFnType
|
||||||
|
|
||||||
receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]
|
receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]
|
||||||
params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)
|
params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)
|
||||||
if llvmFn.Type().ElementType().ReturnType().TypeKind() == llvm.VoidTypeKind {
|
if llvmFnType.ReturnType().TypeKind() == llvm.VoidTypeKind {
|
||||||
b.CreateCall(llvmFnType, llvmFn, params, "")
|
b.CreateCall(llvmFnType, llvmFn, params, "")
|
||||||
b.CreateRetVoid()
|
b.CreateRetVoid()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -70,10 +70,7 @@ func (c *checker) checkType(t llvm.Type, checked map[llvm.Type]struct{}, special
|
||||||
return fmt.Errorf("failed to verify element type of array type %s: %s", t.String(), err.Error())
|
return fmt.Errorf("failed to verify element type of array type %s: %s", t.String(), err.Error())
|
||||||
}
|
}
|
||||||
case llvm.PointerTypeKind:
|
case llvm.PointerTypeKind:
|
||||||
// check underlying type
|
// Pointers can't be checked in an opaque pointer world.
|
||||||
if err := c.checkType(t.ElementType(), checked, specials); err != nil {
|
|
||||||
return fmt.Errorf("failed to verify underlying type of pointer type %s: %s", t.String(), err.Error())
|
|
||||||
}
|
|
||||||
case llvm.VectorTypeKind:
|
case llvm.VectorTypeKind:
|
||||||
// check element type
|
// check element type
|
||||||
if err := c.checkType(t.ElementType(), checked, specials); err != nil {
|
if err := c.checkType(t.ElementType(), checked, specials); err != nil {
|
||||||
|
|
|
@ -83,7 +83,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
||||||
// Add an extra parameter as the function context. This context is used in
|
// Add an extra parameter as the function context. This context is used in
|
||||||
// closures and bound methods, but should be optimized away when not used.
|
// closures and bound methods, but should be optimized away when not used.
|
||||||
if !info.exported {
|
if !info.exported {
|
||||||
paramInfos = append(paramInfos, paramInfo{llvmType: c.i8ptrType, name: "context", flags: 0})
|
paramInfos = append(paramInfos, paramInfo{llvmType: c.i8ptrType, name: "context", elemSize: 0})
|
||||||
}
|
}
|
||||||
|
|
||||||
var paramTypes []llvm.Type
|
var paramTypes []llvm.Type
|
||||||
|
@ -112,17 +112,8 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
||||||
|
|
||||||
dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null")
|
dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null")
|
||||||
for i, info := range paramInfos {
|
for i, info := range paramInfos {
|
||||||
if info.flags¶mIsDeferenceableOrNull == 0 {
|
if info.elemSize != 0 {
|
||||||
continue
|
dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, info.elemSize)
|
||||||
}
|
|
||||||
if info.llvmType.TypeKind() == llvm.PointerTypeKind {
|
|
||||||
el := info.llvmType.ElementType()
|
|
||||||
size := c.targetData.TypeAllocSize(el)
|
|
||||||
if size == 0 {
|
|
||||||
// dereferenceable_or_null(0) appears to be illegal in LLVM.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, size)
|
|
||||||
llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull)
|
llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,7 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
||||||
case llvm.Alloca:
|
case llvm.Alloca:
|
||||||
// Alloca allocates stack space for local variables.
|
// Alloca allocates stack space for local variables.
|
||||||
numElements := r.getValue(inst.llvmInst.Operand(0)).(literalValue).value.(uint32)
|
numElements := r.getValue(inst.llvmInst.Operand(0)).(literalValue).value.(uint32)
|
||||||
elementSize := r.targetData.TypeAllocSize(inst.llvmInst.Type().ElementType())
|
elementSize := r.targetData.TypeAllocSize(inst.llvmInst.AllocatedType())
|
||||||
inst.operands = []value{
|
inst.operands = []value{
|
||||||
literalValue{elementSize * uint64(numElements)},
|
literalValue{elementSize * uint64(numElements)},
|
||||||
}
|
}
|
||||||
|
@ -218,17 +218,17 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
||||||
inst.name = llvmInst.Name()
|
inst.name = llvmInst.Name()
|
||||||
ptr := llvmInst.Operand(0)
|
ptr := llvmInst.Operand(0)
|
||||||
n := llvmInst.OperandsCount()
|
n := llvmInst.OperandsCount()
|
||||||
elementType := ptr.Type().ElementType()
|
elementType := llvmInst.GEPSourceElementType()
|
||||||
// gep: [source ptr, dest value size, pairs of indices...]
|
// gep: [source ptr, dest value size, pairs of indices...]
|
||||||
inst.operands = []value{
|
inst.operands = []value{
|
||||||
r.getValue(ptr),
|
r.getValue(ptr),
|
||||||
literalValue{r.targetData.TypeAllocSize(llvmInst.Type().ElementType())},
|
|
||||||
r.getValue(llvmInst.Operand(1)),
|
r.getValue(llvmInst.Operand(1)),
|
||||||
literalValue{r.targetData.TypeAllocSize(elementType)},
|
literalValue{r.targetData.TypeAllocSize(elementType)},
|
||||||
}
|
}
|
||||||
for i := 2; i < n; i++ {
|
for i := 2; i < n; i++ {
|
||||||
operand := r.getValue(llvmInst.Operand(i))
|
operand := r.getValue(llvmInst.Operand(i))
|
||||||
if elementType.TypeKind() == llvm.StructTypeKind {
|
switch elementType.TypeKind() {
|
||||||
|
case llvm.StructTypeKind:
|
||||||
index := operand.(literalValue).value.(uint32)
|
index := operand.(literalValue).value.(uint32)
|
||||||
elementOffset := r.targetData.ElementOffset(elementType, int(index))
|
elementOffset := r.targetData.ElementOffset(elementType, int(index))
|
||||||
// Encode operands in a special way. The elementOffset
|
// Encode operands in a special way. The elementOffset
|
||||||
|
@ -242,12 +242,15 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
||||||
// runtime.
|
// runtime.
|
||||||
inst.operands = append(inst.operands, literalValue{elementOffset}, literalValue{^uint64(index)})
|
inst.operands = append(inst.operands, literalValue{elementOffset}, literalValue{^uint64(index)})
|
||||||
elementType = elementType.StructElementTypes()[index]
|
elementType = elementType.StructElementTypes()[index]
|
||||||
} else {
|
case llvm.ArrayTypeKind:
|
||||||
elementType = elementType.ElementType()
|
elementType = elementType.ElementType()
|
||||||
elementSize := r.targetData.TypeAllocSize(elementType)
|
elementSize := r.targetData.TypeAllocSize(elementType)
|
||||||
elementSizeOperand := literalValue{elementSize}
|
elementSizeOperand := literalValue{elementSize}
|
||||||
// Add operand * elementSizeOperand bytes to the pointer.
|
// Add operand * elementSizeOperand bytes to the pointer.
|
||||||
inst.operands = append(inst.operands, operand, elementSizeOperand)
|
inst.operands = append(inst.operands, operand, elementSizeOperand)
|
||||||
|
default:
|
||||||
|
// This should be unreachable.
|
||||||
|
panic("unknown type: " + elementType.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt:
|
case llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt:
|
||||||
|
@ -267,10 +270,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
offset += r.targetData.ElementOffset(indexingType, int(index))
|
offset += r.targetData.ElementOffset(indexingType, int(index))
|
||||||
indexingType = indexingType.StructElementTypes()[index]
|
indexingType = indexingType.StructElementTypes()[index]
|
||||||
default: // ArrayTypeKind
|
case llvm.ArrayTypeKind:
|
||||||
indexingType = indexingType.ElementType()
|
indexingType = indexingType.ElementType()
|
||||||
elementSize := r.targetData.TypeAllocSize(indexingType)
|
elementSize := r.targetData.TypeAllocSize(indexingType)
|
||||||
offset += elementSize * uint64(index)
|
offset += elementSize * uint64(index)
|
||||||
|
default:
|
||||||
|
panic("unknown type kind") // unreachable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size := r.targetData.TypeAllocSize(inst.llvmInst.Type())
|
size := r.targetData.TypeAllocSize(inst.llvmInst.Type())
|
||||||
|
@ -290,10 +295,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
offset += r.targetData.ElementOffset(indexingType, int(index))
|
offset += r.targetData.ElementOffset(indexingType, int(index))
|
||||||
indexingType = indexingType.StructElementTypes()[index]
|
indexingType = indexingType.StructElementTypes()[index]
|
||||||
default: // ArrayTypeKind
|
case llvm.ArrayTypeKind:
|
||||||
indexingType = indexingType.ElementType()
|
indexingType = indexingType.ElementType()
|
||||||
elementSize := r.targetData.TypeAllocSize(indexingType)
|
elementSize := r.targetData.TypeAllocSize(indexingType)
|
||||||
offset += elementSize * uint64(index)
|
offset += elementSize * uint64(index)
|
||||||
|
default:
|
||||||
|
panic("unknown type kind") // unreachable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// insertvalue [agg, elt, byteOffset]
|
// insertvalue [agg, elt, byteOffset]
|
||||||
|
|
|
@ -156,7 +156,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
|
||||||
if obj.constant {
|
if obj.constant {
|
||||||
continue // constant buffers can't have been modified
|
continue // constant buffers can't have been modified
|
||||||
}
|
}
|
||||||
initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.Type().ElementType(), &mem)
|
initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(), &mem)
|
||||||
if err == errInvalidPtrToIntSize {
|
if err == errInvalidPtrToIntSize {
|
||||||
// This can happen when a previous interp run did not have the
|
// This can happen when a previous interp run did not have the
|
||||||
// correct LLVM type for a global and made something up. In that
|
// correct LLVM type for a global and made something up. In that
|
||||||
|
@ -190,7 +190,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() {
|
if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {
|
||||||
panic("initializer type mismatch")
|
panic("initializer type mismatch")
|
||||||
}
|
}
|
||||||
obj.llvmGlobal.SetInitializer(initializer)
|
obj.llvmGlobal.SetInitializer(initializer)
|
||||||
|
@ -213,7 +213,7 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
|
||||||
r.pkgName = initName[:len(initName)-len(".init")]
|
r.pkgName = initName[:len(initName)-len(".init")]
|
||||||
|
|
||||||
// Create new function with the interp result.
|
// Create new function with the interp result.
|
||||||
newFn := llvm.AddFunction(mod, fn.Name()+".tmp", fn.Type().ElementType())
|
newFn := llvm.AddFunction(mod, fn.Name()+".tmp", fn.GlobalValueType())
|
||||||
newFn.SetLinkage(fn.Linkage())
|
newFn.SetLinkage(fn.Linkage())
|
||||||
newFn.SetVisibility(fn.Visibility())
|
newFn.SetVisibility(fn.Visibility())
|
||||||
entry := mod.Context().AddBasicBlock(newFn, "entry")
|
entry := mod.Context().AddBasicBlock(newFn, "entry")
|
||||||
|
@ -263,11 +263,11 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
|
||||||
if obj.constant {
|
if obj.constant {
|
||||||
continue // constant, so can't have been modified
|
continue // constant, so can't have been modified
|
||||||
}
|
}
|
||||||
initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.Type().ElementType(), &mem)
|
initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(), &mem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() {
|
if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {
|
||||||
panic("initializer type mismatch")
|
panic("initializer type mismatch")
|
||||||
}
|
}
|
||||||
obj.llvmGlobal.SetInitializer(initializer)
|
obj.llvmGlobal.SetInitializer(initializer)
|
||||||
|
|
|
@ -655,7 +655,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||||
// GetElementPtr does pointer arithmetic, changing the offset of the
|
// GetElementPtr does pointer arithmetic, changing the offset of the
|
||||||
// pointer into the underlying object.
|
// pointer into the underlying object.
|
||||||
var offset uint64
|
var offset uint64
|
||||||
for i := 2; i < len(operands); i += 2 {
|
for i := 1; i < len(operands); i += 2 {
|
||||||
index := operands[i].Uint()
|
index := operands[i].Uint()
|
||||||
elementSize := operands[i+1].Uint()
|
elementSize := operands[i+1].Uint()
|
||||||
if int64(elementSize) < 0 {
|
if int64(elementSize) < 0 {
|
||||||
|
|
|
@ -808,14 +808,17 @@ func (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
elementType := field.Type().ElementType()
|
if !field.IsAGlobalVariable().IsNil() {
|
||||||
if elementType.TypeKind() == llvm.StructTypeKind {
|
elementType := field.GlobalValueType()
|
||||||
// There are some special pointer types that should be used as a
|
if elementType.TypeKind() == llvm.StructTypeKind {
|
||||||
// ptrtoint, so that they can be used in certain optimizations.
|
// There are some special pointer types that should be used
|
||||||
name := elementType.StructName()
|
// as a ptrtoint, so that they can be used in certain
|
||||||
if name == "runtime.typecodeID" || name == "runtime.funcValueWithSignature" {
|
// optimizations.
|
||||||
uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
|
name := elementType.StructName()
|
||||||
field = llvm.ConstPtrToInt(field, uintptrType)
|
if name == "runtime.typecodeID" || name == "runtime.funcValueWithSignature" {
|
||||||
|
uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
|
||||||
|
field = llvm.ConstPtrToInt(field, uintptrType)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
structFields = append(structFields, field)
|
structFields = append(structFields, field)
|
||||||
|
@ -998,7 +1001,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
||||||
ptr := llvmValue.Operand(0)
|
ptr := llvmValue.Operand(0)
|
||||||
index := llvmValue.Operand(1)
|
index := llvmValue.Operand(1)
|
||||||
numOperands := llvmValue.OperandsCount()
|
numOperands := llvmValue.OperandsCount()
|
||||||
elementType := ptr.Type().ElementType()
|
elementType := llvmValue.GEPSourceElementType()
|
||||||
totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
|
totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
|
||||||
for i := 2; i < numOperands; i++ {
|
for i := 2; i < numOperands; i++ {
|
||||||
indexValue := llvmValue.Operand(i)
|
indexValue := llvmValue.Operand(i)
|
||||||
|
@ -1173,7 +1176,7 @@ func (r *runner) getValue(llvmValue llvm.Value) value {
|
||||||
r.globals[llvmValue] = index
|
r.globals[llvmValue] = index
|
||||||
r.objects = append(r.objects, obj)
|
r.objects = append(r.objects, obj)
|
||||||
if !llvmValue.IsAGlobalVariable().IsNil() {
|
if !llvmValue.IsAGlobalVariable().IsNil() {
|
||||||
obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.Type().ElementType()))
|
obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.GlobalValueType()))
|
||||||
if initializer := llvmValue.Initializer(); !initializer.IsNil() {
|
if initializer := llvmValue.Initializer(); !initializer.IsNil() {
|
||||||
obj.buffer = r.getValue(initializer)
|
obj.buffer = r.getValue(initializer)
|
||||||
obj.constant = llvmValue.IsGlobalConstant()
|
obj.constant = llvmValue.IsGlobalConstant()
|
||||||
|
|
|
@ -124,7 +124,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, logger func(tok
|
||||||
alloca.SetAlignment(alignment)
|
alloca.SetAlignment(alignment)
|
||||||
|
|
||||||
// Zero the allocation inside the block where the value was originally allocated.
|
// Zero the allocation inside the block where the value was originally allocated.
|
||||||
zero := llvm.ConstNull(alloca.Type().ElementType())
|
zero := llvm.ConstNull(alloca.AllocatedType())
|
||||||
builder.SetInsertPointBefore(bitcast)
|
builder.SetInsertPointBefore(bitcast)
|
||||||
store := builder.CreateStore(zero, alloca)
|
store := builder.CreateStore(zero, alloca)
|
||||||
store.SetAlignment(alignment)
|
store.SetAlignment(alignment)
|
||||||
|
|
|
@ -18,7 +18,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
|
||||||
stackChainStart := mod.NamedGlobal("runtime.stackChainStart")
|
stackChainStart := mod.NamedGlobal("runtime.stackChainStart")
|
||||||
if !stackChainStart.IsNil() {
|
if !stackChainStart.IsNil() {
|
||||||
stackChainStart.SetLinkage(llvm.InternalLinkage)
|
stackChainStart.SetLinkage(llvm.InternalLinkage)
|
||||||
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType()))
|
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.GlobalValueType()))
|
||||||
stackChainStart.SetGlobalConstant(true)
|
stackChainStart.SetGlobalConstant(true)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -96,7 +96,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
stackChainStart.SetLinkage(llvm.InternalLinkage)
|
stackChainStart.SetLinkage(llvm.InternalLinkage)
|
||||||
stackChainStartType := stackChainStart.Type().ElementType()
|
stackChainStartType := stackChainStart.GlobalValueType()
|
||||||
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
|
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
|
||||||
|
|
||||||
// Iterate until runtime.trackPointer has no uses left.
|
// Iterate until runtime.trackPointer has no uses left.
|
||||||
|
|
|
@ -423,7 +423,7 @@ func (p *lowerInterfacesPass) defineInterfaceImplementsFunc(fn llvm.Value, itf *
|
||||||
func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) {
|
func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) {
|
||||||
context := fn.LastParam()
|
context := fn.LastParam()
|
||||||
actualType := llvm.PrevParam(context)
|
actualType := llvm.PrevParam(context)
|
||||||
returnType := fn.Type().ElementType().ReturnType()
|
returnType := fn.GlobalValueType().ReturnType()
|
||||||
context.SetName("context")
|
context.SetName("context")
|
||||||
actualType.SetName("actualType")
|
actualType.SetName("actualType")
|
||||||
fn.SetLinkage(llvm.InternalLinkage)
|
fn.SetLinkage(llvm.InternalLinkage)
|
||||||
|
|
|
@ -66,7 +66,7 @@ func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
|
||||||
// function used for creating reflection sidetables, for example.
|
// function used for creating reflection sidetables, for example.
|
||||||
func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value {
|
func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value {
|
||||||
oldGlobal := mod.NamedGlobal(name)
|
oldGlobal := mod.NamedGlobal(name)
|
||||||
globalType, global := makeGlobalArray(mod, buf, name+".tmp", oldGlobal.Type().ElementType())
|
globalType, global := makeGlobalArray(mod, buf, name+".tmp", oldGlobal.GlobalValueType())
|
||||||
gep := llvm.ConstGEP(globalType, global, []llvm.Value{
|
gep := llvm.ConstGEP(globalType, global, []llvm.Value{
|
||||||
llvm.ConstInt(mod.Context().Int32Type(), 0, false),
|
llvm.ConstInt(mod.Context().Int32Type(), 0, false),
|
||||||
llvm.ConstInt(mod.Context().Int32Type(), 0, false),
|
llvm.ConstInt(mod.Context().Int32Type(), 0, false),
|
||||||
|
|
|
@ -50,7 +50,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error {
|
||||||
paramTypes := []llvm.Type{}
|
paramTypes := []llvm.Type{}
|
||||||
|
|
||||||
// Check return type for 64-bit integer.
|
// Check return type for 64-bit integer.
|
||||||
fnType := fn.Type().ElementType()
|
fnType := fn.GlobalValueType()
|
||||||
returnType := fnType.ReturnType()
|
returnType := fnType.ReturnType()
|
||||||
if returnType == int64Type {
|
if returnType == int64Type {
|
||||||
hasInt64 = true
|
hasInt64 = true
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче