Skip to content

Commit

Permalink
Simplified target generation
Browse files Browse the repository at this point in the history
Removed internal partial register information. Now each register must be declared at least once with an explicit type
  • Loading branch information
RealA10N committed Feb 7, 2025
1 parent c67b0bc commit d1a5a45
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 186 deletions.
2 changes: 1 addition & 1 deletion gen/argument_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type ArgumentInfo interface {
GetType() *ReferencedTypeInfo

// The location where the argument appears in the source code.
Declaration() core.UnmanagedSourceView
Declaration() *core.UnmanagedSourceView

// Returns the argument string, as it should appear in the code code.
String() string
Expand Down
4 changes: 2 additions & 2 deletions gen/immediate_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ func (i *ImmediateInfo) GetType() *ReferencedTypeInfo {
return &i.Type
}

func (i *ImmediateInfo) Declaration() core.UnmanagedSourceView {
return i.declaration
func (i *ImmediateInfo) Declaration() *core.UnmanagedSourceView {
return &i.declaration
}

func (i *ImmediateInfo) String() string {
Expand Down
172 changes: 33 additions & 139 deletions gen/instruction_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

type InstructionGenerator struct {
ArgumentGenerator InstructionContextGenerator[parse.ArgumentNode, ArgumentInfo]
TargetGenerator InstructionContextGenerator[parse.TargetNode, registerPartialInfo]
TargetGenerator InstructionContextGenerator[parse.TargetNode, *RegisterInfo]
}

func NewInstructionGenerator() FunctionContextGenerator[
Expand Down Expand Up @@ -45,23 +45,44 @@ func (g *InstructionGenerator) generateArguments(
return arguments, results
}

func (g *InstructionGenerator) generatePartialTargetsInfo(
func (g *InstructionGenerator) generateTargets(
ctx *InstructionGenerationContext,
node parse.InstructionNode,
) ([]registerPartialInfo, core.ResultList) {
targets := make([]registerPartialInfo, len(node.Targets))
) ([]*RegisterArgumentInfo, core.ResultList) {
targets := make([]*RegisterArgumentInfo, len(node.Targets))
results := core.ResultList{}

// Different targets should not effect one another.
// Thus, we just collect all of the errors along the way, and return
// them in one chunk.
for i, target := range node.Targets {
typeInfo, curResults := g.TargetGenerator.Generate(ctx, target)
v := target.View()
registerInfo, curResults := g.TargetGenerator.Generate(ctx, target)
results.Extend(&curResults)
targets[i] = typeInfo

if registerInfo == nil {
// TODO: improve error message
results.Append(core.Result{
{
Type: core.ErrorResult,
Message: "Undefined or untyped register",
Location: &v,
},
{
Type: core.HintResult,
Message: "A register must be defined with an explicit type at least once",
},
})
}

targets[i] = &RegisterArgumentInfo{
Register: registerInfo,
declaration: &v,
}
}

return targets, results
if !results.IsEmpty() {
return nil, results
}

return targets, core.ResultList{}
}

func (g *InstructionGenerator) generateLabels(
Expand All @@ -87,115 +108,6 @@ func (g *InstructionGenerator) generateLabels(
return labels, core.ResultList{}
}

func partialTargetsToTypes(targets []registerPartialInfo) []*ReferencedTypeInfo {
types := make([]*ReferencedTypeInfo, len(targets))
for i, target := range targets {
types[i] = target.Type
}
return types
}

func argumentsToTypes(arguments []ArgumentInfo) []*ReferencedTypeInfo {
types := make([]*ReferencedTypeInfo, len(arguments))
for i, arg := range arguments {
types[i] = arg.GetType()
}
return types
}

func (g *InstructionGenerator) getTargetRegister(
ctx *InstructionGenerationContext,
node parse.TargetNode,
targetType ReferencedTypeInfo,
) (*RegisterInfo, core.ResultList) {
registerName := nodeToSourceString(ctx.FileGenerationContext, node.Register)
registerInfo := ctx.Registers.GetRegister(registerName)
nodeView := node.View()

if registerInfo == nil {
// register is defined here; we should create the register and define
// it's type.
newRegisterInfo := &RegisterInfo{
Name: registerName,
Type: targetType,
Declaration: nodeView,
}

return newRegisterInfo, ctx.Registers.NewRegister(newRegisterInfo)
}

// register is already defined
if !registerInfo.Type.Equal(targetType) {
// notest: sanity check only
return nil, list.FromSingle(core.Result{{
Type: core.InternalErrorResult,
Message: "Internal register type mismatch",
Location: &nodeView,
}})
}

return registerInfo, core.ResultList{}
}

// Registers can be defined by being a target of an instruction.
// After we have determined 100% of the instruction targets types (either
// if they were explicitly declared or not), we call this function with the
// target types, and here we iterate over all target types and define missing
// registers.
//
// This also returns the full list of register targets for the provided
// instruction.
func (g *InstructionGenerator) defineAndGetTargetRegisters(
ctx *InstructionGenerationContext,
node parse.InstructionNode,
targetTypes []ReferencedTypeInfo,
) ([]*RegisterArgumentInfo, core.ResultList) {
if len(node.Targets) != len(targetTypes) {
// notest: sanity check: ensure lengths match.
v := node.View()
return nil, list.FromSingle(core.Result{{
Type: core.InternalErrorResult,
Message: "Targets length mismatch",
Location: &v,
}})
}

registers := make([]*RegisterArgumentInfo, len(node.Targets))
results := core.ResultList{}
for i, target := range node.Targets {
// register errors should not effect one another, so we collect them.
registerInfo, curResults := g.getTargetRegister(
ctx,
target,
targetTypes[i],
)

if !results.IsEmpty() {
results.Extend(&curResults)
}

if registerInfo == nil {
// notest: sanity check, should not happen.
v := target.View()
results.Append(core.Result{{
Type: core.InternalErrorResult,
Message: "Unexpected nil register",
Location: &v,
}})
}

registerArgument := &RegisterArgumentInfo{
Register: registerInfo,
declaration: node.View(),
}

registerInfo.AddDefinition(ctx.InstructionInfo)
registers[i] = registerArgument
}

return registers, results
}

// Convert an instruction parsed node into an instruction that is in the
// instruction set.
// If new registers are defined in the instruction (by assigning values to
Expand All @@ -209,8 +121,6 @@ func (g *InstructionGenerator) Generate(
// and processing the targets and arguments. We accumulate the results,
// since those processes do not effect each other.

// TODO: tidy this mess.

v := node.View()
instCtx := InstructionGenerationContext{
FunctionGenerationContext: ctx,
Expand All @@ -223,7 +133,7 @@ func (g *InstructionGenerator) Generate(
arguments, curResults := g.generateArguments(&instCtx, node)
results.Extend(&curResults)

partialTargets, curResults := g.generatePartialTargetsInfo(&instCtx, node)
targets, curResults := g.generateTargets(&instCtx, node)
results.Extend(&curResults)

labels, curResults := g.generateLabels(&instCtx, node)
Expand All @@ -235,24 +145,8 @@ func (g *InstructionGenerator) Generate(
}

instCtx.InstructionInfo.Arguments = arguments
instCtx.InstructionInfo.Labels = labels

explicitTargetTypes := partialTargetsToTypes(partialTargets)
argumentTypes := argumentsToTypes(arguments)
targetTypes, results := instDef.InferTargetTypes(ctx, explicitTargetTypes, argumentTypes)
// TODO: validate that the returned target types matches expected constraints.

if !results.IsEmpty() {
return nil, results
}

targets, results := g.defineAndGetTargetRegisters(&instCtx, node, targetTypes)

if !results.IsEmpty() {
return nil, results
}

instCtx.InstructionInfo.Targets = targets
instCtx.InstructionInfo.Labels = labels

instruction, results := instDef.BuildInstruction(instCtx.InstructionInfo)
if !results.IsEmpty() {
Expand Down
11 changes: 6 additions & 5 deletions gen/label_argument.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ import (
type LabelArgumentInfo struct {
Label *LabelInfo

// TODO: make this not required.
declaration core.UnmanagedSourceView
declaration *core.UnmanagedSourceView
}

func NewLabelArgumentInfo(
label *LabelInfo,
) *LabelArgumentInfo {
return &LabelArgumentInfo{
Label: label,
Label: label,
declaration: nil,
}
}

func (i *LabelArgumentInfo) GetType() *ReferencedTypeInfo {
return nil // Label argument does not have a type
}

func (i *LabelArgumentInfo) Declaration() core.UnmanagedSourceView {
func (i *LabelArgumentInfo) Declaration() *core.UnmanagedSourceView {
return i.declaration
}

Expand Down Expand Up @@ -63,9 +63,10 @@ func (g *LabelArgumentGenerator) Generate(
})
}

v := node.View()
argument := &LabelArgumentInfo{
Label: labelInfo,
declaration: node.View(),
declaration: &v,
}

return argument, core.ResultList{}
Expand Down
15 changes: 0 additions & 15 deletions gen/regisrer_partial_info.go

This file was deleted.

10 changes: 4 additions & 6 deletions gen/register_argument.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import (
type RegisterArgumentInfo struct {
Register *RegisterInfo

// TODO: make this not required, for generated arguments, for example after
// SSA construction (phi register arguments which do not appear in the
// source code).
declaration core.UnmanagedSourceView
declaration *core.UnmanagedSourceView
}

func NewRegisterArgument(register *RegisterInfo) RegisterArgumentInfo {
Expand All @@ -30,7 +27,7 @@ func (i *RegisterArgumentInfo) GetType() *ReferencedTypeInfo {
return &i.Register.Type
}

func (i *RegisterArgumentInfo) Declaration() core.UnmanagedSourceView {
func (i *RegisterArgumentInfo) Declaration() *core.UnmanagedSourceView {
return i.declaration
}

Expand Down Expand Up @@ -64,9 +61,10 @@ func (g *RegisterArgumentGenerator) Generate(
return nil, results
}

v := node.View()
argument := RegisterArgumentInfo{
Register: register,
declaration: node.View(),
declaration: &v,
}

register.AddUsage(ctx.InstructionInfo)
Expand Down
8 changes: 0 additions & 8 deletions gen/register_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,3 @@ func (i *RegisterInfo) AddDefinition(info *InstructionInfo) {
func (i *RegisterInfo) AddUsage(info *InstructionInfo) {
i.Usages = append(i.Usages, info)
}

func (i *RegisterInfo) toPartialRegisterInfo() registerPartialInfo {
return registerPartialInfo{
Name: i.Name,
Type: &i.Type,
Declaration: i.Declaration,
}
}
8 changes: 4 additions & 4 deletions usm64/core/emulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (ctx *EmulationContext) ArgumentToValue(
return 0, list.FromSingle(core.Result{{
Type: core.InternalErrorResult,
Message: "Undefined register",
Location: &v,
Location: v,
}})
}

Expand All @@ -59,7 +59,7 @@ func (ctx *EmulationContext) ArgumentToValue(
return 0, list.FromSingle(core.Result{{
Type: core.ErrorResult,
Message: "Immediate overflows 64 bits",
Location: &v,
Location: v,
}})
}

Expand All @@ -70,15 +70,15 @@ func (ctx *EmulationContext) ArgumentToValue(
return 0, list.FromSingle(core.Result{{
Type: core.ErrorResult,
Message: "Expected valued argument",
Location: &v,
Location: v,
}})

default:
v := argument.Declaration()
return 0, list.FromSingle(core.Result{{
Type: core.InternalErrorResult,
Message: "Unexpected argument type",
Location: &v,
Location: v,
}})
}
}
Expand Down
Loading

0 comments on commit d1a5a45

Please sign in to comment.