text:
package gc

import (
	"cmd/internal/obj"
	"fmt"
	"sort"
)

const (
	UNVISITED = 0
	VISITED   = 1
)

// An ordinary basic block.
//
// Instructions are threaded together in a doubly-linked list.  To iterate in
// program order follow the link pointer from the first node and stop after the
// last node has been visited
//
//   for(p = bb->first;; p = p->link) {
//     ...
//     if(p == bb->last)
//       break;
//   }
//
// To iterate in reverse program order by following the opt pointer from the
// last node
//
//   for(p = bb->last; p != nil; p = p->opt) {
//     ...
//   }
type BasicBlock struct {
	pred            []*BasicBlock // predecessors; if none, probably start of CFG
	succ            []*BasicBlock // successors; if none, probably ends in return statement
	first           *obj.Prog     // first instruction in block
	last            *obj.Prog     // last instruction in block
	rpo             int           // reverse post-order number (also index in cfg)
	mark            int           // mark bit for traversals
	lastbitmapindex int           // for livenessepilogue

	// Summary sets of block effects.

	// Computed during livenessprologue using only the content of
	// individual blocks:
	//
	//	uevar: upward exposed variables (used before set in block)
	//	varkill: killed variables (set in block)
	//	avarinit: addrtaken variables set or used (proof of initialization)
	uevar    Bvec
	varkill  Bvec
	avarinit Bvec

	// Computed during livenesssolve using control flow information:
	//
	//	livein: variables live at block entry
	//	liveout: variables live at block exit
	//	avarinitany: addrtaken variables possibly initialized at block exit
	//		(initialized in block or at exit from any predecessor block)
	//	avarinitall: addrtaken variables certainly initialized at block exit
	//		(initialized in block or at exit from all predecessor blocks)
	livein      Bvec
	liveout     Bvec
	avarinitany Bvec
	avarinitall Bvec
}

// A collection of global state used by liveness analysis.
type Liveness struct {
	fn   *Node
	ptxt *obj.Prog
	vars []*Node
	cfg  []*BasicBlock

	// An array with a bit vector for each safe point tracking live pointers
	// in the arguments and locals area, indexed by bb.rpo.
	argslivepointers []Bvec
	livepointers     []Bvec
}

// Constructs a new basic block containing a single instruction.
func newblock(prog *obj.Prog) *BasicBlock {
	if prog == nil {
		Fatalf("newblock: prog cannot be nil")
	}
	result := new(BasicBlock)
	result.rpo = -1
	result.mark = UNVISITED
	result.first = prog
	result.last = prog
	result.pred = make([]*BasicBlock, 0, 2)
	result.succ = make([]*BasicBlock, 0, 2)
	return result
}

// Adds an edge between two basic blocks by making from a predecessor of to and
// to a successor of from.
func addedge(from *BasicBlock, to *BasicBlock) {
	if from == nil {
		Fatalf("addedge: from is nil")
	}
	if to == nil {
		Fatalf("addedge: to is nil")
	}
	from.succ = append(from.succ, to)
	to.pred = append(to.pred, from)
}

// Inserts prev before curr in the instruction
// stream.  Any control flow, such as branches or fall throughs, that target the
// existing instruction are adjusted to target the new instruction.
func splicebefore(lv *Liveness, bb *BasicBlock, prev *obj.Prog, curr *obj.Prog) {
	// There may be other instructions pointing at curr,
	// and we want them to now point at prev. Instead of
	// trying to find all such instructions, swap the contents
	// so that the problem becomes inserting next after curr.
	// The "opt" field is the backward link in the linked list.

	// Overwrite curr's data with prev, but keep the list links.
	tmp := *curr

	*curr = *prev
	curr.Opt = tmp.Opt
	curr.Link = tmp.Link

	// Overwrite prev (now next) with curr's old data.
	next := prev

	*next = tmp
	next.Opt = nil
	next.Link = nil

	// Now insert next after curr.
	next.Link = curr.Link

	next.Opt = curr
	curr.Link = next
	if next.Link != nil && next.Link.Opt == curr {
		next.Link.Opt = next
	}

	if bb.last == curr {
		bb.last = next
	}
}

// A pretty printer for basic blocks.
func printblock(bb *BasicBlock) {
	fmt.Printf("basic block %d\n", bb.rpo)
	fmt.Printf("\tpred:")
	for _, pred := range bb.pred {
		fmt.Printf(" %d", pred.rpo)
	}
	fmt.Printf("\n")
	fmt.Printf("\tsucc:")
	for _, succ := range bb.succ {
		fmt.Printf(" %d", succ.rpo)
	}
	fmt.Printf("\n")
	fmt.Printf("\tprog:\n")
	for prog := bb.first; ; prog = prog.Link {
		fmt.Printf("\t\t%v\n", prog)
		if prog == bb.last {
			break
		}
	}
}

// Iterates over a basic block applying a callback to each instruction.  There
// are two criteria for termination.  If the end of basic block is reached a
// value of zero is returned.  If the callback returns a non-zero value, the
// iteration is stopped and the value of the callback is returned.
func blockany(bb *BasicBlock, f func(*obj.Prog) bool) bool {
	for p := bb.last; p != nil; p = p.Opt.(*obj.Prog) {
		if f(p) {
			return true
		}
	}
	return false
}

// Collects and returns and array of Node*s for functions arguments and local
// variables.
func getvariables(fn *Node) []*Node {
	result := make([]*Node, 0, 0)
	for ll := fn.Func.Dcl; ll != nil; ll = ll.Next {
		if ll.N.Op == ONAME {
			// In order for GODEBUG=gcdead=1 to work, each bitmap needs
			// to contain information about all variables covered by the bitmap.
			// For local variables, the bitmap only covers the stkptrsize
			// bytes in the frame where variables containing pointers live.
			// For arguments and results, the bitmap covers all variables,
			// so we must include all the variables, even the ones without
			// pointers.
			//
			// The Node.opt field is available for use by optimization passes.
			// We use it to hold the index of the node in the variables array, plus 1
			// (so that 0 means the Node is not in the variables array).
			// Each pass should clear opt when done, but you never know,
			// so clear them all ourselves too.
			// The Node.curfn field is supposed to be set to the current function
			// already, but for some compiler-introduced names it seems not to be,
			// so fix that here.
			// Later, when we want to find the index of a node in the variables list,
			// we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1
			// is the index in the variables list.
			ll.N.SetOpt(nil)

			// The compiler doesn't emit initializations for zero-width parameters or results.
			if ll.N.Type.Width == 0 {
				continue
			}

			ll.N.Name.Curfn = Curfn
			switch ll.N.Class {
			case PAUTO:
				if haspointers(ll.N.Type) {
					ll.N.SetOpt(int32(len(result)))
					result = append(result, ll.N)
				}

			case PPARAM, PPARAMOUT:
				ll.N.SetOpt(int32(len(result)))
				result = append(result, ll.N)
			}
		}
	}

	return result
}

// A pretty printer for control flow graphs.  Takes an array of BasicBlock*s.
func printcfg(cfg []*BasicBlock) {
	for _, bb := range cfg {
		printblock(bb)
	}
}

// Assigns a reverse post order number to each connected basic block using the
// standard algorithm.  Unconnected blocks will not be affected.
func reversepostorder(root *BasicBlock, rpo *int32) {
	root.mark = VISITED
	for _, bb := range root.succ {
		if bb.mark == UNVISITED {
			reversepostorder(bb, rpo)
		}
	}
	*rpo -= 1
	root.rpo = int(*rpo)
}

// Comparison predicate used for sorting basic blocks by their rpo in ascending
// order.
type blockrpocmp []*BasicBlock

func (x blockrpocmp) Len() int           { return len(x) }
func (x blockrpocmp) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
func (x blockrpocmp) Less(i, j int) bool { return x[i].rpo < x[j].rpo }

// A pattern matcher for call instructions.  Returns true when the instruction
// is a call to a specific package qualified function name.
func iscall(prog *obj.Prog, name *obj.LSym) bool {
	if prog == nil {
		Fatalf("iscall: prog is nil")
	}
	if name == nil {
		Fatalf("iscall: function name is nil")
	}
	if prog.As != obj.ACALL {
		return false
	}
	return name == prog.To.Sym
}

// Returns true for instructions that call a runtime function implementing a
// select communication clause.

var selectNames [4]*obj.LSym

func isselectcommcasecall(prog *obj.Prog) bool {
	if selectNames[0] == nil {
		selectNames[0] = Linksym(Pkglookup("selectsend", Runtimepkg))
		selectNames[1] = Linksym(Pkglookup("selectrecv", Runtimepkg))
		selectNames[2] = Linksym(Pkglookup("selectrecv2", Runtimepkg))
		selectNames[3] = Linksym(Pkglookup("selectdefault", Runtimepkg))
	}

	for _, name := range selectNames {
		if iscall(prog, name) {
			return true
		}
	}
	return false
}

// Returns true for call instructions that target runtime·newselect.

var isnewselect_sym *obj.LSym

func isnewselect(prog *obj.Prog) bool {
	if isnewselect_sym == nil {
		isnewselect_sym = Linksym(Pkglookup("newselect", Runtimepkg))
	}
	return iscall(prog, isnewselect_sym)
}

// Returns true for call instructions that target runtime·selectgo.

var isselectgocall_sym *obj.LSym

func isselectgocall(prog *obj.Prog) bool {
	if isselectgocall_sym == nil {
		isselectgocall_sym = Linksym(Pkglookup("selectgo", Runtimepkg))
	}
	return iscall(prog, isselectgocall_sym)
}

var isdeferreturn_sym *obj.LSym

func isdeferreturn(prog *obj.Prog) bool {
	if isdeferreturn_sym == nil {
		isdeferreturn_sym = Linksym(Pkglookup("deferreturn", Runtimepkg))
	}
	return iscall(prog, isdeferreturn_sym)
}

// Walk backwards from a runtime·selectgo call up to its immediately dominating
// runtime·newselect call.  Any successor nodes of communication clause nodes
// are implicit successors of the runtime·selectgo call node.  The goal of this
// analysis is to add these missing edges to complete the control flow graph.
func addselectgosucc(selectgo *BasicBlock) {
	var succ *BasicBlock

	pred := selectgo
	for {
		if len(pred.pred) == 0 {
			Fatalf("selectgo does not have a newselect")
		}
		pred = pred.pred[0]
		if blockany(pred, isselectcommcasecall) {
			// A select comm case block should have exactly one
			// successor.
			if len(pred.succ) != 1 {
				Fatalf("select comm case has too many successors")
			}
			succ = pred.succ[0]

			// Its successor should have exactly two successors.
			// The drop through should flow to the selectgo block
			// and the branch should lead to the select case
			// statements block.
			if len(succ.succ) != 2 {
				Fatalf("select comm case successor has too many successors")
			}

			// Add the block as a successor of the selectgo block.
			addedge(selectgo, succ)
		}

		if blockany(pred, isnewselect) {
			// Reached the matching newselect.
			break
		}
	}
}

// The entry point for the missing selectgo control flow algorithm.  Takes an
// array of BasicBlock*s containing selectgo calls.
func fixselectgo(selectgo []*BasicBlock) {
	for _, bb := range selectgo {
		addselectgosucc(bb)
	}
}

// Constructs a control flow graph from a sequence of instructions.  This
// procedure is complicated by various sources of implicit control flow that are
// not accounted for using the standard cfg construction algorithm.  Returns an
// array of BasicBlock*s in control flow graph form (basic blocks ordered by
// their RPO number).
func newcfg(firstp *obj.Prog) []*BasicBlock {
	// Reset the opt field of each prog to nil.  In the first and second
	// passes, instructions that are labels temporarily use the opt field to
	// point to their basic block.  In the third pass, the opt field reset
	// to point to the predecessor of an instruction in its basic block.
	for p := firstp; p != nil; p = p.Link {
		p.Opt = nil
	}

	// Allocate an array to remember where we have seen selectgo calls.
	// These blocks will be revisited to add successor control flow edges.
	selectgo := make([]*BasicBlock, 0, 0)

	// Loop through all instructions identifying branch targets
	// and fall-throughs and allocate basic blocks.
	cfg := make([]*BasicBlock, 0, 0)

	bb := newblock(firstp)
	cfg = append(cfg, bb)
	for p := firstp; p != nil; p = p.Link {
		Thearch.Proginfo(p)
		if p.To.Type == obj.TYPE_BRANCH {
			if p.To.Val == nil {
				Fatalf("prog branch to nil")
			}
			if p.To.Val.(*obj.Prog).Opt == nil {
				p.To.Val.(*obj.Prog).Opt = newblock(p.To.Val.(*obj.Prog))
				cfg = append(cfg, p.To.Val.(*obj.Prog).Opt.(*BasicBlock))
			}

			if p.As != obj.AJMP && p.Link != nil && p.Link.Opt == nil {
				p.Link.Opt = newblock(p.Link)
				cfg = append(cfg, p.Link.Opt.(*BasicBlock))
			}
		} else if isselectcommcasecall(p) || isselectgocall(p) {
			// Accommodate implicit selectgo control flow.
			if p.Link.Opt == nil {
				p.Link.Opt = newblock(p.Link)
				cfg = append(cfg, p.Link.Opt.(*BasicBlock))
			}
		}
	}

	// Loop through all basic blocks maximally growing the list of
	// contained instructions until a label is reached.  Add edges
	// for branches and fall-through instructions.
	for _, bb := range cfg {
		for p := bb.last; p != nil; p = p.Link {
			if p.Opt != nil && p != bb.last {
				break
			}
			bb.last = p

			// Stop before an unreachable RET, to avoid creating
			// unreachable control flow nodes.
			if p.Link != nil && p.Link.As == obj.ARET && p.Link.Mode == 1 {
				break
			}

			// Collect basic blocks with selectgo calls.
			if isselectgocall(p) {
				selectgo = append(selectgo, bb)
			}
		}

		if bb.last.To.Type == obj.TYPE_BRANCH {
			addedge(bb, bb.last.To.Val.(*obj.Prog).Opt.(*BasicBlock))
		}
		if bb.last.Link != nil {
			// Add a fall-through when the instruction is
			// not an unconditional control transfer.
			if bb.last.As != obj.AJMP && bb.last.As != obj.ARET && bb.last.As != obj.AUNDEF {
				addedge(bb, bb.last.Link.Opt.(*BasicBlock))
			}
		}
	}

	// Add back links so the instructions in a basic block can be traversed
	// backward.  This is the final state of the instruction opt field.
	for _, bb := range cfg {
		p := bb.first
		var prev *obj.Prog
		for {
			p.Opt = prev
			if p == bb.last {
				break
			}
			prev = p
			p = p.Link
		}
	}

	// Add missing successor edges to the selectgo blocks.
	if len(selectgo) != 0 {
		fixselectgo([]*BasicBlock(selectgo))
	}

	// Find a depth-first order and assign a depth-first number to
	// all basic blocks.
	for _, bb := range cfg {
		bb.mark = UNVISITED
	}
	bb = cfg[0]
	rpo := int32(len(cfg))
	reversepostorder(bb, &rpo)

	// Sort the basic blocks by their depth first number.  The
	// array is now a depth-first spanning tree with the first
	// node being the root.
	sort.Sort(blockrpocmp(cfg))

	// Unreachable control flow nodes are indicated by a -1 in the rpo
	// field.  If we see these nodes something must have gone wrong in an
	// upstream compilation phase.
	bb = cfg[0]
	if bb.rpo == -1 {
		fmt.Printf("newcfg: unreachable basic block for %v\n", bb.last)
		printcfg(cfg)
		Fatalf("newcfg: invalid control flow graph")
	}

	return cfg
}

// Frees a control flow graph (an array of BasicBlock*s) and all of its leaf
// data structures.
func freecfg(cfg []*BasicBlock) {
	if len(cfg) > 0 {
		bb0 := cfg[0]
		for p := bb0.first; p != nil; p = p.Link {
			p.Opt = nil
		}
	}
}

// Returns true if the node names a variable that is otherwise uninteresting to
// the liveness computation.
func isfunny(n *Node) bool {
	return n.Sym != nil && (n.Sym.Name == ".fp" || n.Sym.Name == ".args")
}

// Computes the effects of an instruction on a set of
// variables.  The vars argument is an array of Node*s.
//
// The output vectors give bits for variables:
//	uevar - used by this instruction
//	varkill - killed by this instruction
//		for variables without address taken, means variable was set
//		for variables with address taken, means variable was marked dead
//	avarinit - initialized or referred to by this instruction,
//		only for variables with address taken but not escaping to heap
//
// The avarinit output serves as a signal that the data has been
// initialized, because any use of a variable must come after its
// initialization.
func progeffects(prog *obj.Prog, vars []*Node, uevar Bvec, varkill Bvec, avarinit Bvec) {
	bvresetall(uevar)
	bvresetall(varkill)
	bvresetall(avarinit)

	if prog.As == obj.ARET {
		// Return instructions implicitly read all the arguments.  For
		// the sake of correctness, out arguments must be read.  For the
		// sake of backtrace quality, we read in arguments as well.
		//
		// A return instruction with a p->to is a tail return, which brings
		// the stack pointer back up (if it ever went down) and then jumps
		// to a new function entirely. That form of instruction must read
		// all the parameters for correctness, and similarly it must not
		// read the out arguments - they won't be set until the new
		// function runs.
		for i, node := range vars {
			switch node.Class &^ PHEAP {
			case PPARAM:
				bvset(uevar, int32(i))

				// If the result had its address taken, it is being tracked
			// by the avarinit code, which does not use uevar.
			// If we added it to uevar too, we'd not see any kill
			// and decide that the variable was live entry, which it is not.
			// So only use uevar in the non-addrtaken case.
			// The p->to.type == thearch.D_NONE limits the bvset to
			// non-tail-call return instructions; see note above
			// the for loop for details.
			case PPARAMOUT:
				if !node.Addrtaken && prog.To.Type == obj.TYPE_NONE {
					bvset(uevar, int32(i))
				}
			}
		}

		return
	}

	if prog.As == obj.ATEXT {
		// A text instruction marks the entry point to a function and
		// the definition point of all in arguments.
		for i, node := range vars {
			switch node.Class &^ PHEAP {
			case PPARAM:
				if node.Addrtaken {
					bvset(avarinit, int32(i))
				}
				bvset(varkill, int32(i))
			}
		}

		return
	}

	if prog.Info.Flags&(LeftRead|LeftWrite|LeftAddr) != 0 {
		from := &prog.From
		if from.Node != nil && from.Sym != nil && ((from.Node).(*Node)).Name.Curfn == Curfn {
			switch ((from.Node).(*Node)).Class &^ PHEAP {
			case PAUTO, PPARAM, PPARAMOUT:
				pos, ok := from.Node.(*Node).Opt().(int32) // index in vars
				if !ok {
					goto Next
				}
				if pos >= int32(len(vars)) || vars[pos] != from.Node {
					Fatalf("bad bookkeeping in liveness %v %d", Nconv(from.Node.(*Node), 0), pos)
				}
				if ((from.Node).(*Node)).Addrtaken {
					bvset(avarinit, pos)
				} else {
					if prog.Info.Flags&(LeftRead|LeftAddr) != 0 {
						bvset(uevar, pos)
					}
					if prog.Info.Flags&LeftWrite != 0 {
						if from.Node != nil && !Isfat(((from.Node).(*Node)).Type) {
							bvset(varkill, pos)
						}
					}
				}
			}
		}
	}

Next:
	if prog.Info.Flags&(RightRead|RightWrite|RightAddr) != 0 {
		to := &prog.To
		if to.Node != nil && to.Sym != nil && ((to.Node).(*Node)).Name.Curfn == Curfn {
			switch ((to.Node).(*Node)).Class &^ PHEAP {
			case PAUTO, PPARAM, PPARAMOUT:
				pos, ok := to.Node.(*Node).Opt().(int32) // index in vars
				if !ok {
					return
				}
				if pos >= int32(len(vars)) || vars[pos] != to.Node {
					Fatalf("bad bookkeeping in liveness %v %d", Nconv(to.Node.(*Node), 0), pos)
				}
				if ((to.Node).(*Node)).Addrtaken {
					if prog.As != obj.AVARKILL {
						bvset(avarinit, pos)
					}
					if prog.As == obj.AVARDEF || prog.As == obj.AVARKILL {
						bvset(varkill, pos)
					}
				} else {
					// RightRead is a read, obviously.
					// RightAddr by itself is also implicitly a read.
					//
					// RightAddr|RightWrite means that the address is being taken
					// but only so that the instruction can write to the value.
					// It is not a read. It is equivalent to RightWrite except that
					// having the RightAddr bit set keeps the registerizer from
					// trying to substitute a register for the memory location.
					if (prog.Info.Flags&RightRead != 0) || prog.Info.Flags&(RightAddr|RightWrite) == RightAddr {
						bvset(uevar, pos)
					}
					if prog.Info.Flags&RightWrite != 0 {
						if to.Node != nil && (!Isfat(((to.Node).(*Node)).Type) || prog.As == obj.AVARDEF) {
							bvset(varkill, pos)
						}
					}
				}
			}
		}
	}
}

// Constructs a new liveness structure used to hold the global state of the
// liveness computation.  The cfg argument is an array of BasicBlock*s and the
// vars argument is an array of Node*s.
func newliveness(fn *Node, ptxt *obj.Prog, cfg []*BasicBlock, vars []*Node) *Liveness {
	result := new(Liveness)
	result.fn = fn
	result.ptxt = ptxt
	result.cfg = cfg
	result.vars = vars

	nblocks := int32(len(cfg))
	nvars := int32(len(vars))
	bulk := bvbulkalloc(nvars, nblocks*7)
	for _, bb := range cfg {
		bb.uevar = bulk.next()
		bb.varkill = bulk.next()
		bb.livein = bulk.next()
		bb.liveout = bulk.next()
		bb.avarinit = bulk.next()
		bb.avarinitany = bulk.next()
		bb.avarinitall = bulk.next()
	}

	result.livepointers = make([]Bvec, 0, 0)
	result.argslivepointers = make([]Bvec, 0, 0)
	return result
}

// Frees the liveness structure and all of its leaf data structures.
func freeliveness(lv *Liveness) {
	if lv == nil {
		Fatalf("freeliveness: cannot free nil")
	}
}

func printeffects(p *obj.Prog, uevar Bvec, varkill Bvec, avarinit Bvec) {
	fmt.Printf("effects of %v", p)
	fmt.Printf("\nuevar: ")
	bvprint(uevar)
	fmt.Printf("\nvarkill: ")
	bvprint(varkill)
	fmt.Printf("\navarinit: ")
	bvprint(avarinit)
	fmt.Printf("\n")
}

// Pretty print a variable node.  Uses Pascal like conventions for pointers and
// addresses to avoid confusing the C like conventions used in the node variable
// names.
func printnode(node *Node) {
	p := ""
	if haspointers(node.Type) {
		p = "^"
	}
	a := ""
	if node.Addrtaken {
		a = "@"
	}
	fmt.Printf(" %v%s%s", node, p, a)
}

// Pretty print a list of variables.  The vars argument is an array of Node*s.
func printvars(name string, bv Bvec, vars []*Node) {
	fmt.Printf("%s:", name)
	for i, node := range vars {
		if bvget(bv, int32(i)) != 0 {
			printnode(node)
		}
	}
	fmt.Printf("\n")
}

// Prints a basic block annotated with the information computed by liveness
// analysis.
func livenessprintblock(lv *Liveness, bb *BasicBlock) {
	fmt.Printf("basic block %d\n", bb.rpo)

	fmt.Printf("\tpred:")
	for _, pred := range bb.pred {
		fmt.Printf(" %d", pred.rpo)
	}
	fmt.Printf("\n")

	fmt.Printf("\tsucc:")
	for _, succ := range bb.succ {
		fmt.Printf(" %d", succ.rpo)
	}
	fmt.Printf("\n")

	printvars("\tuevar", bb.uevar, []*Node(lv.vars))
	printvars("\tvarkill", bb.varkill, []*Node(lv.vars))
	printvars("\tlivein", bb.livein, []*Node(lv.vars))
	printvars("\tliveout", bb.liveout, []*Node(lv.vars))
	printvars("\tavarinit", bb.avarinit, []*Node(lv.vars))
	printvars("\tavarinitany", bb.avarinitany, []*Node(lv.vars))
	printvars("\tavarinitall", bb.avarinitall, []*Node(lv.vars))

	fmt.Printf("\tprog:\n")
	for prog := bb.first; ; prog = prog.Link {
		fmt.Printf("\t\t%v", prog)
		if prog.As == obj.APCDATA && prog.From.Offset == obj.PCDATA_StackMapIndex {
			pos := int32(prog.To.Offset)
			live := lv.livepointers[pos]
			fmt.Printf(" ")
			bvprint(live)
		}

		fmt.Printf("\n")
		if prog == bb.last {
			break
		}
	}
}

