Skip to content
This repository was archived by the owner on Dec 14, 2023. It is now read-only.

Commit bba4eb2

Browse files
committed
Roll gofrontend to 225a208260a6
This updates us to Go 1.3 release and adds initial precise GC support.
1 parent cadae0d commit bba4eb2

File tree

3 files changed

+702
-578
lines changed

3 files changed

+702
-578
lines changed

irgen/typemap.go

Lines changed: 158 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type typeDescInfo struct {
4343
global llvm.Value
4444
commonTypePtr llvm.Value
4545
mapDescPtr llvm.Value
46+
gc, gcPtr llvm.Value
4647

4748
interfaceMethodTables typeutil.Map
4849
}
@@ -69,6 +70,9 @@ type TypeMap struct {
6970

7071
hashFnEmptyInterface, hashFnInterface, hashFnFloat, hashFnComplex, hashFnString, hashFnIdentity, hashFnError llvm.Value
7172
equalFnEmptyInterface, equalFnInterface, equalFnFloat, equalFnComplex, equalFnString, equalFnIdentity, equalFnError llvm.Value
73+
74+
zeroType llvm.Type
75+
zeroValue llvm.Value
7276
}
7377

7478
func NewLLVMTypeMap(ctx llvm.Context, target llvm.TargetData) *llvmTypeMap {
@@ -130,6 +134,14 @@ func NewTypeMap(pkg *ssa.Package, llvmtm *llvmTypeMap, module llvm.Module, r *ru
130134
tm.equalFnIdentity = llvm.AddFunction(tm.module, "__go_type_equal_identity", tm.equalFnType)
131135
tm.equalFnError = llvm.AddFunction(tm.module, "__go_type_equal_error", tm.equalFnType)
132136

137+
// The body of this type is set in emitTypeDescInitializers once we have scanned
138+
// every type, as it needs to be as large and well aligned as the
139+
// largest/most aligned type.
140+
tm.zeroType = tm.ctx.StructCreateNamed("zero")
141+
tm.zeroValue = llvm.AddGlobal(tm.module, tm.zeroType, "go$zerovalue")
142+
tm.zeroValue.SetLinkage(llvm.CommonLinkage)
143+
tm.zeroValue.SetInitializer(llvm.ConstNull(tm.zeroType))
144+
133145
tm.commonTypeType = tm.ctx.StructCreateNamed("commonType")
134146
commonTypeTypePtr := llvm.PointerType(tm.commonTypeType, 0)
135147

@@ -159,9 +171,11 @@ func NewTypeMap(pkg *ssa.Package, llvmtm *llvmTypeMap, module llvm.Module, r *ru
159171
tm.ctx.Int32Type(), // hash
160172
llvm.PointerType(tm.hashFnType, 0), // hashfn
161173
llvm.PointerType(tm.equalFnType, 0), // equalfn
174+
voidPtrType, // gc
162175
stringPtrType, // string
163176
llvm.PointerType(tm.uncommonTypeType, 0), // uncommonType
164177
commonTypeTypePtr, // ptrToThis
178+
llvm.PointerType(tm.zeroType, 0), // zero
165179
}, false)
166180

167181
tm.typeSliceType = tm.makeNamedSliceType("typeSlice", commonTypeTypePtr)
@@ -1037,6 +1051,9 @@ func (ts byTypeName) Less(i, j int) bool {
10371051
}
10381052

10391053
func (tm *TypeMap) emitTypeDescInitializers() {
1054+
var maxSize, maxAlign int64
1055+
maxAlign = 1
1056+
10401057
for changed := true; changed; {
10411058
changed = false
10421059

@@ -1047,6 +1064,7 @@ func (tm *TypeMap) emitTypeDescInitializers() {
10471064
if tdi.global.Initializer().C == nil {
10481065
linkage, emit := tm.getTypeDescLinkage(key)
10491066
tdi.global.SetLinkage(linkage)
1067+
tdi.gc.SetLinkage(linkage)
10501068
if emit {
10511069
changed = true
10521070
ts = append(ts, typeAndInfo{key, key.String(), tdi})
@@ -1057,10 +1075,127 @@ func (tm *TypeMap) emitTypeDescInitializers() {
10571075
if changed {
10581076
sort.Sort(byTypeName(ts))
10591077
for _, t := range ts {
1060-
t.tdi.global.SetInitializer(tm.makeTypeDescInitializer(t.typ))
1078+
tm.emitTypeDescInitializer(t.typ, t.tdi)
1079+
if size := tm.Sizeof(t.typ); size > maxSize {
1080+
maxSize = size
1081+
}
1082+
if align := tm.Alignof(t.typ); align > maxAlign {
1083+
maxAlign = align
1084+
}
10611085
}
10621086
}
10631087
}
1088+
1089+
tm.zeroType.StructSetBody([]llvm.Type{llvm.ArrayType(tm.ctx.Int8Type(), int(maxSize))}, false)
1090+
tm.zeroValue.SetAlignment(int(maxAlign))
1091+
}
1092+
1093+
const (
1094+
// From libgo/runtime/mgc0.h
1095+
gcOpcodeEND = iota
1096+
gcOpcodePTR
1097+
gcOpcodeAPTR
1098+
gcOpcodeARRAY_START
1099+
gcOpcodeARRAY_NEXT
1100+
gcOpcodeCALL
1101+
gcOpcodeCHAN_PTR
1102+
gcOpcodeSTRING
1103+
gcOpcodeEFACE
1104+
gcOpcodeIFACE
1105+
gcOpcodeSLICE
1106+
gcOpcodeREGION
1107+
1108+
gcStackCapacity = 8
1109+
)
1110+
1111+
func (tm *TypeMap) makeGcInst(val int64) llvm.Value {
1112+
c := llvm.ConstInt(tm.inttype, uint64(val), false)
1113+
return llvm.ConstIntToPtr(c, llvm.PointerType(tm.ctx.Int8Type(), 0))
1114+
}
1115+
1116+
func (tm *TypeMap) appendGcInsts(insts []llvm.Value, t types.Type, offset, stackSize int64) []llvm.Value {
1117+
switch u := t.Underlying().(type) {
1118+
case *types.Basic:
1119+
switch u.Kind() {
1120+
case types.String:
1121+
insts = append(insts, tm.makeGcInst(gcOpcodeSTRING), tm.makeGcInst(offset))
1122+
case types.UnsafePointer:
1123+
insts = append(insts, tm.makeGcInst(gcOpcodeAPTR), tm.makeGcInst(offset))
1124+
}
1125+
case *types.Pointer:
1126+
insts = append(insts, tm.makeGcInst(gcOpcodePTR), tm.makeGcInst(offset),
1127+
tm.getGcPointer(u.Elem()))
1128+
case *types.Signature, *types.Map:
1129+
insts = append(insts, tm.makeGcInst(gcOpcodeAPTR), tm.makeGcInst(offset))
1130+
case *types.Array:
1131+
if u.Len() == 0 {
1132+
return insts
1133+
} else if stackSize >= gcStackCapacity {
1134+
insts = append(insts, tm.makeGcInst(gcOpcodeREGION), tm.makeGcInst(offset),
1135+
tm.makeGcInst(tm.Sizeof(t)), tm.getGcPointer(t))
1136+
} else {
1137+
insts = append(insts, tm.makeGcInst(gcOpcodeARRAY_START), tm.makeGcInst(offset),
1138+
tm.makeGcInst(u.Len()), tm.makeGcInst(tm.Sizeof(u.Elem())))
1139+
insts = tm.appendGcInsts(insts, u.Elem(), 0, stackSize+1)
1140+
insts = append(insts, tm.makeGcInst(gcOpcodeARRAY_NEXT))
1141+
}
1142+
case *types.Slice:
1143+
if tm.Sizeof(u.Elem()) == 0 {
1144+
insts = append(insts, tm.makeGcInst(gcOpcodeAPTR), tm.makeGcInst(offset))
1145+
} else {
1146+
insts = append(insts, tm.makeGcInst(gcOpcodeSLICE), tm.makeGcInst(offset),
1147+
tm.getGcPointer(u.Elem()))
1148+
}
1149+
case *types.Chan:
1150+
insts = append(insts, tm.makeGcInst(gcOpcodeCHAN_PTR), tm.makeGcInst(offset),
1151+
tm.ToRuntime(t))
1152+
case *types.Struct:
1153+
fields := make([]*types.Var, u.NumFields())
1154+
for i := range fields {
1155+
fields[i] = u.Field(i)
1156+
}
1157+
offsets := tm.Offsetsof(fields)
1158+
1159+
for i, field := range fields {
1160+
insts = tm.appendGcInsts(insts, field.Type(), offset+offsets[i], stackSize)
1161+
}
1162+
case *types.Interface:
1163+
if u.NumMethods() == 0 {
1164+
insts = append(insts, tm.makeGcInst(gcOpcodeEFACE), tm.makeGcInst(offset))
1165+
} else {
1166+
insts = append(insts, tm.makeGcInst(gcOpcodeIFACE), tm.makeGcInst(offset))
1167+
}
1168+
default:
1169+
panic(fmt.Sprintf("unhandled type: %#v", t))
1170+
}
1171+
1172+
return insts
1173+
}
1174+
1175+
func (tm *TypeMap) emitTypeDescInitializer(t types.Type, tdi *typeDescInfo) {
1176+
// initialize type descriptor
1177+
tdi.global.SetInitializer(tm.makeTypeDescInitializer(t))
1178+
1179+
// initialize GC program
1180+
insts := []llvm.Value{tm.makeGcInst(tm.Sizeof(t))}
1181+
insts = tm.appendGcInsts(insts, t, 0, 0)
1182+
insts = append(insts, tm.makeGcInst(gcOpcodeEND))
1183+
1184+
i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
1185+
instArray := llvm.ConstArray(i8ptr, insts)
1186+
1187+
newGc := llvm.AddGlobal(tm.module, instArray.Type(), "")
1188+
newGc.SetGlobalConstant(true)
1189+
newGc.SetInitializer(instArray)
1190+
gcName := tdi.gc.Name()
1191+
tdi.gc.SetName("")
1192+
newGc.SetName(gcName)
1193+
newGc.SetLinkage(tdi.gc.Linkage())
1194+
1195+
tdi.gc.ReplaceAllUsesWith(llvm.ConstBitCast(newGc, tdi.gc.Type()))
1196+
tdi.gc.EraseFromParentAsGlobal()
1197+
tdi.gc = llvm.Value{nil}
1198+
tdi.gcPtr = llvm.ConstBitCast(newGc, i8ptr)
10641199
}
10651200

10661201
func (tm *TypeMap) makeTypeDescInitializer(t types.Type) llvm.Value {
@@ -1347,6 +1482,10 @@ func (tm *TypeMap) getTypeDescInfo(t types.Type) *typeDescInfo {
13471482
global.SetGlobalConstant(true)
13481483
ptr := llvm.ConstBitCast(global, llvm.PointerType(tm.commonTypeType, 0))
13491484

1485+
gc := llvm.AddGlobal(tm.module, llvm.PointerType(llvm.Int8Type(), 0), b.String()+"$gc")
1486+
gc.SetGlobalConstant(true)
1487+
gcPtr := llvm.ConstBitCast(gc, llvm.PointerType(tm.ctx.Int8Type(), 0))
1488+
13501489
var mapDescPtr llvm.Value
13511490
if m, ok := t.Underlying().(*types.Map); ok {
13521491
var mapb bytes.Buffer
@@ -1358,7 +1497,13 @@ func (tm *TypeMap) getTypeDescInfo(t types.Type) *typeDescInfo {
13581497
mapDescPtr.SetInitializer(tm.makeMapDesc(ptr, m))
13591498
}
13601499

1361-
tdi := &typeDescInfo{global: global, commonTypePtr: ptr, mapDescPtr: mapDescPtr}
1500+
tdi := &typeDescInfo{
1501+
global: global,
1502+
commonTypePtr: ptr,
1503+
mapDescPtr: mapDescPtr,
1504+
gc: gc,
1505+
gcPtr: gcPtr,
1506+
}
13621507
tm.types.Set(t, tdi)
13631508
return tdi
13641509
}
@@ -1371,6 +1516,10 @@ func (tm *TypeMap) getMapDescriptorPointer(t types.Type) llvm.Value {
13711516
return tm.getTypeDescInfo(t).mapDescPtr
13721517
}
13731518

1519+
func (tm *TypeMap) getGcPointer(t types.Type) llvm.Value {
1520+
return tm.getTypeDescInfo(t).gcPtr
1521+
}
1522+
13741523
func (tm *TypeMap) getItabPointer(srctype types.Type, targettype *types.Interface) llvm.Value {
13751524
if targettype.NumMethods() == 0 {
13761525
return tm.ToRuntime(srctype)
@@ -1543,7 +1692,7 @@ func runtimeTypeKind(t types.Type) (k uint8) {
15431692
}
15441693

15451694
func (tm *TypeMap) makeCommonType(t types.Type) llvm.Value {
1546-
var vals [10]llvm.Value
1695+
var vals [12]llvm.Value
15471696
vals[0] = llvm.ConstInt(tm.ctx.Int8Type(), uint64(runtimeTypeKind(t)), false)
15481697
vals[1] = llvm.ConstInt(tm.ctx.Int8Type(), uint64(tm.Alignof(t)), false)
15491698
vals[2] = vals[1]
@@ -1552,15 +1701,17 @@ func (tm *TypeMap) makeCommonType(t types.Type) llvm.Value {
15521701
hash, equal := tm.getAlgorithmFunctions(t)
15531702
vals[5] = hash
15541703
vals[6] = equal
1704+
vals[7] = tm.getGcPointer(t)
15551705
var b bytes.Buffer
15561706
tm.writeType(t, &b)
1557-
vals[7] = tm.globalStringPtr(b.String())
1558-
vals[8] = tm.makeUncommonTypePtr(t)
1707+
vals[8] = tm.globalStringPtr(b.String())
1708+
vals[9] = tm.makeUncommonTypePtr(t)
15591709
if _, ok := t.(*types.Named); ok {
1560-
vals[9] = tm.getTypeDescriptorPointer(types.NewPointer(t))
1710+
vals[10] = tm.getTypeDescriptorPointer(types.NewPointer(t))
15611711
} else {
1562-
vals[9] = llvm.ConstPointerNull(llvm.PointerType(tm.commonTypeType, 0))
1712+
vals[10] = llvm.ConstPointerNull(llvm.PointerType(tm.commonTypeType, 0))
15631713
}
1714+
vals[11] = tm.zeroValue
15641715

15651716
return llvm.ConstNamedStruct(tm.commonTypeType, vals[:])
15661717
}

0 commit comments

Comments
 (0)