Skip to content
Permalink
Browse files
Store instruction data in interface, instead of directly
  • Loading branch information
Storyyeller committed Sep 25, 2016
1 parent 55e8e65 commit 8f35ae0954652595575972ef6d60ab742f9297a2
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 63 deletions.
@@ -32,9 +32,9 @@ func AllocateRequiredConstants(pool cpool.Pool, long_irs []*IRWriter) {
for i := range irw.Instructions {
instr := &irw.Instructions[i]
if instr.Tag == ir.PRIMCONSTANT {
key := instr.PrimConstant.Pair
key := instr.PrimConstant().Pair
alt_lens[key] = len(instr.Bytecode)
if instr.PrimConstant.T.Wide() {
if instr.PrimConstant().T.Wide() {
if len(instr.Bytecode) > 3 {
wide_pairs[key] += 1
}
@@ -46,14 +46,24 @@ type Instruction struct {
HasBC bool

Tag insTag
Label
RegAccess
PrimConstant
Goto
If
Switch
sub interface{}
}

func (self *Instruction) Label() Label {
lbl, ok := self.sub.(*Label)
if !ok {
return Label{}
} else {
return *lbl
}
}

func (self *Instruction) RegAccess() *RegAccess { return self.sub.(*RegAccess) }
func (self *Instruction) PrimConstant() *PrimConstant { return self.sub.(*PrimConstant) }
func (self *Instruction) Goto() *Goto { return self.sub.(*Goto) }
func (self *Instruction) If() *If { return self.sub.(*If) }
func (self *Instruction) Switch() *Switch { return self.sub.(*Switch) }

func (self *Instruction) Fallsthrough() bool {
switch self.Tag {
case GOTO_TAG, SWITCH:
@@ -71,11 +81,12 @@ func (self *Instruction) Fallsthrough() bool {
func (self *Instruction) Targets() []uint32 {
switch self.Tag {
case GOTO_TAG:
return []uint32{self.Goto.Target}
return []uint32{self.Goto().Target}
case IF:
return []uint32{self.If.Target}
return []uint32{self.If().Target}
case SWITCH:
{
self := self.Switch()
result := make([]uint32, 0, 1+len(self.Jumps))
for _, v := range self.Jumps {
result = append(result, v)
@@ -97,19 +108,19 @@ func (self *Instruction) IsConstant() bool {
func (self *Instruction) MinLen(pos uint32) uint32 {
switch self.Tag {
case GOTO_TAG:
if self.Goto.Wide {
if self.Goto().Wide {
return 5
} else {
return 3
}
case IF:
if self.If.Wide {
if self.If().Wide {
return 8
} else {
return 3
}
case SWITCH:
return ((^pos) % 4) + self.NoPadSize
return ((^pos) % 4) + self.Switch().NoPadSize
default:
return uint32(len(self.Bytecode))
}
@@ -125,7 +136,7 @@ func (self *Instruction) UpperBound() int {
case IF:
return 8
case SWITCH:
return 3 + int(self.NoPadSize)
return 3 + int(self.Switch().NoPadSize)
}
panic(util.Unreachable)
}
@@ -149,7 +160,7 @@ type Label struct {
}

func NewLabel(tag lblTag, pos uint32) Instruction {
return Instruction{HasBC: true, Tag: LABEL, Label: Label{tag, pos}}
return Instruction{HasBC: true, Tag: LABEL, sub: &Label{tag, pos}}
}

type RegKey struct {
@@ -184,12 +195,12 @@ func (self *RegAccess) CalcBytecode(local uint16) string {
}

func NewRegAccess(dreg uint16, st scalars.T, store bool) Instruction {
return Instruction{Tag: REGACCESS, RegAccess: RegAccess{RegKey{dreg, st}, store}}
return Instruction{Tag: REGACCESS, sub: &RegAccess{RegKey{dreg, st}, store}}
}

func RawRegAccess(local uint16, st scalars.T, store bool) Instruction {
data := RegAccess{RegKey{0, st}, store}
return Instruction{Bytecode: data.CalcBytecode(local), HasBC: true, Tag: REGACCESS, RegAccess: data}
return Instruction{Bytecode: data.CalcBytecode(local), HasBC: true, Tag: REGACCESS, sub: &data}
}

type PrimConstant struct {
@@ -260,7 +271,7 @@ func NewPrimConstant(st scalars.T, val uint64, pool cpool.Pool) Instruction {
} else {
bytecode = constants.Calc(st, val)
}
return Instruction{Bytecode: bytecode, HasBC: true, Tag: PRIMCONSTANT, PrimConstant: PrimConstant{st, key}}
return Instruction{Bytecode: bytecode, HasBC: true, Tag: PRIMCONSTANT, sub: &PrimConstant{st, key}}
}

func NewOtherConstant(bc string) Instruction {
@@ -273,7 +284,7 @@ type Goto struct {
}

func NewGoto(target uint32) Instruction {
return Instruction{Tag: GOTO_TAG, Goto: Goto{target, false}}
return Instruction{Tag: GOTO_TAG, sub: &Goto{target, false}}
}

type If struct {
@@ -283,7 +294,7 @@ type If struct {
}

func NewIf(op uint8, target uint32) Instruction {
return Instruction{Tag: IF, If: If{target, false, op}}
return Instruction{Tag: IF, sub: &If{target, false, op}}
}

type Switch struct {
@@ -317,7 +328,7 @@ func NewSwitch(def uint32, jumps map[int32]uint32) Instruction {
best = jumpSize
}

return Instruction{Tag: SWITCH, Switch: Switch{
return Instruction{Tag: SWITCH, sub: &Switch{
Default: def,
Jumps: jumps,
Low: int32(low),
@@ -82,10 +82,11 @@ func (self *IRWriter) calcInitialArgs(nregs uint16, scalar_ptypes []scalars.T) {

func (self *IRWriter) addExceptionRedirect(target uint32) ir.Label {
if val, ok := self.exception_redirects[target]; ok {
return val.Label
return val.Label()
}
self.exception_redirects[target] = ir.NewLabel(ir.EHANDLER, target)
return self.exception_redirects[target].Label
temp := ir.NewLabel(ir.EHANDLER, target)
self.exception_redirects[target] = temp
return temp.Label()
}

func (self *IRWriter) createBlock(pos uint32) *irBlock {
@@ -42,7 +42,7 @@ func widenIfNecessary(ins *ir.Instruction, pos uint32, info PosInfo) bool {
switch ins.Tag {
case ir.GOTO_TAG:
{
data := &ins.Goto
data := ins.Goto()
if data.Wide {
return false
}
@@ -52,7 +52,7 @@ func widenIfNecessary(ins *ir.Instruction, pos uint32, info PosInfo) bool {
}
case ir.IF:
{
data := &ins.If
data := ins.If()
if data.Wide {
return false
}
@@ -77,7 +77,7 @@ func optimizeJumps(irdata *IRWriter) {
for i := range instrs {
ins := &instrs[i]
if ins.Tag == ir.LABEL {
lblToVind[ins.Label] = i
lblToVind[ins.Label()] = i
}
}

@@ -110,7 +110,7 @@ func createBytecode(irdata *IRWriter) (string, []string) {
for i := range instrs {
ins := &instrs[i]
if ins.Tag == ir.LABEL {
lblToVind[ins.Label] = i
lblToVind[ins.Label()] = i
}
}

@@ -125,7 +125,7 @@ func createBytecode(irdata *IRWriter) (string, []string) {
switch ins.Tag {
case ir.GOTO_TAG:
{
data := ins.Goto
data := ins.Goto()
offset := info.offset(pos, data.Target)
if data.Wide {
stream.WriteString(byteio.Bi(GOTO_W, offset))
@@ -135,7 +135,7 @@ func createBytecode(irdata *IRWriter) (string, []string) {
}
case ir.IF:
{
data := ins.If
data := ins.If()
offset := info.offset(pos, data.Target)
if data.Wide {
// Unlike with goto, if instructions are limited to a 16 bit jump offset.
@@ -157,7 +157,7 @@ func createBytecode(irdata *IRWriter) (string, []string) {
}
case ir.SWITCH:
{
data := ins.Switch
data := ins.Switch()
offset := info.offset(pos, data.Default)
pad := (^pos) % 4

@@ -206,12 +206,12 @@ func createBytecode(irdata *IRWriter) (string, []string) {
// therefore we include the previous (IR) instruction too
// Note that this cannot cause an overlap because in that case the previous
// instruction would just be a label and hence not change anything
sind := lblToVind[item.start.Label]
sind := lblToVind[item.start.Label()]
if sind > 0 {
sind--
}
soff := positions[sind]
excepts = append(excepts, byteio.HHHH(uint16(soff), uint16(info.getlbl(item.end.Label)), uint16(info.getlbl(item.target)), item.ctype))
excepts = append(excepts, byteio.HHHH(uint16(soff), uint16(info.getlbl(item.end.Label())), uint16(info.getlbl(item.target)), item.ctype))
}

return stream.String(), excepts
@@ -118,23 +118,23 @@ func CopyPropagation(irdata *IRWriter) {
for i := range instrs {
instr := &instrs[i]
// reset all info when control flow is merged
if irdata.IsTarget(instr.Label) {
if irdata.IsTarget(instr.Label()) {
// try to use info if this was a single predecessor forward jump
if i > 0 && !prev.Fallsthrough() && irdata.target_pred_counts[instr.Label] == 1 {
current = single_pred_infos[instr.Label]
if i > 0 && !prev.Fallsthrough() && irdata.target_pred_counts[instr.Label()] == 1 {
current = single_pred_infos[instr.Label()]
if current == nil {
current = newCopySetsMap()
}
} else {
current = newCopySetsMap()
}
} else if instr.Tag == ir.REGACCESS {
ins := instr.RegAccess
ins := instr.RegAccess()
key := ins.RegKey
if ins.Store {
// check if previous instr was a load
if prev.Tag == ir.REGACCESS && !prev.RegAccess.Store {
if !current.move(key, prev.RegKey) {
if prev.Tag == ir.REGACCESS && !prev.RegAccess().Store {
if !current.move(key, prev.RegAccess().RegKey) {
replace[i-1] = nil
replace[i] = nil
}
@@ -172,8 +172,8 @@ func RemoveUnusedRegisters(irdata *IRWriter) {
used := make(map[ir.RegKey]bool)
for i := range instrs {
instr := &instrs[i]
if instr.Tag == ir.REGACCESS && !instr.RegAccess.Store {
used[instr.RegKey] = true
if instr.Tag == ir.REGACCESS && !instr.RegAccess().Store {
used[instr.RegAccess().RegKey] = true
}
}

@@ -182,22 +182,22 @@ func RemoveUnusedRegisters(irdata *IRWriter) {
for i := range instrs {
instr := &instrs[i]
if instr.Tag == ir.REGACCESS {
if !used[instr.RegAccess.RegKey] {
util.Assert(instr.RegAccess.Store)
if !used[instr.RegAccess().RegKey] {
util.Assert(instr.RegAccess().Store)
// if prev instruction is load or const, just remove it and the store
// otherwise, replace the store with a pop
if prev_was_replaceable {
replace[i-1] = nil
replace[i] = nil
} else {
if instr.RegAccess.T.Wide() {
if instr.RegAccess().T.Wide() {
replace[i] = []ir.Instruction{ir.NewOther(byteio.B(POP2))}
} else {
replace[i] = []ir.Instruction{ir.NewOther(byteio.B(POP))}
}
}
}
prev_was_replaceable = !instr.RegAccess.Store
prev_was_replaceable = !instr.RegAccess().Store
} else {
prev_was_replaceable = instr.IsConstant()
}
@@ -218,16 +218,16 @@ func SimpleAllocateRegisters(irdata *IRWriter) {
for i := range instrs {
instr := &instrs[i]
if instr.Tag == ir.REGACCESS {
if _, ok := regmap[instr.RegKey]; !ok {
regmap[instr.RegKey] = next
if _, ok := regmap[instr.RegAccess().RegKey]; !ok {
regmap[instr.RegAccess().RegKey] = next
next++
if instr.RegAccess.T.Wide() {
if instr.RegAccess().T.Wide() {
next++
}
}
_, ok := regmap[instr.RegKey]
_, ok := regmap[instr.RegAccess().RegKey]
util.Assert(ok)
instrs[i].Bytecode = instr.CalcBytecode(uint16(regmap[instr.RegKey]))
instrs[i].Bytecode = instr.RegAccess().CalcBytecode(uint16(regmap[instr.RegAccess().RegKey]))
instrs[i].HasBC = true
}
}
@@ -264,7 +264,7 @@ func SortAllocateRegisters(irdata *IRWriter) {
for i := range instrs {
instr := &instrs[i]
if instr.Tag == ir.REGACCESS {
use_counts[instr.RegKey] += 1
use_counts[instr.RegAccess().RegKey] += 1
}
}

@@ -343,7 +343,7 @@ func SortAllocateRegisters(irdata *IRWriter) {
for i := range instrs {
instr := &instrs[i]
if instr.Tag == ir.REGACCESS && !instr.HasBC {
instr.Bytecode = instr.RegAccess.CalcBytecode(uint16(regmap[instr.RegKey]))
instr.Bytecode = instr.RegAccess().CalcBytecode(uint16(regmap[instr.RegAccess().RegKey]))
instr.HasBC = true
}
}

0 comments on commit 8f35ae0

Please sign in to comment.