// Prints a control flow graph annotated with any information computed by
// liveness analysis.
func livenessprintcfg(lv *Liveness) {
	for _, bb := range lv.cfg {
		livenessprintblock(lv, bb)
	}
}

func checkauto(fn *Node, p *obj.Prog, n *Node) {
	for l := fn.Func.Dcl; l != nil; l = l.Next {
		if l.N.Op == ONAME && l.N.Class == PAUTO && l.N == n {
			return
		}
	}

	if n == nil {
		fmt.Printf("%v: checkauto %v: nil node in %v\n", p.Line(), Curfn, p)
		return
	}

	fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p)
	for l := fn.Func.Dcl; l != nil; l = l.Next {
		fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class)
	}
	Yyerror("checkauto: invariant lost")
}

func checkparam(fn *Node, p *obj.Prog, n *Node) {
	if isfunny(n) {
		return
	}
	var a *Node
	var class Class
	for l := fn.Func.Dcl; l != nil; l = l.Next {
		a = l.N
		class = a.Class &^ PHEAP
		if a.Op == ONAME && (class == PPARAM || class == PPARAMOUT) && a == n {
			return
		}
	}

	fmt.Printf("checkparam %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p)
	for l := fn.Func.Dcl; l != nil; l = l.Next {
		fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class)
	}
	Yyerror("checkparam: invariant lost")
}

func checkprog(fn *Node, p *obj.Prog) {
	if p.From.Name == obj.NAME_AUTO {
		checkauto(fn, p, p.From.Node.(*Node))
	}
	if p.From.Name == obj.NAME_PARAM {
		checkparam(fn, p, p.From.Node.(*Node))
	}
	if p.To.Name == obj.NAME_AUTO {
		checkauto(fn, p, p.To.Node.(*Node))
	}
	if p.To.Name == obj.NAME_PARAM {
		checkparam(fn, p, p.To.Node.(*Node))
	}
}

// Check instruction invariants.  We assume that the nodes corresponding to the
// sources and destinations of memory operations will be declared in the
// function.  This is not strictly true, as is the case for the so-called funny
// nodes and there are special cases to skip over that stuff.  The analysis will
// fail if this invariant blindly changes.
func checkptxt(fn *Node, firstp *obj.Prog) {
	if debuglive == 0 {
		return
	}

	for p := firstp; p != nil; p = p.Link {
		if false {
			fmt.Printf("analyzing '%v'\n", p)
		}
		if p.As != obj.ADATA && p.As != obj.AGLOBL && p.As != obj.ATYPE {
			checkprog(fn, p)
		}
	}
}

// NOTE: The bitmap for a specific type t should be cached in t after the first run
// and then simply copied into bv at the correct offset on future calls with
// the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, onebitwalktype1
// accounts for 40% of the 6g execution time.
func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
	if t.Align > 0 && *xoffset&int64(t.Align-1) != 0 {
		Fatalf("onebitwalktype1: invalid initial alignment, %v", t)
	}

	switch t.Etype {
	case TINT8,
		TUINT8,
		TINT16,
		TUINT16,
		TINT32,
		TUINT32,
		TINT64,
		TUINT64,
		TINT,
		TUINT,
		TUINTPTR,
		TBOOL,
		TFLOAT32,
		TFLOAT64,
		TCOMPLEX64,
		TCOMPLEX128:
		*xoffset += t.Width

	case TPTR32,
		TPTR64,
		TUNSAFEPTR,
		TFUNC,
		TCHAN,
		TMAP:
		if *xoffset&int64(Widthptr-1) != 0 {
			Fatalf("onebitwalktype1: invalid alignment, %v", t)
		}
		bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer
		*xoffset += t.Width

	case TSTRING:
		// struct { byte *str; intgo len; }
		if *xoffset&int64(Widthptr-1) != 0 {
			Fatalf("onebitwalktype1: invalid alignment, %v", t)
		}
		bvset(bv, int32(*xoffset/int64(Widthptr))) //pointer in first slot
		*xoffset += t.Width

	case TINTER:
		// struct { Itab *tab;	void *data; }
		// or, when isnilinter(t)==true:
		// struct { Type *type; void *data; }
		if *xoffset&int64(Widthptr-1) != 0 {
			Fatalf("onebitwalktype1: invalid alignment, %v", t)
		}
		bvset(bv, int32(*xoffset/int64(Widthptr)))   // pointer in first slot
		bvset(bv, int32(*xoffset/int64(Widthptr)+1)) // pointer in second slot
		*xoffset += t.Width

	case TARRAY:
		// The value of t->bound is -1 for slices types and >=0 for
		// for fixed array types.  All other values are invalid.
		if t.Bound < -1 {
			Fatalf("onebitwalktype1: invalid bound, %v", t)
		}
		if Isslice(t) {
			// struct { byte *array; uintgo len; uintgo cap; }
			if *xoffset&int64(Widthptr-1) != 0 {
				Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
			}
			bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot (BitsPointer)
			*xoffset += t.Width
		} else {
			for i := int64(0); i < t.Bound; i++ {
				onebitwalktype1(t.Type, xoffset, bv)
			}
		}

	case TSTRUCT:
		o := int64(0)
		var fieldoffset int64
		for t1 := t.Type; t1 != nil; t1 = t1.Down {
			fieldoffset = t1.Width
			*xoffset += fieldoffset - o
			onebitwalktype1(t1.Type, xoffset, bv)
			o = fieldoffset + t1.Type.Width
		}

		*xoffset += t.Width - o

	default:
		Fatalf("onebitwalktype1: unexpected type, %v", t)
	}
}

// Returns the number of words of local variables.
func localswords() int32 {
	return int32(stkptrsize / int64(Widthptr))
}

// Returns the number of words of in and out arguments.
func argswords() int32 {
	return int32(Curfn.Type.Argwid / int64(Widthptr))
}

// Generates live pointer value maps for arguments and local variables.  The
// this argument and the in arguments are always assumed live.  The vars
// argument is an array of Node*s.
func onebitlivepointermap(lv *Liveness, liveout Bvec, vars []*Node, args Bvec, locals Bvec) {
	var node *Node
	var xoffset int64

	for i := int32(0); ; i++ {
		i = int32(bvnext(liveout, i))
		if i < 0 {
			break
		}
		node = vars[i]
		switch node.Class {
		case PAUTO:
			xoffset = node.Xoffset + stkptrsize
			onebitwalktype1(node.Type, &xoffset, locals)

		case PPARAM, PPARAMOUT:
			xoffset = node.Xoffset
			onebitwalktype1(node.Type, &xoffset, args)
		}
	}

	// The node list only contains declared names.
	// If the receiver or arguments are unnamed, they will be omitted
	// from the list above. Preserve those values - even though they are unused -
	// in order to keep their addresses live for use in stack traces.
	thisargtype := getthisx(lv.fn.Type)

	if thisargtype != nil {
		xoffset = 0
		onebitwalktype1(thisargtype, &xoffset, args)
	}

	inargtype := getinargx(lv.fn.Type)
	if inargtype != nil {
		xoffset = 0
		onebitwalktype1(inargtype, &xoffset, args)
	}
}

// Construct a disembodied instruction.
func unlinkedprog(as int) *obj.Prog {
	p := Ctxt.NewProg()
	Clearp(p)
	p.As = int16(as)
	return p
}

// Construct a new PCDATA instruction associated with and for the purposes of
// covering an existing instruction.
func newpcdataprog(prog *obj.Prog, index int32) *obj.Prog {
	var from Node
	var to Node

	Nodconst(&from, Types[TINT32], obj.PCDATA_StackMapIndex)
	Nodconst(&to, Types[TINT32], int64(index))
	pcdata := unlinkedprog(obj.APCDATA)
	pcdata.Lineno = prog.Lineno
	Naddr(&pcdata.From, &from)
	Naddr(&pcdata.To, &to)
	return pcdata
}

// Returns true for instructions that are safe points that must be annotated
// with liveness information.
func issafepoint(prog *obj.Prog) bool {
	return prog.As == obj.ATEXT || prog.As == obj.ACALL
}

// Initializes the sets for solving the live variables.  Visits all the
// instructions in each basic block to summarizes the information at each basic
// block
func livenessprologue(lv *Liveness) {
	nvars := int32(len(lv.vars))
	uevar := bvalloc(nvars)
	varkill := bvalloc(nvars)
	avarinit := bvalloc(nvars)
	for _, bb := range lv.cfg {
		// Walk the block instructions backward and update the block
		// effects with the each prog effects.
		for p := bb.last; p != nil; p = p.Opt.(*obj.Prog) {
			progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit)
			if debuglive >= 3 {
				printeffects(p, uevar, varkill, avarinit)
			}
			bvor(bb.varkill, bb.varkill, varkill)
			bvandnot(bb.uevar, bb.uevar, varkill)
			bvor(bb.uevar, bb.uevar, uevar)
		}

		// Walk the block instructions forward to update avarinit bits.
		// avarinit describes the effect at the end of the block, not the beginning.
		bvresetall(varkill)

		for p := bb.first; ; p = p.Link {
			progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit)
			if debuglive >= 3 {
				printeffects(p, uevar, varkill, avarinit)
			}
			bvandnot(bb.avarinit, bb.avarinit, varkill)
			bvor(bb.avarinit, bb.avarinit, avarinit)
			if p == bb.last {
				break
			}
		}
	}
}

// Solve the liveness dataflow equations.
func livenesssolve(lv *Liveness) {
	// These temporary bitvectors exist to avoid successive allocations and
	// frees within the loop.
	newlivein := bvalloc(int32(len(lv.vars)))

	newliveout := bvalloc(int32(len(lv.vars)))
	any := bvalloc(int32(len(lv.vars)))
	all := bvalloc(int32(len(lv.vars)))

	// Push avarinitall, avarinitany forward.
	// avarinitall says the addressed var is initialized along all paths reaching the block exit.
	// avarinitany says the addressed var is initialized along some path reaching the block exit.
	for i, bb := range lv.cfg {
		if i == 0 {
			bvcopy(bb.avarinitall, bb.avarinit)
		} else {
			bvresetall(bb.avarinitall)
			bvnot(bb.avarinitall)
		}
		bvcopy(bb.avarinitany, bb.avarinit)
	}

	change := int32(1)
	for change != 0 {
		change = 0
		for _, bb := range lv.cfg {
			bvresetall(any)
			bvresetall(all)
			for j, pred := range bb.pred {
				if j == 0 {
					bvcopy(any, pred.avarinitany)
					bvcopy(all, pred.avarinitall)
				} else {
					bvor(any, any, pred.avarinitany)
					bvand(all, all, pred.avarinitall)
				}
			}

			bvandnot(any, any, bb.varkill)
			bvandnot(all, all, bb.varkill)
			bvor(any, any, bb.avarinit)
			bvor(all, all, bb.avarinit)
			if bvcmp(any, bb.avarinitany) != 0 {
				change = 1
				bvcopy(bb.avarinitany, any)
			}

			if bvcmp(all, bb.avarinitall) != 0 {
				change = 1
				bvcopy(bb.avarinitall, all)
			}
		}
	}

	// Iterate through the blocks in reverse round-robin fashion.  A work
	// queue might be slightly faster.  As is, the number of iterations is
	// so low that it hardly seems to be worth the complexity.
	change = 1

	for change != 0 {
		change = 0

		// Walk blocks in the general direction of propagation.  This
		// improves convergence.
		for i := len(lv.cfg) - 1; i >= 0; i-- {
			bb := lv.cfg[i]

			// A variable is live on output from this block
			// if it is live on input to some successor.
			//
			// out[b] = \bigcup_{s \in succ[b]} in[s]
			bvresetall(newliveout)
			for _, succ := range bb.succ {
				bvor(newliveout, newliveout, succ.livein)
			}

			if bvcmp(bb.liveout, newliveout) != 0 {
				change = 1
				bvcopy(bb.liveout, newliveout)
			}

			// A variable is live on input to this block
			// if it is live on output from this block and
			// not set by the code in this block.
			//
			// in[b] = uevar[b] \cup (out[b] \setminus varkill[b])
			bvandnot(newlivein, bb.liveout, bb.varkill)

			bvor(bb.livein, newlivein, bb.uevar)
		}
	}
}

// This function is slow but it is only used for generating debug prints.
// Check whether n is marked live in args/locals.
func islive(n *Node, args Bvec, locals Bvec) bool {
	switch n.Class {
	case PPARAM, PPARAMOUT:
		for i := 0; int64(i) < n.Type.Width/int64(Widthptr); i++ {
			if bvget(args, int32(n.Xoffset/int64(Widthptr)+int64(i))) != 0 {
				return true
			}
		}

	case PAUTO:
		for i := 0; int64(i) < n.Type.Width/int64(Widthptr); i++ {
			if bvget(locals, int32((n.Xoffset+stkptrsize)/int64(Widthptr)+int64(i))) != 0 {
				return true
			}
		}
	}

	return false
}

// Visits all instructions in a basic block and computes a bit vector of live
// variables at each safe point locations.
func livenessepilogue(lv *Liveness) {
	var pred *BasicBlock
	var args Bvec
	var locals Bvec
	var n *Node
	var p *obj.Prog
	var j int32
	var pos int32
	var xoffset int64

	nvars := int32(len(lv.vars))
	livein := bvalloc(nvars)
	liveout := bvalloc(nvars)
	uevar := bvalloc(nvars)
	varkill := bvalloc(nvars)
	avarinit := bvalloc(nvars)
	any := bvalloc(nvars)
	all := bvalloc(nvars)
	ambig := bvalloc(localswords())
	nmsg := int32(0)
	startmsg := int32(0)

	for _, bb := range lv.cfg {
		// Compute avarinitany and avarinitall for entry to block.
		// This duplicates information known during livenesssolve
		// but avoids storing two more vectors for each block.
		bvresetall(any)

		bvresetall(all)
		for j = 0; j < int32(len(bb.pred)); j++ {
			pred = bb.pred[j]
			if j == 0 {
				bvcopy(any, pred.avarinitany)
				bvcopy(all, pred.avarinitall)
			} else {
				bvor(any, any, pred.avarinitany)
				bvand(all, all, pred.avarinitall)
			}
		}

		// Walk forward through the basic block instructions and
		// allocate liveness maps for those instructions that need them.
		// Seed the maps with information about the addrtaken variables.
		for p = bb.first; ; p = p.Link {
			progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit)
			bvandnot(any, any, varkill)
			bvandnot(all, all, varkill)
			bvor(any, any, avarinit)
			bvor(all, all, avarinit)

			if issafepoint(p) {
				// Annotate ambiguously live variables so that they can
				// be zeroed at function entry.
				// livein and liveout are dead here and used as temporaries.
				bvresetall(livein)

				bvandnot(liveout, any, all)
				if !bvisempty(liveout) {
					for pos = 0; pos < liveout.n; pos++ {
						if bvget(liveout, pos) == 0 {
							continue
						}
						bvset(all, pos) // silence future warnings in this block
						n = lv.vars[pos]
						if !n.Name.Needzero {
							n.Name.Needzero = true
							if debuglive >= 1 {
								Warnl(int(p.Lineno), "%v: %v is ambiguously live", Curfn.Func.Nname, Nconv(n, obj.FmtLong))
							}

							// Record in 'ambiguous' bitmap.
							xoffset = n.Xoffset + stkptrsize

							onebitwalktype1(n.Type, &xoffset, ambig)
						}
					}
				}

				// Allocate a bit vector for each class and facet of
				// value we are tracking.

				// Live stuff first.
				args = bvalloc(argswords())

				lv.argslivepointers = append(lv.argslivepointers, args)
				locals = bvalloc(localswords())
				lv.livepointers = append(lv.livepointers, locals)

				if debuglive >= 3 {
					fmt.Printf("%v\n", p)
					printvars("avarinitany", any, lv.vars)
				}

				// Record any values with an "address taken" reaching
				// this code position as live. Must do now instead of below
				// because the any/all calculation requires walking forward
				// over the block (as this loop does), while the liveout
				// requires walking backward (as the next loop does).
				onebitlivepointermap(lv, any, lv.vars, args, locals)
			}

			if p == bb.last {
				break
			}
		}

		bb.lastbitmapindex = len(lv.livepointers) - 1
	}

	var fmt_ string
	var next *obj.Prog
	var numlive int32
	var msg []string
	for _, bb := range lv.cfg {
		if debuglive >= 1 && Curfn.Func.Nname.Sym.Name != "init" && Curfn.Func.Nname.Sym.Name[0] != '.' {
			nmsg = int32(len(lv.livepointers))
			startmsg = nmsg
			msg = make([]string, nmsg)
			for j = 0; j < nmsg; j++ {
				msg[j] = ""
			}
		}

		// walk backward, emit pcdata and populate the maps
		pos = int32(bb.lastbitmapindex)

		if pos < 0 {
			// the first block we encounter should have the ATEXT so
			// at no point should pos ever be less than zero.
			Fatalf("livenessepilogue")
		}

		bvcopy(livein, bb.liveout)
		for p = bb.last; p != nil; p = next {
			next = p.Opt.(*obj.Prog) // splicebefore modifies p->opt

			// Propagate liveness information
			progeffects(p, lv.vars, uevar, varkill, avarinit)

			bvcopy(liveout, livein)
			bvandnot(livein, liveout, varkill)
			bvor(livein, livein, uevar)
			if debuglive >= 3 && issafepoint(p) {
				fmt.Printf("%v\n", p)
				printvars("uevar", uevar, lv.vars)
				printvars("varkill", varkill, lv.vars)
				printvars("livein", livein, lv.vars)
				printvars("liveout", liveout, lv.vars)
			}

			if issafepoint(p) {
				// Found an interesting instruction, record the
				// corresponding liveness information.

				// Useful sanity check: on entry to the function,
				// the only things that can possibly be live are the
				// input parameters.
				if p.As == obj.ATEXT {
					for j = 0; j < liveout.n; j++ {
						if bvget(liveout, j) == 0 {
							continue
						}
						n = lv.vars[j]
						if n.Class != PPARAM {
							yyerrorl(int(p.Lineno), "internal error: %v %v recorded as live on entry", Curfn.Func.Nname, Nconv(n, obj.FmtLong))
						}
					}
				}

				// Record live pointers.
				args = lv.argslivepointers[pos]

				locals = lv.livepointers[pos]
				onebitlivepointermap(lv, liveout, lv.vars, args, locals)

				// Ambiguously live variables are zeroed immediately after
				// function entry. Mark them live for all the non-entry bitmaps
				// so that GODEBUG=gcdead=1 mode does not poison them.
				if p.As == obj.ACALL {
					bvor(locals, locals, ambig)
				}

				// Show live pointer bitmaps.
				// We're interpreting the args and locals bitmap instead of liveout so that we
				// include the bits added by the avarinit logic in the
				// previous loop.
				if msg != nil {
					fmt_ = ""
					fmt_ += fmt.Sprintf("%v: live at ", p.Line())
					if p.As == obj.ACALL && p.To.Node != nil {
						fmt_ += fmt.Sprintf("call to %s:", ((p.To.Node).(*Node)).Sym.Name)
					} else if p.As == obj.ACALL {
						fmt_ += "indirect call:"
					} else {
						fmt_ += fmt.Sprintf("entry to %s:", ((p.From.Node).(*Node)).Sym.Name)
					}
					numlive = 0
					for j = 0; j < int32(len(lv.vars)); j++ {
						n = lv.vars[j]
						if islive(n, args, locals) {
							fmt_ += fmt.Sprintf(" %v", n)
							numlive++
						}
					}

					fmt_ += "\n"
					if numlive == 0 { // squelch message

					} else {
						startmsg--
						msg[startmsg] = fmt_
					}
				}

				// Only CALL instructions need a PCDATA annotation.
				// The TEXT instruction annotation is implicit.
				if p.As == obj.ACALL {
					if isdeferreturn(p) {
						// runtime.deferreturn modifies its return address to return
						// back to the CALL, not to the subsequent instruction.
						// Because the return comes back one instruction early,
						// the PCDATA must begin one instruction early too.
						// The instruction before a call to deferreturn is always a
						// no-op, to keep PC-specific data unambiguous.
						splicebefore(lv, bb, newpcdataprog(p.Opt.(*obj.Prog), pos), p.Opt.(*obj.Prog))
					} else {
						splicebefore(lv, bb, newpcdataprog(p, pos), p)
					}
				}

				pos--
			}
		}

		if msg != nil {
			for j = startmsg; j < nmsg; j++ {
				if msg[j] != "" {
					fmt.Printf("%s", msg[j])
				}
			}

			msg = nil
			nmsg = 0
			startmsg = 0
		}
	}

	Flusherrors()
}

// FNV-1 hash function constants.
const (
	H0 = 2166136261
	Hp = 16777619
)

func hashbitmap(h uint32, bv Bvec) uint32 {
	var w uint32

	n := int((bv.n + 31) / 32)
	for i := 0; i < n; i++ {
		w = bv.b[i]
		h = (h * Hp) ^ (w & 0xff)
		h = (h * Hp) ^ ((w >> 8) & 0xff)
		h = (h * Hp) ^ ((w >> 16) & 0xff)
		h = (h * Hp) ^ ((w >> 24) & 0xff)
	}

	return h
}

// Compact liveness information by coalescing identical per-call-site bitmaps.
// The merging only happens for a single function, not across the entire binary.
//
// There are actually two lists of bitmaps, one list for the local variables and one
// list for the function arguments. Both lists are indexed by the same PCDATA
// index, so the corresponding pairs must be considered together when
// merging duplicates. The argument bitmaps change much less often during
// function execution than the local variable bitmaps, so it is possible that
// we could introduce a separate PCDATA index for arguments vs locals and
// then compact the set of argument bitmaps separately from the set of
// local variable bitmaps. As of 2014-04-02, doing this to the godoc binary
// is actually a net loss: we save about 50k of argument bitmaps but the new
// PCDATA tables cost about 100k. So for now we keep using a single index for
// both bitmap lists.
func livenesscompact(lv *Liveness) {
	// Linear probing hash table of bitmaps seen so far.
	// The hash table has 4n entries to keep the linear
	// scan short. An entry of -1 indicates an empty slot.
	n := len(lv.livepointers)

	tablesize := 4 * n
	table := make([]int, tablesize)
	for i := range table {
		table[i] = -1
	}

	// remap[i] = the new index of the old bit vector #i.
	remap := make([]int, n)

	for i := range remap {
		remap[i] = -1
	}
	uniq := 0 // unique tables found so far

	// Consider bit vectors in turn.
	// If new, assign next number using uniq,
	// record in remap, record in lv->livepointers and lv->argslivepointers
	// under the new index, and add entry to hash table.
	// If already seen, record earlier index in remap and free bitmaps.
	var jarg Bvec
	var j int
	var h uint32
	var arg Bvec
	var jlocal Bvec
	var local Bvec
	for i := 0; i < n; i++ {
		local = lv.livepointers[i]
		arg = lv.argslivepointers[i]
		h = hashbitmap(hashbitmap(H0, local), arg) % uint32(tablesize)

		for {
			j = table[h]
			if j < 0 {
				break
			}
			jlocal = lv.livepointers[j]
			jarg = lv.argslivepointers[j]
			if bvcmp(local, jlocal) == 0 && bvcmp(arg, jarg) == 0 {
				remap[i] = j
				goto Next
			}

			h++
			if h == uint32(tablesize) {
				h = 0
			}
		}

		table[h] = uniq
		remap[i] = uniq
		lv.livepointers[uniq] = local
		lv.argslivepointers[uniq] = arg
		uniq++
	Next:
	}

	// We've already reordered lv->livepointers[0:uniq]
	// and lv->argslivepointers[0:uniq] and freed the bitmaps
	// we don't need anymore. Clear the pointers later in the
	// array so that we can tell where the coalesced bitmaps stop
	// and so that we don't double-free when cleaning up.
	for j := uniq; j < n; j++ {
		lv.livepointers[j] = Bvec{}
		lv.argslivepointers[j] = Bvec{}
	}

	// Rewrite PCDATA instructions to use new numbering.
	var i int
	for p := lv.ptxt; p != nil; p = p.Link {
		if p.As == obj.APCDATA && p.From.Offset == obj.PCDATA_StackMapIndex {
			i = int(p.To.Offset)
			if i >= 0 {
				p.To.Offset = int64(remap[i])
			}
		}
	}
}

func printbitset(printed int, name string, vars []*Node, bits Bvec) int {
	started := 0
	for i, n := range vars {
		if bvget(bits, int32(i)) == 0 {
			continue
		}
		if started == 0 {
			if printed == 0 {
				fmt.Printf("\t")
			} else {
				fmt.Printf(" ")
			}
			started = 1
			printed = 1
			fmt.Printf("%s=", name)
		} else {
			fmt.Printf(",")
		}

		fmt.Printf("%s", n.Sym.Name)
	}

	return printed
}

// Prints the computed liveness information and inputs, for debugging.
// This format synthesizes the information used during the multiple passes
// into a single presentation.
func livenessprintdebug(lv *Liveness) {
	var j int
	var printed int
	var p *obj.Prog
	var args Bvec
	var locals Bvec
	var n *Node

	fmt.Printf("liveness: %s\n", Curfn.Func.Nname.Sym.Name)

	uevar := bvalloc(int32(len(lv.vars)))
	varkill := bvalloc(int32(len(lv.vars)))
	avarinit := bvalloc(int32(len(lv.vars)))

	pcdata := 0
	for i, bb := range lv.cfg {
		if i > 0 {
			fmt.Printf("\n")
		}

		// bb#0 pred=1,2 succ=3,4
		fmt.Printf("bb#%d pred=", i)

		for j = 0; j < len(bb.pred); j++ {
			if j > 0 {
				fmt.Printf(",")
			}
			fmt.Printf("%d", (bb.pred[j]).rpo)
		}

		fmt.Printf(" succ=")
		for j = 0; j < len(bb.succ); j++ {
			if j > 0 {
				fmt.Printf(",")
			}
			fmt.Printf("%d", (bb.succ[j]).rpo)
		}

		fmt.Printf("\n")

		// initial settings
		printed = 0

		printed = printbitset(printed, "uevar", lv.vars, bb.uevar)
		printed = printbitset(printed, "livein", lv.vars, bb.livein)
		if printed != 0 {
			fmt.Printf("\n")
		}

		// program listing, with individual effects listed
		for p = bb.first; ; p = p.Link {
			fmt.Printf("%v\n", p)
			if p.As == obj.APCDATA && p.From.Offset == obj.PCDATA_StackMapIndex {
				pcdata = int(p.To.Offset)
			}
			progeffects(p, lv.vars, uevar, varkill, avarinit)
			printed = 0
			printed = printbitset(printed, "uevar", lv.vars, uevar)
			printed = printbitset(printed, "varkill", lv.vars, varkill)
			printed = printbitset(printed, "avarinit", lv.vars, avarinit)
			if printed != 0 {
				fmt.Printf("\n")
			}
			if issafepoint(p) {
				args = lv.argslivepointers[pcdata]
				locals = lv.livepointers[pcdata]
				fmt.Printf("\tlive=")
				printed = 0
				for j = 0; j < len(lv.vars); j++ {
					n = lv.vars[j]
					if islive(n, args, locals) {
						if printed != 0 {
							fmt.Printf(",")
						}
						fmt.Printf("%v", n)
						printed++
					}
				}
				fmt.Printf("\n")
			}

			if p == bb.last {
				break
			}
		}

		// bb bitsets
		fmt.Printf("end\n")

		printed = printbitset(printed, "varkill", lv.vars, bb.varkill)
		printed = printbitset(printed, "liveout", lv.vars, bb.liveout)
		printed = printbitset(printed, "avarinit", lv.vars, bb.avarinit)
		printed = printbitset(printed, "avarinitany", lv.vars, bb.avarinitany)
		printed = printbitset(printed, "avarinitall", lv.vars, bb.avarinitall)
		if printed != 0 {
			fmt.Printf("\n")
		}
	}

	fmt.Printf("\n")
}

// Dumps an array of bitmaps to a symbol as a sequence of uint32 values.  The
// first word dumped is the total number of bitmaps.  The second word is the
// length of the bitmaps.  All bitmaps are assumed to be of equal length.  The
// words that are followed are the raw bitmap words.  The arr argument is an
// array of Node*s.
func onebitwritesymbol(arr []Bvec, sym *Sym) {
	var i int
	var j int
	var word uint32

	n := len(arr)
	off := 0
	off += 4 // number of bitmaps, to fill in later
	bv := arr[0]
	off = duint32(sym, off, uint32(bv.n)) // number of bits in each bitmap
	for i = 0; i < n; i++ {
		// bitmap words
		bv = arr[i]

		if bv.b == nil {
			break
		}
		for j = 0; int32(j) < bv.n; j += 32 {
			word = bv.b[j/32]

			// Runtime reads the bitmaps as byte arrays. Oblige.
			off = duint8(sym, off, uint8(word))

			off = duint8(sym, off, uint8(word>>8))
			off = duint8(sym, off, uint8(word>>16))
			off = duint8(sym, off, uint8(word>>24))
		}
	}

	duint32(sym, 0, uint32(i)) // number of bitmaps
	ggloblsym(sym, int32(off), obj.RODATA)
}

func printprog(p *obj.Prog) {
	for p != nil {
		fmt.Printf("%v\n", p)
		p = p.Link
	}
}

// Entry pointer for liveness analysis.  Constructs a complete CFG, solves for
// the liveness of pointer variables in the function, and emits a runtime data
// structure read by the garbage collector.
func liveness(fn *Node, firstp *obj.Prog, argssym *Sym, livesym *Sym) {
	// Change name to dump debugging information only for a specific function.
	debugdelta := 0

	if Curfn.Func.Nname.Sym.Name == "!" {
		debugdelta = 2
	}

	debuglive += debugdelta
	if debuglive >= 3 {
		fmt.Printf("liveness: %s\n", Curfn.Func.Nname.Sym.Name)
		printprog(firstp)
	}

	checkptxt(fn, firstp)

	// Construct the global liveness state.
	cfg := newcfg(firstp)

	if debuglive >= 3 {
		printcfg([]*BasicBlock(cfg))
	}
	vars := getvariables(fn)
	lv := newliveness(fn, firstp, cfg, vars)

	// Run the dataflow framework.
	livenessprologue(lv)

	if debuglive >= 3 {
		livenessprintcfg(lv)
	}
	livenesssolve(lv)
	if debuglive >= 3 {
		livenessprintcfg(lv)
	}
	livenessepilogue(lv)
	if debuglive >= 3 {
		livenessprintcfg(lv)
	}
	livenesscompact(lv)

	if debuglive >= 2 {
		livenessprintdebug(lv)
	}

	// Emit the live pointer map data structures
	onebitwritesymbol(lv.livepointers, livesym)

	onebitwritesymbol(lv.argslivepointers, argssym)

	// Free everything.
	for l := fn.Func.Dcl; l != nil; l = l.Next {
		if l.N != nil {
			l.N.SetOpt(nil)
		}
	}
	freeliveness(lv)

	freecfg([]*BasicBlock(cfg))

	debuglive -= debugdelta
}

redpajama_set_name: RedPajamaGithub


text:
About Save Our Heritage
Current Objectives
Support Save Our Heritage!
Protecting the birthplace of the American Revolution, the cradle of the American Environmental Movement, and the home of the American Literary Renaissance.
That State and Federal designations are enacted recognizing the historical and environmental significance of this area. To achieve permanent protection for the national historical, cultural, and environmental resources in the Massachusetts towns of Concord, Bedford, Lincoln, and Lexington in order to prevent their gradual destruction by pollution, noise, and development.
We are a group of Americans who care deeply about the long term future of these historic communities. Each national landmark in these communities has a wonderful and dedicated group of volunteers who have a long term vision for that landmark. Save Our Heritage does not seek to duplicate these efforts but rather to help these different groups come together to collaborate on common challenges, and, when necessary, step in to assist with unexpected problems or opportunities that have no established constituency.
Current Objectives:
The Barrett Farm Project
Ongoing protection of the buildings and landscape of Barrett Farm, the British destination on the first day of the Revolutionary War, and central to the story of April 19.
This historic site was acquired by Save Our Heritage and restored over a 10 year period and then ownership was transferred Minute Man National Historical Park, in order to complete the Park and help it fulfill its mission.
The Hanscom Project
To educate the public regarding the special nature of the resources surrounding Hanscom Field and the threat these national landmarks face from the expansion of the airport.
To increase public awareness of the consequences if limits are not placed on the increased noise, ground traffic, and environmental pollution that may result from the expansion of air traffic at Hanscom Field or changes in the character and use of the airport.
To monitor to ensure that State authorities honor their 25 year commitment not to develop Hanscom Field into a commercial airport.
To encourage public engagement so that all future development properly comprehends, discloses, and is appropriately burdened with the costs of damage to the unique historical and environmental resources of this area.
To increase public understanding regarding the impacts of Airports on health and the environment.
To encourage the development of Federal programs which will reduce the impact of Aircraft on people and the environment
Other Objectives:
To work to ensure that the Orchard House and other key historic buildings are restored protected from natural deterioration processes which are seriously affecting their condition.
To work to ensure that Walden Woods is protected and the remaining surrounding undeveloped land is reunited with Walden Pond.
The Advisory Board of Save Our Heritage:
Kathi Anderson, Executive Director, Walden Woods Project &Thoreau Institute
Representative Cory Atkins (honorary)
Ed Begley, Jr., Actor, Environmentalist
Douglas Brinkley, Professor of History, Tulane University
Richard D. Brown, Professor of History University of Connecticut
Ken Burns, Director, Producer, Historical Documentarian
Joan Cusack, Actress
Michael S. Dukakis, Professor, UCLA & Northeastern University Former Governor, Massachusetts
Doris Kearns Goodwin, Historian, Author
Don Henley, Recording Artist, Founder, Walden Woods Project
Laura Johnson, Former President,  Massachusetts Audubon Society
Michael Kellett, Executive Director, Thoreau Country Conservation Alliance & RESTORE: The North Woods
Congressman Edward J. Markey, (honorary)
Gregor McGregor, Esq.,  McGregor and Associates, P.C.
David McCullough, Historian, Author
Richard Moe, Former President, Natl. Trust for Historic Preservation
Wesley T. Mott, Former President,  The Emerson Society
Edward O. Wilson, Ph.D., Author,  Professor, Harvard University
Joanne Woodward, Actress, Humanitarian
Anna West Winter
You can contact us at 978-369-6662

redpajama_set_name: RedPajamaCommonCrawl


Cheddar (bulk by the pound) (food service) - Sunflower-based Vegan Indulgence Made for Everyone.
Meltable, sliceable, grate-able – this lightly-sharp cheddar is wonderful on Mac N' Cheese, burgers, pizzas and more. Sold by pound in blocks.
Meltable, sliceable, grate-able – this lightly-sharp cheddar is wonderful on Mac N' Cheese, burgers, pizzas and more.
Free of dairy, nuts, soy, and gluten. Vegan. Kosher. Made with organic ingredients.


KAO DODE (Jumping knee strike) - the Thai boxer jumps up on one leg and strikes with that leg's knee, sometimes grabbing opponents head and pulling down at same time.
KAO LOI (Flying knee strike) - the Thai boxer takes step(s) traverses the ground, springs up off one leg and in mid-air switches to the other knee to strike. A quite spectacular sight when it connects, best when opponent is off balanced, hurt or tired.
KAO DTRONG (Straight knee strike) - the Thai boxer simply thrusts it straight upwards stabbing forwards. According to one written source, this technique is somewhat more recent than Kao Dode & Kao Loi. Supposedly, when the Thai boxers fought with rope-bound hands rather than the modern boxing gloves, this particular technique was subject to potentially vicious cutting, slicing and sawing by an alert opponent who would block it or deflect it with the sharp "rope-glove" edges .
Past University College London RukThai Camp Thai Martial Arts Society Presidents Bhavin and Pardeep Demonstrate Special Master Tricks of MuayThai.


