all: replace llvm.Const* calls with builder.Create* calls
A number of llvm.Const* functions (in particular extractvalue and insertvalue) were removed in LLVM 15, so we have to use a builder instead. This builder will create the same constant values, it simply uses a different API.
Этот коммит содержится в:
родитель
f57cffce2d
коммит
09ec846c9f
13 изменённых файлов: 86 добавлений и 65 удалений
|
@ -145,7 +145,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
|
|||
}
|
||||
// Make the maxBufSize actually the maximum allowed value (in number of
|
||||
// elements in the channel buffer).
|
||||
maxBufSize = llvm.ConstUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false))
|
||||
maxBufSize = b.CreateUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false), "")
|
||||
|
||||
// Make sure maxBufSize has the same type as bufSize.
|
||||
if maxBufSize.Type() != bufSize.Type() {
|
||||
|
|
|
@ -63,6 +63,7 @@ type compilerContext struct {
|
|||
DumpSSA bool
|
||||
mod llvm.Module
|
||||
ctx llvm.Context
|
||||
builder llvm.Builder // only used for constant operations
|
||||
dibuilder *llvm.DIBuilder
|
||||
cu llvm.Metadata
|
||||
difiles map[string]llvm.Metadata
|
||||
|
@ -98,6 +99,7 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
|
|||
}
|
||||
|
||||
c.ctx = llvm.NewContext()
|
||||
c.builder = c.ctx.NewBuilder()
|
||||
c.mod = c.ctx.NewModule(moduleName)
|
||||
c.mod.SetTarget(config.Triple)
|
||||
c.mod.SetDataLayout(c.targetData.String())
|
||||
|
@ -126,6 +128,12 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
|
|||
return c
|
||||
}
|
||||
|
||||
// Dispose everything related to the context, _except_ for the IR module (and
|
||||
// the associated context).
|
||||
func (c *compilerContext) dispose() {
|
||||
c.builder.Dispose()
|
||||
}
|
||||
|
||||
// builder contains all information relevant to build a single function.
|
||||
type builder struct {
|
||||
*compilerContext
|
||||
|
@ -256,6 +264,7 @@ func Sizes(machine llvm.TargetMachine) types.Sizes {
|
|||
// CompilePackage compiles a single package to a LLVM module.
|
||||
func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {
|
||||
c := newCompilerContext(moduleName, machine, config, dumpSSA)
|
||||
defer c.dispose()
|
||||
c.packageDir = pkg.OriginalDir()
|
||||
c.embedGlobals = pkg.EmbedGlobals
|
||||
c.pkg = pkg.Pkg
|
||||
|
@ -972,10 +981,10 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Valu
|
|||
for _, file := range allFiles {
|
||||
fileStruct := llvm.ConstNull(embedFileStructType)
|
||||
name := c.createConst(ssa.NewConst(constant.MakeString(file.Name), types.Typ[types.String]))
|
||||
fileStruct = llvm.ConstInsertValue(fileStruct, name, []uint32{0}) // "name" field
|
||||
fileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, "") // "name" field
|
||||
if file.Hash != "" {
|
||||
data := c.getEmbedFileString(file)
|
||||
fileStruct = llvm.ConstInsertValue(fileStruct, data, []uint32{1}) // "data" field
|
||||
fileStruct = c.builder.CreateInsertValue(fileStruct, data, 1, "") // "data" field
|
||||
}
|
||||
fileStructs = append(fileStructs, fileStruct)
|
||||
}
|
||||
|
@ -1006,7 +1015,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Valu
|
|||
// Define the embed.FS struct. It has only one field: the files (as a
|
||||
// *[]embed.file).
|
||||
globalInitializer := llvm.ConstNull(c.getLLVMType(member.Type().(*types.Pointer).Elem()))
|
||||
globalInitializer = llvm.ConstInsertValue(globalInitializer, sliceGlobal, []uint32{0})
|
||||
globalInitializer = c.builder.CreateInsertValue(globalInitializer, sliceGlobal, 0, "")
|
||||
global.SetInitializer(globalInitializer)
|
||||
global.SetVisibility(llvm.HiddenVisibility)
|
||||
global.SetAlignment(c.targetData.ABITypeAlignment(globalInitializer.Type()))
|
||||
|
@ -2757,15 +2766,15 @@ func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value {
|
|||
r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32]))
|
||||
i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32]))
|
||||
cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
|
||||
cplx = llvm.ConstInsertValue(cplx, r, []uint32{0})
|
||||
cplx = llvm.ConstInsertValue(cplx, i, []uint32{1})
|
||||
cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
|
||||
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||
return cplx
|
||||
} else if typ.Kind() == types.Complex128 {
|
||||
r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]))
|
||||
i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64]))
|
||||
cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
|
||||
cplx = llvm.ConstInsertValue(cplx, r, []uint32{0})
|
||||
cplx = llvm.ConstInsertValue(cplx, i, []uint32{1})
|
||||
cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
|
||||
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||
return cplx
|
||||
} else {
|
||||
panic("unknown constant of basic type: " + expr.String())
|
||||
|
|
|
@ -88,20 +88,20 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||
}
|
||||
globalValue := llvm.ConstNull(global.Type().ElementType())
|
||||
if !references.IsNil() {
|
||||
globalValue = llvm.ConstInsertValue(globalValue, references, []uint32{0})
|
||||
globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "")
|
||||
}
|
||||
if length != 0 {
|
||||
lengthValue := llvm.ConstInt(c.uintptrType, uint64(length), false)
|
||||
globalValue = llvm.ConstInsertValue(globalValue, lengthValue, []uint32{1})
|
||||
globalValue = c.builder.CreateInsertValue(globalValue, lengthValue, 1, "")
|
||||
}
|
||||
if !methodSet.IsNil() {
|
||||
globalValue = llvm.ConstInsertValue(globalValue, methodSet, []uint32{2})
|
||||
globalValue = c.builder.CreateInsertValue(globalValue, methodSet, 2, "")
|
||||
}
|
||||
if !ptrTo.IsNil() {
|
||||
globalValue = llvm.ConstInsertValue(globalValue, ptrTo, []uint32{3})
|
||||
globalValue = c.builder.CreateInsertValue(globalValue, ptrTo, 3, "")
|
||||
}
|
||||
if !typeAssert.IsNil() {
|
||||
globalValue = llvm.ConstInsertValue(globalValue, typeAssert, []uint32{4})
|
||||
globalValue = c.builder.CreateInsertValue(globalValue, typeAssert, 4, "")
|
||||
}
|
||||
global.SetInitializer(globalValue)
|
||||
global.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||
|
@ -121,7 +121,7 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
|
|||
structGlobalValue := llvm.ConstNull(structGlobalType)
|
||||
for i := 0; i < typ.NumFields(); i++ {
|
||||
fieldGlobalValue := llvm.ConstNull(runtimeStructField)
|
||||
fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, c.getTypeCode(typ.Field(i).Type()), []uint32{0})
|
||||
fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, c.getTypeCode(typ.Field(i).Type()), 0, "")
|
||||
fieldNameType, fieldName := c.makeGlobalArray([]byte(typ.Field(i).Name()), "reflect/types.structFieldName", c.ctx.Int8Type())
|
||||
fieldName.SetLinkage(llvm.PrivateLinkage)
|
||||
fieldName.SetUnnamedAddr(true)
|
||||
|
@ -129,7 +129,7 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
|
|||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
})
|
||||
fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldName, []uint32{1})
|
||||
fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldName, 1, "")
|
||||
if typ.Tag(i) != "" {
|
||||
fieldTagType, fieldTag := c.makeGlobalArray([]byte(typ.Tag(i)), "reflect/types.structFieldTag", c.ctx.Int8Type())
|
||||
fieldTag.SetLinkage(llvm.PrivateLinkage)
|
||||
|
@ -138,13 +138,13 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
|
|||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
})
|
||||
fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldTag, []uint32{2})
|
||||
fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldTag, 2, "")
|
||||
}
|
||||
if typ.Field(i).Embedded() {
|
||||
fieldEmbedded := llvm.ConstInt(c.ctx.Int1Type(), 1, false)
|
||||
fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldEmbedded, []uint32{3})
|
||||
fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldEmbedded, 3, "")
|
||||
}
|
||||
structGlobalValue = llvm.ConstInsertValue(structGlobalValue, fieldGlobalValue, []uint32{uint32(i)})
|
||||
structGlobalValue = c.builder.CreateInsertValue(structGlobalValue, fieldGlobalValue, i, "")
|
||||
}
|
||||
structGlobal.SetInitializer(structGlobalValue)
|
||||
structGlobal.SetUnnamedAddr(true)
|
||||
|
|
|
@ -49,9 +49,11 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||
global.SetGlobalConstant(true)
|
||||
global.SetUnnamedAddr(true)
|
||||
initializer := llvm.ConstNull(globalLLVMType)
|
||||
initializer = llvm.ConstInsertValue(initializer, funcContext, []uint32{0})
|
||||
initializer = llvm.ConstInsertValue(initializer, funcPtr, []uint32{1})
|
||||
initializer = llvm.ConstInsertValue(initializer, llvm.ConstInt(b.intType, uint64(id.Int64()), true), []uint32{2, 0})
|
||||
initializer = b.CreateInsertValue(initializer, funcContext, 0, "")
|
||||
initializer = b.CreateInsertValue(initializer, funcPtr, 1, "")
|
||||
initializer = b.CreateInsertValue(initializer, llvm.ConstNamedStruct(globalLLVMType.StructElementTypes()[2], []llvm.Value{
|
||||
llvm.ConstInt(b.intType, uint64(id.Int64()), true),
|
||||
}), 2, "")
|
||||
global.SetInitializer(initializer)
|
||||
|
||||
// Add debug info to the interrupt global.
|
||||
|
|
|
@ -70,7 +70,7 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType l
|
|||
value := llvm.Undef(globalType)
|
||||
for i := 0; i < len(buf); i++ {
|
||||
ch := uint64(buf[i])
|
||||
value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false), []uint32{uint32(i)})
|
||||
value = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i, "")
|
||||
}
|
||||
global.SetInitializer(value)
|
||||
return globalType, global
|
||||
|
|
|
@ -408,7 +408,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||
// Elem() is only valid for certain type classes.
|
||||
switch class {
|
||||
case "chan", "pointer", "slice", "array":
|
||||
elementType := llvm.ConstExtractValue(typecodeID.Initializer(), []uint32{0})
|
||||
elementType := r.builder.CreateExtractValue(typecodeID.Initializer(), 0, "")
|
||||
uintptrType := r.mod.Context().IntType(int(mem.r.pointerSize) * 8)
|
||||
locals[inst.localIndex] = r.getValue(llvm.ConstPtrToInt(elementType, uintptrType))
|
||||
default:
|
||||
|
@ -461,8 +461,8 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||
// easier checking in the next step.
|
||||
concreteTypeMethods := map[string]struct{}{}
|
||||
for i := 0; i < methodSet.Type().ArrayLength(); i++ {
|
||||
methodInfo := llvm.ConstExtractValue(methodSet, []uint32{uint32(i)})
|
||||
name := llvm.ConstExtractValue(methodInfo, []uint32{0}).Name()
|
||||
methodInfo := r.builder.CreateExtractValue(methodSet, i, "")
|
||||
name := r.builder.CreateExtractValue(methodInfo, 0, "").Name()
|
||||
concreteTypeMethods[name] = struct{}{}
|
||||
}
|
||||
|
||||
|
@ -496,7 +496,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||
typecodeID := typecodeIDBitCast.Operand(0).Initializer()
|
||||
|
||||
// Load the method set, which is part of the typecodeID object.
|
||||
methodSet := llvm.ConstExtractValue(typecodeID, []uint32{2}).Operand(0).Initializer()
|
||||
methodSet := r.builder.CreateExtractValue(typecodeID, 2, "").Operand(0).Initializer()
|
||||
|
||||
// We don't need to load the interface method set.
|
||||
|
||||
|
@ -511,9 +511,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||
numMethods := methodSet.Type().ArrayLength()
|
||||
var method llvm.Value
|
||||
for i := 0; i < numMethods; i++ {
|
||||
methodSignature := llvm.ConstExtractValue(methodSet, []uint32{uint32(i), 0})
|
||||
methodSignatureAgg := r.builder.CreateExtractValue(methodSet, i, "")
|
||||
methodSignature := r.builder.CreateExtractValue(methodSignatureAgg, 0, "")
|
||||
if methodSignature == signature {
|
||||
method = llvm.ConstExtractValue(methodSet, []uint32{uint32(i), 1}).Operand(0)
|
||||
method = r.builder.CreateExtractValue(methodSignatureAgg, 1, "").Operand(0)
|
||||
}
|
||||
}
|
||||
if method.IsNil() {
|
||||
|
|
|
@ -215,7 +215,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {
|
|||
case llvm.StructTypeKind:
|
||||
numElements := llvmType.StructElementTypesCount()
|
||||
for i := 0; i < numElements; i++ {
|
||||
element := llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)})
|
||||
element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
|
||||
err := mv.markExternal(element, mark)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -224,7 +224,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {
|
|||
case llvm.ArrayTypeKind:
|
||||
numElements := llvmType.ArrayLength()
|
||||
for i := 0; i < numElements; i++ {
|
||||
element := llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)})
|
||||
element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
|
||||
err := mv.markExternal(element, mark)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1074,7 +1074,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
|||
field := rawValue{
|
||||
buf: v.buf[offset:],
|
||||
}
|
||||
field.set(llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}), r)
|
||||
field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r)
|
||||
}
|
||||
case llvm.ArrayTypeKind:
|
||||
numElements := llvmType.ArrayLength()
|
||||
|
@ -1085,7 +1085,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
|
|||
field := rawValue{
|
||||
buf: v.buf[offset:],
|
||||
}
|
||||
field.set(llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}), r)
|
||||
field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r)
|
||||
}
|
||||
case llvm.DoubleTypeKind:
|
||||
f, _ := llvmValue.DoubleValue()
|
||||
|
|
|
@ -218,7 +218,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
|
|||
initialStackObject := llvm.ConstNull(stackObjectType)
|
||||
numSlots := (targetData.TypeAllocSize(stackObjectType) - uint64(targetData.PointerSize())*2) / uint64(targetData.ABITypeAlignment(uintptrType))
|
||||
numSlotsValue := llvm.ConstInt(uintptrType, numSlots, false)
|
||||
initialStackObject = llvm.ConstInsertValue(initialStackObject, numSlotsValue, []uint32{1})
|
||||
initialStackObject = builder.CreateInsertValue(initialStackObject, numSlotsValue, 1, "")
|
||||
builder.CreateStore(initialStackObject, stackObject)
|
||||
|
||||
// Update stack start.
|
||||
|
|
|
@ -154,7 +154,7 @@ func (p *lowerInterfacesPass) run() error {
|
|||
if initializer.IsNil() {
|
||||
continue
|
||||
}
|
||||
methodSet := llvm.ConstExtractValue(initializer, []uint32{2})
|
||||
methodSet := p.builder.CreateExtractValue(initializer, 2, "")
|
||||
p.addTypeMethods(t, methodSet)
|
||||
}
|
||||
}
|
||||
|
@ -288,9 +288,9 @@ func (p *lowerInterfacesPass) run() error {
|
|||
zeroUintptr := llvm.ConstNull(p.uintptrType)
|
||||
for _, t := range p.types {
|
||||
initializer := t.typecode.Initializer()
|
||||
methodSet := llvm.ConstExtractValue(initializer, []uint32{2})
|
||||
initializer = llvm.ConstInsertValue(initializer, llvm.ConstNull(methodSet.Type()), []uint32{2})
|
||||
initializer = llvm.ConstInsertValue(initializer, zeroUintptr, []uint32{4})
|
||||
methodSet := p.builder.CreateExtractValue(initializer, 2, "")
|
||||
initializer = p.builder.CreateInsertValue(initializer, llvm.ConstNull(methodSet.Type()), 2, "")
|
||||
initializer = p.builder.CreateInsertValue(initializer, zeroUintptr, 4, "")
|
||||
t.typecode.SetInitializer(initializer)
|
||||
}
|
||||
|
||||
|
@ -311,10 +311,10 @@ func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet llvm.Value)
|
|||
t.methodSet = methodSet
|
||||
set := methodSet.Initializer() // get value from global
|
||||
for i := 0; i < set.Type().ArrayLength(); i++ {
|
||||
methodData := llvm.ConstExtractValue(set, []uint32{uint32(i)})
|
||||
signatureGlobal := llvm.ConstExtractValue(methodData, []uint32{0})
|
||||
methodData := p.builder.CreateExtractValue(set, i, "")
|
||||
signatureGlobal := p.builder.CreateExtractValue(methodData, 0, "")
|
||||
signatureName := signatureGlobal.Name()
|
||||
function := llvm.ConstExtractValue(methodData, []uint32{1}).Operand(0)
|
||||
function := p.builder.CreateExtractValue(methodData, 1, "").Operand(0)
|
||||
signature := p.getSignature(signatureName)
|
||||
method := &methodInfo{
|
||||
function: function,
|
||||
|
|
|
@ -44,7 +44,8 @@ func LowerInterrupts(mod llvm.Module) []error {
|
|||
|
||||
// Get the interrupt number from the initializer
|
||||
initializer := global.Initializer()
|
||||
num := llvm.ConstExtractValue(initializer, []uint32{2, 0}).SExtValue()
|
||||
interrupt := builder.CreateExtractValue(initializer, 2, "")
|
||||
num := builder.CreateExtractValue(interrupt, 0, "").SExtValue()
|
||||
pkg := packageFromInterruptHandle(global)
|
||||
|
||||
handles, exists := handleMap[num]
|
||||
|
@ -89,8 +90,8 @@ func LowerInterrupts(mod llvm.Module) []error {
|
|||
builder.SetInsertPointBefore(call)
|
||||
for _, handler := range handlers {
|
||||
initializer := handler.Initializer()
|
||||
context := llvm.ConstExtractValue(initializer, []uint32{0})
|
||||
funcPtr := llvm.ConstExtractValue(initializer, []uint32{1}).Operand(0)
|
||||
context := builder.CreateExtractValue(initializer, 0, "")
|
||||
funcPtr := builder.CreateExtractValue(initializer, 1, "").Operand(0)
|
||||
builder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{
|
||||
num,
|
||||
context,
|
||||
|
|
|
@ -36,25 +36,27 @@ func hasUses(value llvm.Value) bool {
|
|||
// linkage/constant/etc properties yourself.
|
||||
func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType llvm.Type) (llvm.Type, llvm.Value) {
|
||||
buf := reflect.ValueOf(bufItf)
|
||||
globalType := llvm.ArrayType(elementType, buf.Len())
|
||||
global := llvm.AddGlobal(mod, globalType, name)
|
||||
value := llvm.Undef(globalType)
|
||||
var values []llvm.Value
|
||||
for i := 0; i < buf.Len(); i++ {
|
||||
ch := buf.Index(i).Uint()
|
||||
value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false), []uint32{uint32(i)})
|
||||
values = append(values, llvm.ConstInt(elementType, ch, false))
|
||||
}
|
||||
value := llvm.ConstArray(elementType, values)
|
||||
global := llvm.AddGlobal(mod, value.Type(), name)
|
||||
global.SetInitializer(value)
|
||||
return globalType, global
|
||||
return value.Type(), global
|
||||
}
|
||||
|
||||
// getGlobalBytes returns the slice contained in the array of the provided
|
||||
// global. It can recover the bytes originally created using makeGlobalArray, if
|
||||
// makeGlobalArray was given a byte slice.
|
||||
func getGlobalBytes(global llvm.Value) []byte {
|
||||
//
|
||||
// The builder parameter is only used for constant operations.
|
||||
func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
|
||||
value := global.Initializer()
|
||||
buf := make([]byte, value.Type().ArrayLength())
|
||||
for i := range buf {
|
||||
buf[i] = byte(llvm.ConstExtractValue(value, []uint32{uint32(i)}).ZExtValue())
|
||||
buf[i] = byte(builder.CreateExtractValue(value, i, "").ZExtValue())
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
|
|
@ -76,6 +76,10 @@ var nonBasicTypes = map[string]int64{
|
|||
// typeCodeAssignmentState keeps some global state around for type code
|
||||
// assignments, used to assign one unique type code to each Go type.
|
||||
type typeCodeAssignmentState struct {
|
||||
// Builder used purely for constant operations (because LLVM 15 removed many
|
||||
// llvm.Const* functions).
|
||||
builder llvm.Builder
|
||||
|
||||
// An integer that's incremented each time it's used to give unique IDs to
|
||||
// type codes that are not yet fully supported otherwise by the reflect
|
||||
// package (or are simply unused in the compiled program).
|
||||
|
@ -165,6 +169,7 @@ func LowerReflect(mod llvm.Module) {
|
|||
defer targetData.Dispose()
|
||||
uintptrType := mod.Context().IntType(targetData.PointerSize() * 8)
|
||||
state := typeCodeAssignmentState{
|
||||
builder: mod.Context().NewBuilder(),
|
||||
fallbackIndex: 1,
|
||||
uintptrLen: targetData.PointerSize() * 8,
|
||||
namedBasicTypes: make(map[string]int),
|
||||
|
@ -177,6 +182,7 @@ func LowerReflect(mod llvm.Module) {
|
|||
needsStructNamesSidetable: len(getUses(mod.NamedGlobal("reflect.structNamesSidetable"))) != 0,
|
||||
needsArrayTypesSidetable: len(getUses(mod.NamedGlobal("reflect.arrayTypesSidetable"))) != 0,
|
||||
}
|
||||
defer state.builder.Dispose()
|
||||
for _, t := range types {
|
||||
num := state.getTypeCodeNum(t.typecode)
|
||||
if num.BitLen() > state.uintptrLen || !num.IsUint64() {
|
||||
|
@ -238,7 +244,7 @@ func LowerReflect(mod llvm.Module) {
|
|||
// It also cleans up the IR for testing.
|
||||
for _, typ := range types {
|
||||
initializer := typ.typecode.Initializer()
|
||||
references := llvm.ConstExtractValue(initializer, []uint32{0})
|
||||
references := state.builder.CreateExtractValue(initializer, 0, "")
|
||||
typ.typecode.SetInitializer(llvm.ConstNull(initializer.Type()))
|
||||
if strings.HasPrefix(typ.name, "reflect/types.type:struct:") {
|
||||
// Structs have a 'references' field that is not a typecode but
|
||||
|
@ -260,7 +266,7 @@ func (state *typeCodeAssignmentState) getTypeCodeNum(typecode llvm.Value) *big.I
|
|||
name := ""
|
||||
if class == "named" {
|
||||
name = value
|
||||
typecode = llvm.ConstExtractValue(typecode.Initializer(), []uint32{0})
|
||||
typecode = state.builder.CreateExtractValue(typecode.Initializer(), 0, "")
|
||||
class, value = getClassAndValueFromTypeCode(typecode)
|
||||
}
|
||||
if class == "basic" {
|
||||
|
@ -344,7 +350,7 @@ func (state *typeCodeAssignmentState) getNonBasicTypeCode(class string, typecode
|
|||
switch class {
|
||||
case "chan", "pointer", "slice":
|
||||
// Prefix-style type kinds. The upper bits contain the element type.
|
||||
sub := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0})
|
||||
sub := state.builder.CreateExtractValue(typecode.Initializer(), 0, "")
|
||||
return state.getTypeCodeNum(sub)
|
||||
case "array":
|
||||
// An array is basically a pair of (typecode, length) stored in a
|
||||
|
@ -416,7 +422,7 @@ func (state *typeCodeAssignmentState) getArrayTypeNum(typecode llvm.Value) int {
|
|||
return num
|
||||
}
|
||||
|
||||
elemTypeCode := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0})
|
||||
elemTypeCode := state.builder.CreateExtractValue(typecode.Initializer(), 0, "")
|
||||
elemTypeNum := state.getTypeCodeNum(elemTypeCode)
|
||||
if elemTypeNum.BitLen() > state.uintptrLen || !elemTypeNum.IsUint64() {
|
||||
// TODO: make this a regular error
|
||||
|
@ -424,7 +430,7 @@ func (state *typeCodeAssignmentState) getArrayTypeNum(typecode llvm.Value) int {
|
|||
}
|
||||
|
||||
// The array side table is a sequence of {element type, array length}.
|
||||
arrayLength := llvm.ConstExtractValue(typecode.Initializer(), []uint32{1}).ZExtValue()
|
||||
arrayLength := state.builder.CreateExtractValue(typecode.Initializer(), 1, "").ZExtValue()
|
||||
buf := makeVarint(elemTypeNum.Uint64())
|
||||
buf = append(buf, makeVarint(arrayLength)...)
|
||||
|
||||
|
@ -454,7 +460,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int
|
|||
|
||||
// Get the fields this struct type contains.
|
||||
// The struct number will be the start index of
|
||||
structTypeGlobal := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0}).Operand(0).Initializer()
|
||||
structTypeGlobal := state.builder.CreateExtractValue(typecode.Initializer(), 0, "").Operand(0).Initializer()
|
||||
numFields := structTypeGlobal.Type().ArrayLength()
|
||||
|
||||
// The first data that is stored in the struct sidetable is the number of
|
||||
|
@ -471,28 +477,28 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int
|
|||
// the sidetable bigger.
|
||||
for i := 0; i < numFields; i++ {
|
||||
// Collect some information about this field.
|
||||
field := llvm.ConstExtractValue(structTypeGlobal, []uint32{uint32(i)})
|
||||
field := state.builder.CreateExtractValue(structTypeGlobal, i, "")
|
||||
|
||||
nameGlobal := llvm.ConstExtractValue(field, []uint32{1})
|
||||
nameGlobal := state.builder.CreateExtractValue(field, 1, "")
|
||||
if nameGlobal == llvm.ConstPointerNull(nameGlobal.Type()) {
|
||||
panic("compiler: no name for this struct field")
|
||||
}
|
||||
fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0))
|
||||
fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0), state.builder)
|
||||
fieldNameNumber := state.getStructNameNumber(fieldNameBytes)
|
||||
|
||||
// See whether this struct field has an associated tag, and if so,
|
||||
// store that tag in the tags sidetable.
|
||||
tagGlobal := llvm.ConstExtractValue(field, []uint32{2})
|
||||
tagGlobal := state.builder.CreateExtractValue(field, 2, "")
|
||||
hasTag := false
|
||||
tagNumber := 0
|
||||
if tagGlobal != llvm.ConstPointerNull(tagGlobal.Type()) {
|
||||
hasTag = true
|
||||
tagBytes := getGlobalBytes(tagGlobal.Operand(0))
|
||||
tagBytes := getGlobalBytes(tagGlobal.Operand(0), state.builder)
|
||||
tagNumber = state.getStructNameNumber(tagBytes)
|
||||
}
|
||||
|
||||
// The 'embedded' or 'anonymous' flag for this field.
|
||||
embedded := llvm.ConstExtractValue(field, []uint32{3}).ZExtValue() != 0
|
||||
embedded := state.builder.CreateExtractValue(field, 3, "").ZExtValue() != 0
|
||||
|
||||
// The first byte in the struct types sidetable is a flags byte with
|
||||
// two bits in it.
|
||||
|
@ -510,7 +516,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int
|
|||
|
||||
// Get the type number and add it to the buffer.
|
||||
// All fields have a type, so include it directly here.
|
||||
typeNum := state.getTypeCodeNum(llvm.ConstExtractValue(field, []uint32{0}))
|
||||
typeNum := state.getTypeCodeNum(state.builder.CreateExtractValue(field, 0, ""))
|
||||
if typeNum.BitLen() > state.uintptrLen || !typeNum.IsUint64() {
|
||||
// TODO: make this a regular error
|
||||
panic("struct field has a type code that is too big")
|
||||
|
|
|
@ -149,7 +149,7 @@ func OptimizeReflectImplements(mod llvm.Module) {
|
|||
interfaceType := interfaceTypeBitCast.Operand(0)
|
||||
if strings.HasPrefix(interfaceType.Name(), "reflect/types.type:named:") {
|
||||
// Get the underlying type.
|
||||
interfaceType = llvm.ConstExtractValue(interfaceType.Initializer(), []uint32{0})
|
||||
interfaceType = builder.CreateExtractValue(interfaceType.Initializer(), 0, "")
|
||||
}
|
||||
if !strings.HasPrefix(interfaceType.Name(), "reflect/types.type:interface:") {
|
||||
// This is an error. The Type passed to Implements should be of
|
||||
|
@ -161,7 +161,7 @@ func OptimizeReflectImplements(mod llvm.Module) {
|
|||
// Interface is unknown at compile time. This can't be optimized.
|
||||
continue
|
||||
}
|
||||
typeAssertFunction := llvm.ConstExtractValue(interfaceType.Initializer(), []uint32{4}).Operand(0)
|
||||
typeAssertFunction := builder.CreateExtractValue(interfaceType.Initializer(), 4, "").Operand(0)
|
||||
|
||||
// Replace Implements call with the type assert call.
|
||||
builder.SetInsertPointBefore(call)
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче