Beispiel #1
0
// SetAlias creates a type alias between the given name and type.
func (ctx *Context) SetAlias(name string, typ Type) error {
	if _, ok := ctx.structs[name]; ok {
		return fmt.Errorf("redefinition of identified structure %q as type alias (%q)", enc.Local(name), typ)
	}
	if old, ok := ctx.alias[name]; ok {
		return fmt.Errorf("redefinition of type alias %q; old mapping %q, new mapping %q", enc.Local(name), old, typ)
	}
	ctx.alias[name] = typ
	return nil
}
Beispiel #2
0
// String returns the string representation of the instruction.
func (term *Br) String() string {
	cond := term.Cond()
	trueBranch, falseBranch := term.TrueBranch(), term.FalseBranch()
	// TODO: Make use of ValueString rather than enc.Local for trueBranch and
	// falseBranch.
	return fmt.Sprintf("br %s %s, label %s, label %s", cond.Type(), cond.ValueString(), enc.Local(trueBranch.Name()), enc.Local(falseBranch.Name()))
}
Beispiel #3
0
func TestLocal(t *testing.T) {
	golden := []struct {
		s    string
		want string
	}{
		// i=0
		{s: "foo", want: "%foo"},
		// i=1
		{s: "a b", want: `%a\20b`},
		// i=2
		{s: "$a", want: "%$a"},
		// i=3
		{s: "-a", want: "%-a"},
		// i=4
		{s: ".a", want: "%.a"},
		// i=5
		{s: "_a", want: "%_a"},
		// i=6
		{s: "#a", want: `%\23a`},
		// i=7
		{s: "a b#c", want: `%a\20b\23c`},
		// i=8
		{s: "2", want: "%2"},
		// i=9
		{s: "foo世bar", want: `%foo\E4\B8\96bar`},
	}

	for i, g := range golden {
		got := enc.Local(g.s)
		if got != g.want {
			t.Errorf("i=%d: name mismatch; expected %q, got %q", i, g.want, got)
		}
	}
}
Beispiel #4
0
// assignIDs assigns unique IDs to unnamed basic blocks and local variable
// definitions.
func (block *BasicBlock) assignIDs() error {
	f := block.Parent()

	// Named represents a named basic block or local variable definition.
	type Named interface {
		Name() string
		SetName(name string)
	}

	// setName assigns unique local IDs to unnamed basic blocks and local
	// variable definitions.
	setName := func(n Named) error {
		// TODO: Ensure that global variables cannot be mixed up with local
		// variables. This should be easy, as global variables may not be unnamed.
		// Check that global variables are always given a name during creation.
		if name := n.Name(); len(name) == 0 {
			n.SetName(f.nextID())
		} else if isLocalID(name) {
			// Validate that explicitly named local IDs conform to the localID
			// counter and update the localID counter to keep explicitly and
			// implicitly named local IDs in sync.
			if want := f.nextID(); name != want {
				return errutil.Newf("invalid local ID; expected %s, got %s", enc.Local(want), enc.Local(name))
			}
		}
		return nil
	}

	// Assign unique local IDs to unnamed basic blocks.
	if err := setName(block); err != nil {
		return errutil.Err(err)
	}

	// Assign unique local IDs to unnamed local variable definitions.
	for _, inst := range block.Insts() {
		if def, ok := inst.(*instruction.LocalVarDef); ok {
			if !types.IsVoid(def.ValInst().RetType()) {
				if err := setName(def); err != nil {
					return errutil.Err(err)
				}
			}
		}
	}

	return nil
}
Beispiel #5
0
// Validate validates the type context by verifying that all identified
// structures have been assigned bodies.
func (ctx *Context) Validate() error {
	for _, t := range ctx.structs {
		if t.typ == nil {
			return fmt.Errorf("empty body of identified structure %q", enc.Local(t.Name()))
		}
	}
	return nil
}
Beispiel #6
0
// String returns a string representation of the module.
func (m *Module) String() string {
	// Data layout; e.g.
	//    target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
	buf := new(bytes.Buffer)
	if len(m.Layout) > 0 {
		fmt.Fprintf(buf, "target datalayout = %q\n", m.Layout)
	}

	// Target triple; e.g.
	//    target triple = "x86_64-unknown-linux-gnu"
	if len(m.Triple) > 0 {
		fmt.Fprintf(buf, "target triple = %q\n", m.Triple)
	}

	// Type definitions; e.g.
	//    %foo = type {i32}
	for _, typ := range m.Types {
		fmt.Fprintf(buf, "%v = type %v\n", enc.Local(typ.Name()), typ.Struct())
	}

	// Global variables; e.g.
	//    @x = global i32 42
	for _, global := range m.Globals {
		fmt.Fprintln(buf, global)
	}

	// Function declarations; e.g.
	//    declare i32 @printf(i8*, ...)
	//
	// Function definitions; e.g.
	//    define i32 @main() {
	//       ret i32 42
	//    }
	for _, f := range m.Funcs {
		fmt.Fprintln(buf, f)
	}

	// TODO: Print named metadata.
	// TODO: Print metadata.

	return buf.String()
}
Beispiel #7
0
// String returns the string representation of the instruction.
func (term *Jmp) String() string {
	return fmt.Sprintf("br label %s", enc.Local(term.target.Name()))
}
Beispiel #8
0
func BenchmarkLocalReplace(b *testing.B) {
	for i := 0; i < b.N; i++ {
		enc.Local("$foo bar#baz")
	}
}
Beispiel #9
0
// ValueString returns a string representation of the value.
func (block *BasicBlock) ValueString() string {
	return enc.Local(block.Name())
}
Beispiel #10
0
// ValueString returns a string representation of the value.
func (t *Param) ValueString() string {
	return enc.Local(t.Name())
}
Beispiel #11
0
// String returns a string representation of the function parameter type.
func (t *Param) String() string {
	if len(t.name) > 0 {
		return fmt.Sprintf("%v %v", t.typ, enc.Local(t.name))
	}
	return t.typ.String()
}
Beispiel #12
0
// Struct returns the identified structure of the given name. If no such
// structure exists, a new identified structure is created. To enable recursive
// and forward references, identified structures are initially created without
// bodies. It is the caller's responsibility to populate the body of the
// identified structure.
func (ctx *Context) Struct(name string) (*NamedStruct, error) {
	if old, ok := ctx.alias[name]; ok {
		return nil, fmt.Errorf("redefinition of type alias %q (%q) as identified structure", enc.Local(name), old)
	}
	t, ok := ctx.structs[name]
	if !ok {
		t = &NamedStruct{name: name}
		ctx.structs[name] = t
	}
	return t, nil
}
Beispiel #13
0
// String returns a string representation of the identified structure type.
//
// As identified structure types may include recursive references, they are
// always printed by their type names.
func (t *NamedStruct) String() string {
	// e.g. "%regset"
	return enc.Local(t.Name())
}
Beispiel #14
0
// SetStruct sets the underlying structure type definition of the identified
// structure.
func (t *NamedStruct) SetStruct(typ *Struct) error {
	if typ == nil {
		t.typ = typ
	} else if !t.typ.Equal(typ) {
		return fmt.Errorf("redefinition of identified structure %q; old definition %v, new definition %v", enc.Local(t.Name()), t.typ, typ)
	}
	return nil
}
Beispiel #15
0
// ValueString returns a string representation of the value.
func (def *LocalVarDef) ValueString() string {
	return enc.Local(def.Name())
}