text:
Diaries of AIF Servicemen, Bert Schramm, 30 September 1918
Topic: Diary - Schramm
Diaries of AIF Servicemen
Bert Schramm
2823 Private Herbert Leslie SCHRAMM, a 22 year old Farmer from Whites River, South Australia. He enlisted on 17 February 1916; and at the conclusion of the war Returned to Australia, 10 July 1919.
During part of the course of his military service with the AIF, Bert Schramm kept a diary of his life. Bert was not a man of letters so this diary was produced with great effort on his behalf. Bert made a promise to his sweetheart, Lucy Solley, that he would do so after he received the blank pocket notebook wherein these entries are found. As a Brigade Scout since September 1918, he took a lead part in the September Offensive by the Allied forces in Palestine. Bert's diary entries are placed alongside those of the 9th Light Horse Regiment to which he belonged and to the 3rd Light Horse Brigade to which the 9th LHR was attached. On this basis we can follow Bert in the context of his formation.
The complete diary is now available on the Australian Light Horse Studies Centre Site at:
Bert Schramm Diary
Finding more about a service person. See:
Navigating the National Archives Service File
Bert Schramm's Handwritten Diary, 27 September to 1 October 1918
[Click on page for a larger print version.]
Bert Schramm's Location - Khan esh Shiha; Dumar
Bert Schramm's Diary - We pushed on all day towards Damascus and we had sharp fighting all day. Tonight we are on the outskirts of Damascus. Enemy has been burning all dumps, wireless station etc. It is a great sight to see tonight. We have been firing into a village north west of the town which is pretty full of the enemy.
9th Light Horse Regiment War Diary
9th Light Horse Regiment Location - Khan esh Shiha; Dumar
9th Light Horse Regiment War Diary - 0300, a fresh Brigade now passed through the 3rd Light Horse Brigade which, after concentrating, moved off about 0330 to Sasa where a halt was made for one hour and horses watered.
0730 The brigade moved towards Damascus preceded by 5th and 4th Light Horse Brigades.
0900 Arrived Khan esh Shiha. From this place the first sight of Damascus was obtained. 4,000 enemy were reported in vicinity of Kaukab. At Khan esh Shiha the Division deployed for the final advance on Damascus. 4th Light Horse Brigade on the right, 5th Light Horse Brigade on the left with 3rd Light Horse Brigade immediately in rear. Each Brigade in columns of squadrons in line, a very imposing sight. 11/2 miles south west of Kaukab 5th and 3rd Light Horse Brigades turned slightly to the left and advanced rapidly north eastwards along the foot of the ridge on the western side of the orchards south of Damascus. 4th Light Horse Brigade were meeting opposition in country south east of Kaukab. Enemy artillery and machine guns were firing but our batteries soon opened up. Part of the 4th Light Horse Brigade were observed to charge and their advance of that Brigade continued. Meanwhile the 5th and 3rd Light Horse Brigades continued to advance rapidly until about one mile south west of El Mezze was reached. At this place further advance was strongly opposed by the enemy who had mounted machine guns on the outskirts of the village orchards.
1400 The French Regiment of the 5th Light Horse Brigade were observed to move west into hills followed later by another portion of that Brigade.
1540 Orders received were for 9th Light Horse Regiment to supply advance guard for 3rd Light Horse Brigade to cross over Damascus - Beirut railway and endeavour to get astride the main road in vicinity of Jobar.
1600 The Regiment moved with A Squadron in advance. Country was extremely difficult being high stony hills without roads.
1645 A Squadron had seized the high ground overlooking Dumar and the Damascus - Beirut road and railway. The only means of entering the village was down a narrow rocky track. A Squadron made two attempts to force this route but found it strongly commanded by many enemy machine guns placed in and around the village of Dumar. This squadron with two machine guns attached then took up a position overlooking village, road and railway. The road was packed with enemy troops and transport. A heavy fire was brought to bear on those and heavy casualties inflicted. Portion of 5th Light Horse Brigade were in position on left of A Squadron.
1700 Remainder of Regiment and machine gun squadron arrived. B Squadron and all machine guns were put into the line and concentrated their fire on road and railway. Before nightfall a fresh attempt was made to force the track into village but it was found to be still impassable without heavy casualties.
1830 Orders received to hold present position containing main road for remainder of night and the Brigade would advance at 0500 following morning. 9th Light Horse Regiment to detail two Troops dismounted reconnoitre village and railway early as possible.
1910 Hargrave, Lieutenant LMS, MC and Masson, Lieutenant GG, with their troops from C Squadron and Regimental interpreter moved out on this duty. It was a difficult mission and great credit is due to these two troops for their boldness and daring in successfully reconnoitring the village and railway. Two troops reported back to Regiment at 2100. Hargrave, Lieutenant LMS, reporting that the village was free from enemy except bodies of stragglers. Six Hospitals were in village and believed full of wounded and sick. The main road to Amara was blocked with transport but believed passable for mounted troops. A Turkish guard was on duty at the railway station. A large running creek surrounded the village on three sides but all bridges observed were intact. The Regiment remained in position during remainder of night. Intermittent fire was maintained on road and railway. During the night an enemy train from direction of Beirut entered the station and was captured when the Brigade advanced the following morning.
1930 The Commanding Officer on account of a recurrence of malaria was obliged to halt and rest. Daly, Major TJ, DSO assumed command of the Regiment.
3rd Light Horse Brigade War Diary
At 0200 as the 9th and 10th Light Horse Regiments were making only slow progress, 6th Light Horse Regiment, less two Squadrons was sent in dismounted to storm the enemy position frontally from the road. Cooperation by the 9th and 10th Light Horse Regiments was arranged for as far as darkness time, and the exceedingly rough nature of the ground permitted. By 0200 the 8th Light Horse Regiment had captured the enemy position with five machine guns and a few German prisoners. During the advance, the Regiment was subjected to a heavy rifle and machine gun fire. The enemy beat a hasty retreat towards Damascus, vigorously pursued along the road by the 10th Light Horse Regiment. The advance was again held up temporarily about one mile south of Sasa. The vanguard with two machine guns attached dismounted and rushed the enemy, who then broke and made off towards Sasa in motor lorries, which had been brought up behind their lines. In the course of this pursuit the 10th Light Horse Regiment captured two 77mm field guns, two machine guns, one motor lorry and about 20 prisoners. The Brigade had orders that from dawn onwards the 4th Light Horse Brigade would form the Divisional advance guard, while the 3rd Light Horse Brigade assembled after the action just concluded. Shortly after the 4th Light Horse Brigade took up the pursuit they overtook and captured several hundred fugitives. At 0645 all troops of rhe Brigade had reached Sasa, and at 0730 the Brigade marched following the remainder of the Division. On arrival at Khan esh Shiha, Divisional orders for the approach on Damascus were received. The 5th Light Horse Brigade closely followed by the 3rd Light Horse Brigade were to outflank the town by moving via Katana, north easterly along the foothills of Kalabat el Mezze. Bourchier's force, [two Regiments of the 4th Light Horse Brigade], were to move directly on the town via Daraya. Soon after this movement commenced enemy machine gun fire was heard directed against Bourchier's force from the vicinity El Kaukab. The 19th Brigade, Royal Horse Artillery engaged these machine guns, the 5th and 3rd Light Horse Brigade meantime pressing on to their objective at the trot. When a point half a mile north of Mudhamiye had been reached, troops of Bourchier's force were observed galloping the enemy's position supported by the fire of the Royal Horse Artillery batteries. Away to the east could be seen shrapnel bursting, no doubt; from the artillery of the 14th Brigade of the 5th Cavalry Division sent across to intercept the Turkish third Cavalry division retreating on Damascus. The 5th and 3rd Brigades pressed on, until at a point about 11/2 miles south west of El Mezze the French Cavalry Regiment which was leading was held up by machine gun fire from the garden west of the southern end of the town. The Royal Horse Artillery batteries were brought up and engaged these, machine guns - the 3rd Light Horse Brigade remaining halted ready to support the 5th Light Horse Brigade when and where required. The enemy machine guns concealed in the gardens were difficult to locate and swept the open ground over which any direct advance would have to be made. About 1530 orders were received that the 5th Light Horse Brigade were to turn into the hills on their left and cut the road and railway leading north west to Beirut along which the main line of retreat of enemy troops to Damascus lay, while the 3rd Light Horse Brigade, were to make their way to the north east road leading to Homs and Aleppo and block that line of retreat. The Brigade at once moved off, 9th Light Horse Regiment and six machine guns forming the advance guard. After a short advance over rough hilly country the Brigade reached a point about one mile south west of the village of Dumar. Reconnaissances soon showed that the nature of the terrain was such that an advance across country over Jebel Kasiun was impossible. The only alternative was the main road from Dumar through Er Rabue and then through the northern end of Damascus itself. In preparation of this the leading squadron of the 9th Light Horse Regiment and four machine guns took up a position on the high ground immediately south west of Dumar. Large bodies of the enemy were seen to be retreating along the road from Damascus to Beirut. They were in a closely formed column of infantry, transport and guns. This column was caught at effective range by the fire of our rifles and machine guns. Those who had passed before our occupation of the high ground commanding the road above Dumar were caught by the fire of the 5th Light Horse Brigade further to the west, while still further west again a squadron of the 8th Light Horse Regiment was also in position commanding road and railway. It is estimated that at least 700 casualties were inflicted on the enemy in this gorge of the Barada, in addition hundreds of animals were killed; horses, cattle, donkeys, sheep and dogs. The remainder of the column lost heart and returned back to Damascus and no doubt formed the bulk of the 12,000 prisoners which were collected there next morning. The Beirut road was thus closed at sunset on 30th September 1918. A visual station had been sent out to get communication with Division and through it orders were now received for the Brigade to bivouac in its present position for the night and march for the Homs road at 0500 the next day in pursuit of enemy retreating to the north east. Loud explosions were heard in Damascus and the flames of burning stores lit up the skies throughout the night.
The 9th Light Horse Regiment and six machine guns remained all night in position above Dumar sweeping the roads by fire and preventing any escape along this route by the enemy. Such targets are more dreamed of than realised by machine gunners.
At 1900 two troops of the 9th Light Horse Regiment, [Hargrave, Lieutenant LMS, MC and Masson, Lieutenant GG], reconnoitred the village of Dumar and found same clear of enemy, except for dead, sick and wounded and a few stragglers. The main road to Damascus was packed with transport but with little trouble would be passable to mounted troops. The bridge over the Barada was intact. A Turkish guard was still on sentry at the railway station.
Not withstanding rough country and the delaying action fought by the enemy south of Sasa the Brigade had covered 34 miles in 26 hours without off saddling, except for one hour at Sasa.
9th LHR AIF War Diary, 30 September
Darley
Darley, TH, With the Ninth Light Horse in the Great War, Adelaide, Hassell Press, 1924, pp 158 - 162.
The Fall of Damascus
As day broke on the 1st October, 1918, the beautiful city of Damascus, the Jewel of the East, came into view. Many splendid buildings could be seen, including the main railway station and the military barracks, now used as a hospital, from the staff of which the red crescent was flying. The Barada River wound like a silver thread through the town and surrounding country, with numerous small water channels passing through the beautiful orchards and vineyards which enclosed the city on all sides.
At 5 a.m. the Regiment, with the remainder of the Brigade, crossed the river by the bridge at Dumar and proceeded along the main road towards Damascus. As the advance continued the terrible execution of the previous day became apparent, the road being completely blocked with piles of dead and dying men and animals, and disabled transport. The advance troops reported that for nearly a mile ahead the road was practically impassable, and parties were sent forward to clear a track. It was gruesome task. The wounded Germans and Turks were carried, with as much care as possible, to the grassy bank of the river, where they were left to be collected by our ambulances, which were in rear of the Brigade, whilst the dead were removed to the side of the road to await burial.
Wounded animals were shot and dragged to the side of the road, as were also the vehicles. Many of the vehicles had overturned into the river during the attempt to break through, and had been abandoned.
The advance Regiment, 10th Light Horse Regiment, pushed forward and captured the railway station together with the train which had passed through the previous night. About 1,000 prisoners were also taken at this point. A few Germans made an attempt at resistance, but were soon overpowered and taken prisoner. At the barracks a huge force of Turks could be seen on the parade ground, and appeared to be in a state of great confusion. After a slight show of resistance they surrendered to the advance guard.
As the column reached the centre of the city dense crowds filled the streets and squares. A large number of these people carried firearms of some description, and as a sign of rejoicing they proceeded to discharge them into the air, so that what was really a peaceful entry sounded more like a desperate battle. The crowds were composed of all classes: Arabs in their long galabiehs, Syrians mostly in European dress, Greek and Turkish civilians, Jews, Armenians, and French. Cheering wildly they lined the streets and offered gifts of fruit and cigarettes to the passing troops.
This wonderful welcome was somewhat difficult to understand, and many doubted its genuineness. It was, however, ascertained from a guide that a rumour had been circulated the previous afternoon to the effect that in the event of the British Cavalry approaching nearer to Damascus the Germans intended burning the city, a threat they were determined to carry out. Not only had we approached, but we had actually entered the city which was thus saved from destruction. No doubt our rapid advance had frustrated the plans of the Germans, much to the delight of the inhabitants.
Passing through the narrow alleyways of the Bazaar the head of the column reached the French quarter, where it received a great reception. The inhabitants turned out in force, almost blocking the narrow streets, and evidence of their great joy was apparent on all sides. Gifts were showered on the troops as they passed, whilst many of the women and girls shouted greetings and blew kisses from the windows along the route.
The Brigade moved along the Aleppo road to Jobar, at which place a halt was called. After a short spell the advance was continued, the advance Regiment coming in contact with the enemy rear guard in the vicinity of Marista el Basal. The Regiment moved up in support, and the opposition was speedily overcome. At 1 p.m. information was received to the effect that a large enemy force, protected by a strong rearguard, was retreating north east along the main Aleppo road.
"B" and "C" Squadrons were therefore pushed forward to strengthen the flanks of the 10th Light Horse Regiment, and later "A" Squadron was moved up to the left flank. At 2 p.m. Daly, Major TJ, DSO, with the balance of the Regiment also moved up to the left flank and pushed rapidly forward to within one mile of Khan Ayash. At this point touch was gained with "B" Squadron, who were holding a position approximately one mile west of the village, the 10th Light Horse Regiment being astride the main road one and a half miles south-west, and with advanced troops in the village.
The enemy were now moving up the pass leading into the hills north of Kubbet i Asafur, thus securing their retreat. At 6 p.m. the Regiment concentrated on the main road two miles south-west of Khan Ayash, and moved to Khan Kusseir where it bivouacked for the night. Hogan, Lieutenant LR; and, ten other ranks were moved out as a night outpost, being posted on the edge of the olive grove in which the Regiment was bivouacked, with orders to watch the main road.
The following members of the Regiment, who had been taken prisoners at Sasa on the 29th September 1918, were reported to be in the German hospital at Damascus: King, 552 Sergeant AE; Betteridge, 262 Corporal AL; Down, 921 Corporal AC; Clark, 1528 Lance Corporal CB, Hanrahan, 2116 Lance Corporal EP; O'Donnell, 2140 Trooper DV; and, Adams, 702 Corporal HG.
At 6.15 a.m. on the 2nd October 1918, Hogan, Lieutenant LR, Officer in Command outpost, reported that a large force of enemy infantry were moving north, one mile east of his post. Doubt existed as to whether the advancing troops were actually enemy or Sherifian troops, and a mounted patrol of "B" Squadron was rushed out to investigate and report. A message was despatched to Brigade Headquarters reporting the presence of approximately 2,000 infantry, and asking for information.
The Regiment was at breakfast when the report from Hogan, Lieutenant LR, was received, but within ten minutes horses had been saddled and the Regiment paraded ready to move. At 6.30 a.m. a few shots were heard from the direction of the column, and shortly afterwards a galloper from the outpost reported that the column was composed of Turkish infantry.
Orders were at once issued, and the Regiment moved out to the attack, and as the head of the Regiment cleared the olive grove the following message was received from Brigade Headquarters; "Party believed to be Germans; move and investigate at once; 8th Light Horse Regiment with four machine guns will be ready to support, if required."
With "B" Squadron in advance and Sharp, Lieutenant RC; and, his troop of "A" Squadron as right flank guard, the Regiment moved at a rapid pace north-east along the main road for about half a mile, then swung to the left among the vineyards. The rear of the enemy column was now observed about one mile along the road.
By increasing the pace and moving towards the foothills the Regiment rapidly gained on the enemy, who had now mounted several machine guns, and pushed out several small parties to their left flank, in an endeavour to hold up our advance. In spite of the heavy machine gun fire the Regiment pushed forward and reached a favourable position about one mile to the left, and opposite the centre of the enemy column.
Orders were given to "A" Squadron to move rapidly and seize Khan Ayash, and to "C" Squadron to seize the main road in the vicinity of Kubbet i Asafur. "C" Squadron immediately galloped forward, followed by "A" Squadron, under heavy fire, whilst "B" Squadron dismounted and opened a heavy fire on the centre of the enemy column. Regimental Headquarters established themselves near the water channel and gained touch with Brigade Headquarters by heliograph.
The two squadrons who had been sent forward were now seen to be well ahead of the enemy advance guard, and to be swinging in towards the main road to seize the villages, thus cutting off all chances of escape for the enemy. The head of the main body of the enemy seemed to hesitate as if doubtful of its next move, and their leaders appeared to be holding a conference.
As the two squadrons swung round the remainder of the Regiment under orders from Daly, Major TJ, mounted, and with drawn swords, charged the main enemy column, detaching a small party of "B" Squadron to move round the flank. This move had the desired effect; the main body of the enemy promptly hoisting the white flag before the charging troops reached them.
In conjunction with this move, A and "C" Squadrons drew swords and charged the enemy cavalry advance guard. This was the first time the Light Horse, armed as cavalry, had the chance to try conclusions with the Turkish cavalry who were armed with sword and lance, and it was expected that they would put up a fight. The determined front shown by our men must have taken all the heart out of the enemy cavalry, as they surrendered without the slightest show of resistance.
"A" Squadron, moving forward, rushed a machine gun just as it was mounted and ready to open fire, whilst C seized the pass into the hills, and captured two 75 cm. guns near Kubbet i Asafur.
The Regiment collected together the various portions of the enemy force and proceeded to take stock of the bag, which gave the following totals: 91 officers, 318 cavalry, 1,064 infantry, eight German machine gunners, 26 machine guns, one mountain gun [No. F 7524], two 75 cm. [M 15, G.K.N.] guns, twelve automatic rifles, 264 rifles, and 285 animals. This force was captured within one hour of leaving the bivouac at Khan Kusseir, seven miles distant.
Amongst the officers captured was the General who commanded the Turkish Division defending Shunet Nimrin in the Jordan Valley, against our attack in May, 1918. The standard of the 46th Regiment was also captured, and is believed to be the only enemy standard captured during the war. That such a force could be taken in open country in such a short time and with so few casualties, appears astounding, but the fact must not be lost sight of that they had been driven from pillar to post for the past three weeks, with no rest and little food, facts which had, no doubt, taken the heart out of them.
The rapidity of our movements contributed largely to the success of the operations, but great credit is due to both, Charley, Major WT; and, Bleechmore, Major C, for the manner in which they manoeuvred their squadrons, in seizing the pass and main road ahead of the enemy columns. Daly, Major TJ, who conducted the operations, deserves special mention for his quick decisions and plan of operations, in which he was ably seconded by Shaw, Lieutenant OJ, the Adjutant,
In spite of the hard work of the past three weeks, the horses responded bravely to this additional call, and covered the ground in fine style. The ground passed over was devoid of cover and fairly rough, being covered with stones and broken by numerous small wadis.
When the main column surrendered Smyth, 902 Signaller JM; and, Halliday, 1458 Signaller NC, who were moving to the Regimental signalling station, in galloping over a rise were suddenly confronted by a party of the enemy composed of three Germans and 85 Turks, who were taking up a position within a few hundred yards of the signal station. A German officer was mounting a machine gun when Smyth, 902 Signaller JM; and, Halliday, 1458 Signaller NC, with great gallantry, and under a shower of bombs, rushed at the officer and snatched his revolver, which he had hastily drawn, from his hand. With this revolver they fired into the enemy and seized the machine gun, the prompt action so surprising the enemy that they surrendered.
Smyth, 902 Signaller JM; and, Halliday, 1458 Signaller NC, were both awarded the Distinguished Conduct Medal for this gallant act, which prevented the enemy establishing a post from which a destructive fire could have been turned on the rear of the Regiment.
Freebairn, Lieutenant DT, with one troop, escorted the prisoners to Brigade Headquarters, where they were handed over. After collecting the captured war material into one dump, which was placed under a guard, the Regiment returned to bivouac to finish its breakfast, which had been so rudely interrupted. At 2 p.m. "A" Squadron was sent out to reconnoitre the country six miles east of the bivouac for stragglers, returning at 5 p.m. and reporting "all clear."
At 2 p.m. on the 3rd October Freebairn, Lieutenant DT, with a troop of "B" Squadron, moved out and mounted an outpost in the Wadi Maraba to guard the approaches to Damascus from the north. The inhabitants of these parts were very friendly disposed towards our men, bringing baskets of grapes, eggs, etc., into our lines. The country surrounding the bivouac was covered with flourishing vineyards and orchards which were abundantly watered. The grapes were ripe and of exceptionally good quality and flavour, being grown chiefly for drying into raisins.
On the following day "C" Squadron moved out at 9 a.m. to relieve "A" Squadron of the 8th Light Horse Regiment who were holding the pass at Kubbet i Asafur. Hahn, Lieutenant HJ, with a working party, and with A echelon of the transport, collected the captured war material, which filled five wagons. The captured guns were also brought in and sent to Damascus. At 11 a.m. orders were received for the Brigade to move to a point south-west of Damascus, leaving "C" Squadron of the Regiment at Duma to hold the main Aleppo road, and the Wadi Maraba.
At 3 p.m. the Regiment, less "C" Squadron, moved via the main. Aleppo road, through Damascus to a point two and a half miles south-west of El Mezze, where it bivouacked for the night. Four of the men who had been taken prisoner at Sasa on the 29th September 1918 and who had been recaptured on the fall of Damascus, rejoined the Regiment at this bivouac.
Previous: Bert Schramm's Diary, 29 September 1918
Next: Bert Schramm's Diary, 1 October 1918
Sources Used:
Bert Schramm's Diary
National Archives Service File.
Embarkation Roll, AWM8.
Australian War Memorial Roll of Honour
Nominal Roll, AWM133, Nominal Roll of Australian Imperial Force who left Australia for service abroad, 1914-1918 War.
War Diaries and Letters
All War Diaries and letters cited on this site should be read in conjunction with the Australian Light Horse Studies Centre, War Diaries and Letters, Site Transcription Policy which may be accessed at:
Australian Light Horse Studies Centre, War Diaries and Letters, Site Transcription Policy
Bert Schramm Diary, Album
Bert Schramm's Photo Album
9th Australian Light Horse Regiment, AIF
9th Australian Light Horse Regiment, War Diary, Day by Day Account
Citation: Diaries of AIF Servicemen, Bert Schramm, 30 September 1918
Posted by Project Leader at 1:01 AM EADT
Updated: Tuesday, 7 June 2011 7:38 AM EADT
Hotchkiss Portable Machine Gun Handbook - Page 47 Plate 7
Topic: Wp - Hotchkiss PMG
The following weeks will see the various pages from the Hotchkiss Portable Machine Gun Handbook, the official manual issued by the company for the use of troops in the field. The Hotchkiss Gun was introduced in the Light Horse formations during the early months of 1917. The introduction of this robust and portable gun gave the Light Horse Regiments additional mobile fire power which considereably added to their ability to sustain light combat situations and defend against vastly numerically superior forces. Apart from being an excellent weapon, it was in much demand by the Turkish forces who considered the capture of a Hotchkiss Gun well worth any risks involved in the process. This is a manual produced in 1917 and illustrates the method by which the Hotchkiss Gun was packed and moved throughout the Palestine campaign.
Citation: Hotchkiss Portable Machine Gun Handbook - Page 47 Plate 7
Updated: Sunday, 28 September 2008 11:01 PM EADT
Colonel Husnu, Yildirim, Page 85
Topic: Tk - Bks - Yildirim
Another entry from the book written by Lieutenant Colonel Hüseyin Hüsnü Emir, called Yildirim. Every day, one page of the book will be posted. This is Page 85.
Colonel Hüsnü, Yildirim, Page 85.
Citation: Colonel Hüsnü, Yildirim, Page 85
Updated: Thursday, 2 October 2008 10:50 PM EADT
570 Private Francis Darvall Templer
Topic: AIF - 1B - 2 LHR
570 Private Francis Darvall Templer, 2nd Light Horse Regiment, "C" Squadron
Francis Darvall Templer, a brief military biography from The AIF Project:
Francis Darvall TEMPLER
Place of birth Geraldine, South Canterbury, New Zealand
School Boys' High School, Christchurch, New Zealand
Age on arrival in Australia 21
Occupation Farmer
Next of kin Father, Edwd. Templer, Geraldine, South Canterbury, New Zealand
Previous military service Nil
Enlistment date 25 August 1914
Unit name 2nd Light Horse Regiment, C Squadron
AWM Embarkation Roll number 10/7/1
Embarkation details Unit embarked from Brisbane, Queensland, on board HMAT A15 Star Of England on 24 September 1914
Unit from Nominal Roll 2nd Light Horse Regiment
Fate Died of wounds 22 October 1915
Place of death or wounding Gallipoli, Turkey
Commemoration details The Lone Pine Memorial (Panel 2), Gallipoli, Turkey
The Lone Pine Memorial, situated in the Lone Pine Cemetery at Anzac, is the main Australian Memorial on Gallipoli, and one of four memorials to men of the New Zealand Expeditionary Force. Designed by Sir John Burnet, the principal architect of the Gallipoli cemeteries, it is a thick tapering pylon 14.3 metres high on a square base 12.98 metres wide. It is constructed from limestone mined at Ilgardere in Turkey.
The Memorial commemorates the 3268 Australians and 456 New Zealanders who have no known grave and the 960 Australians and 252 New Zealanders who were buried at sea after evacuation through wounds or disease. The names of New Zealanders commemorated are inscribed on stone panels mounted on the south and north sides of the pylon, while those of the Australians are listed on a long wall of panels in front of the pylon and to either side. Names are arranged by unit and rank.
The Memorial stands over the centre of the Turkish trenches and tunnels which were the scene of heavy fighting during the August offensive. Most cemeteries on Gallipoli contain relatively few marked graves, and the majority of Australians killed on Gallipoli are commemorated here.
Roll of Honour Panel number, Roll of Honour,
Australian War Memorial 3
Family/military connections Cousins: a number (surname BARTON) served in the AIF.
War service: Egypt, Gallipoli
Citation: 570 Private Francis Darvall Templer
Updated: Wednesday, 1 October 2008 9:14 PM EADT
9th LHR AIF War Diary, September 30
9th LHR, AIF
9th Light Horse Regiment
War Diary, 30 September
Pro Gloria et Honore - For Glory and Honour
Regimental March - Marching Through Georgia
The following entries are extracted and transcribed from the 9th Light Horse Regiment War Diary, the originals of which are held by the Australian War Memorial. There are 366 entries on this site. Each day has entries as they occurred from 1914 to 1919. In addition to the 9th Light Horse Regiment War Diary, when appropriate, entries from the 3rd Light Horse Brigade War Diary and other regiments with the Brigade will also appear. Entries from the unit history, Darley, TH, With the Ninth Light Horse in the Great War, Adelaide, Hassell Press, 1924 will also appear from time to time. The aim is to give the broadest context to the story and allow the reader to follow the day to day activities of the regiment. If a relative happened to have served in the regiment during the Great War, then this provides a general framework in which the individual story may be told.
The Diary
See 4th Military District, South Australia for militia activities.
9th Light Horse Regiment Location - Rhododendron Hill
9th Light Horse Regiment War Diary - General Birdwood inspected part of the trenches.
The whole hill has been reached with shrapnel fire every day for the last five days, especially over the bivouacs. One shell wounded five men at Regimental Headquarters.
Started to dig trenches for Headquarters and men to camp in.
Twenty men sick in the lines besides an average of three men per day evacuated through sickness.
9th Light Horse Regiment Location - Hod Amara
9th Light Horse Regiment War Diary - Routine work. About 1 hours rifle exercise and marching done in morning. Lewis Gun teams on firing practice.
The following promotions of NCO's published in AIF Egypt Orders No. 5, 27 September 1916.
493 Squadron Sergeant Major Shaw OJ to be Second Lieutenant.
73 Sergeant Sharp, RC to be Second Lieutenant.
366 Squadron Sergeant Major Hogan, LR to be Second Lieutenant.
Also Second Lieutenant Philan, L, to be Lieutenant and Major (Temporary Lieutenant Colonel) WH Scott, DSO to be Lieutenant Colonel.
Captaint Bleechmore, C, reported to the Regiment for duty from the Training Squadron vice Captain Malcolm.
9th Light Horse Regiment Location - Um Urgan
9th Light Horse Regiment War Diary - Church Parade 0700.
Lapthorne, Captain AE, marched in from 2 Australian Station Hospital.
Twenty two donkeys arrived and taken on strength.
0900 Arrived Khan esh Shiha. From this place the first sight of Damascus was obtained. 4,000 enemy were reported in vicinity of Kaukab. At Khan esh Shiha the Division deployed for the final advance on Damascus. 4th Light Horse Brigade on the right, 5th Light Horse Brigade on the left with 3rd Light Horse Brigade immediately in rear. Each Brigade in columns of squadrons in line, a very imposing sight. 1½ miles south west of Kaukab 5th and 3rd Light Horse Brigades turned slightly to the left and advanced rapidly north eastwards along the foot of the ridge on the western side of the orchards south of Damascus. 4th Light Horse Brigade were meeting opposition in country south east of Kaukab. Enemy artillery and machine guns were firing but our batteries soon opened up. Part of the 4th Light Horse Brigade were observed to charge and their advance of that Brigade continued. Meanwhile the 5th and 3rd Light Horse Brigades continued to advance rapidly until about one mile south west of El Mezze was reached. At this place further advance was strongly opposed by the enemy who had mounted machine guns on the outskirts of the village orchards.
1645 "A" Squadron had seized the high ground overlooking Dumar and the Damascus - Beirut road and railway. The only means of entering the village was down a narrow rocky track. "A" Squadron made two attempts to force this route but found it strongly commanded by many enemy machine guns placed in and around the village of Dumar.
This squadron with two machine guns attached then took up a position overlooking village, road and railway. The road was packed with enemy troops and transport. A heavy fire was brought to bear on those and heavy casualties inflicted. Portion of 5th Light Horse Brigade were in position on left of "A" Squadron.
3rd Light Horse Brigade War Diary - At 0200 as the 9th and 10th Light Horse Regiments were making only slow progress, 6th Light Horse Regiment, less two Squadrons was sent in dismounted to storm the enemy position frontally from the road. Cooperation by the 9th and 10th Light Horse Regiments was arranged for as far as darkness time, and the exceedingly rough nature of the ground permitted. By 0200 the 8th Light Horse Regiment had captured the enemy position with five machine guns and a few German prisoners. During the advance, the Regiment was subjected to a heavy rifle and machine gun fire. The enemy beat a hasty retreat towards Damascus, vigorously pursued along the road by the 10th Light Horse Regiment. The advance was again held up temporarily about one mile south of Sasa. The vanguard with two machine guns attached dismounted and rushed the enemy, who then broke and made off towards Sasa in motor lorries, which had been brought up behind their lines. In the course of this pursuit the 10th Light Horse Regiment captured two 77mm field guns, two machine guns, one motor lorry and about 20 prisoners. The Brigade had orders that from dawn onwards the 4th Light Horse Brigade would form the Divisional advance guard, while the 3rd Light Horse Brigade assembled after the action just concluded. Shortly after the 4th Light Horse Brigade took up the pursuit they overtook and captured several hundred fugitives. At 0645 all troops of rhe Brigade had reached Sasa, and at 0730 the Brigade marched following the remainder of the Division. On arrival at Khan esh Shiha, Divisional orders for the approach on Damascus were received. The 5th Light Horse Brigade closely followed by the 3rd Light Horse Brigade were to outflank the town by moving via Katana, north easterly along the foothills of Kalabat el Mezze. Bourchier's force, [two Regiments of the 4th Light Horse Brigade], were to move directly on the town via Daraya. Soon after this movement commenced enemy machine gun fire was heard directed against Bourchier's force from the vicinity El Kaukab. The 19th Brigade, Royal Horse Artillery engaged these machine guns, the 5th and 3rd Light Horse Brigade meantime pressing on to their objective at the trot. When a point half a mile north of Mudhamiye had been reached, troops of Bourchier's force were observed galloping the enemy's position supported by the fire of the Royal Horse Artillery batteries. Away to the east could be seen shrapnel bursting, no doubt; from the artillery of the 14th Brigade of the 5th Cavalry Division sent across to intercept the Turkish third Cavalry division retreating on Damascus. The 5th and 3rd Brigade pressed on, until at a point about 1½ miles south west of El Mezze the French Cavalry Regiment which was leading was held up by machine gun fire from the garden west of the southern end of the town. The Royal Horse Artillery batteries were brought up and engaged these, machine guns - the 3rd Light Horse Brigade remaining halted ready to support the 5th Light Horse Brigade when and where required. The enemy machine guns concealed in the gardens were difficult to locate and swept the open ground over which any direct advance would have to be made. About 1530 orders were received that the 5th Light Horse Brigade were to turn into the hills on their left and cut the road and railway leading north west to Beirut along which the main line of retreat of enemy troops to Damascus lay, while the 3rd Light Horse Brigade, were to make their way to the north east road leading to Homs and Aleppo and block that line of retreat. The Brigade at once moved off, 9th Light Horse Regiment and six machine guns forming the advance guard. After a short advance over rough hilly country the Brigade reached a point about one mile south west of the village of Dumar.
Reconnaissances soon showed that the nature of the terrain was such that an advance across country over Jebel Kasiun was impossible. The only alternative was the main road from Dumar through Er Rabue and then through the northern end of Damascus itself. In preparation of this the leading squadron of the 9th Light Horse Regiment and four machine guns took up a position on the high ground immediately south west of Dumar. Large bodies of the enemy were seen to be retreating along the road from Damascus to Beirut. They were in a closely formed column of infantry, transport and guns. This column was caught at effective range by the fire of our rifles and machine guns. Those who had passed before our occupation of the high ground commanding the road above Dumar were caught by the fire of the 5th Light Horse Brigade further to the west, while still further west again "A" Squadron of the 8th Light Horse Regiment was also in position commanding road and railway. It is estimated that at least 700 casualties were inflicted on the enemy in this gorge of the Barada, in addition hundreds of animals were killed; horses, cattle, donkeys, sheep and dogs. The remainder of the column lost heart and returned back to Damascus and no doubt formed the bulk of the 12,000 prisoners which were collected there next morning. The Beirut road was thus closed at sunset on 30th September 1918. A visual station had been sent out to get communication with Division and through it orders were now received for the Brigade to bivouac in its present position for the night and march for the Homs road at 0500 the next day in pursuit of enemy retreating to the north east. Loud explosions were heard in Damascus and the flames of burning stores lit up the skies throughout the night.
9th Light Horse Regiment Location - Adelaide
9th Light Horse Regiment War Diary - Regiment disbanded.
Previous: 9th LHR AIF War Diary, 29 September
Next: 9th LHR AIF War Diary, 1 October
See: 9th Australian Light Horse Regiment, Contents
Australian Light Horse Studies Centre, AIF War Diaries of the Great War, Site Transcription Policy
9th Light Horse Regiment AIF
9th Australian Light Horse Regiment, Roll of Honour
Citation: 9th LHR AIF War Diary, 30 September
Updated: Thursday, 16 September 2010 11:13 AM EADT


Hi, im doing a little game "like" Mario Galaxy and im trying to put my camera on a constant distance between the player and the world.
But if I move the camera to 10 units from player (thats the distance value) and later i move the camera to 30 units from world (distance + world radius) then the camera stops being 10 units from the player.
When the player walks, you can see how the world shakes and I think that shaking is the result of the variable distance between the camera and the player.
I'm doing the player's movements in the Update and the camera's movements in the LateUpdate, Is this correct?


| General Discussion (Anxiety Free Zone) | Pets | Topic: Meet Stepan the Bear 0 Members and 1 Guest are viewing this topic.
Well hello Stepan. Aren't you so Big & Lovable.
He's like a big goofy family dog. And sits at the table having tea and crumpets no less LOL.
Love is love...he seems so sweet in the pics.