Skip to content

Commit

Permalink
Clean up commandline implementation, add additional options for debug…
Browse files Browse the repository at this point in the history
…ging and various correctness and matching fixes
  • Loading branch information
tge-was-taken committed Dec 8, 2024
1 parent b2da7e9 commit 73ee27a
Show file tree
Hide file tree
Showing 10 changed files with 594 additions and 328 deletions.
550 changes: 358 additions & 192 deletions Source/AtlusScriptCompiler/Program.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ public FlowScriptBinary Build()

if (mMatching)
{
// add return instruction at end
mTextSection.Add(new BinaryInstruction() { Opcode = Opcode.END });

// apply string section padding
if (mFormatVersion == BinaryFormatVersion.Version1)
{
// add return instruction at end
mTextSection.Add(new BinaryInstruction() { Opcode = Opcode.END });

// apply string section padding
while (mStringSection.Count < 0xF0)
mStringSection.Add(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1395,8 +1395,12 @@ private bool TryEmitProcedureBody(ProcedureDeclaration declaration)

ReturnStatement returnStatement = new ReturnStatement();

var hasOutParameters = declaration.Parameters
.Where(x => x.Modifier == ParameterModifier.Out)
.Any();

// Remove last return statement
if (declaration.Body.Statements.Count != 0 && declaration.Body.Statements.Last() is ReturnStatement)
if (hasOutParameters && declaration.Body.Statements.Count != 0 && declaration.Body.Statements.Last() is ReturnStatement)
{
returnStatement = (ReturnStatement)declaration.Body.Last();
declaration.Body.Statements.Remove(returnStatement);
Expand All @@ -1416,6 +1420,9 @@ private bool TryEmitProcedureBody(ProcedureDeclaration declaration)
var intVariableCount = 0;
var floatVariableCount = 0;

// TODO: fix bug where out parameters are not assigned during early returns
// early returns must jump to an end label that leads to the epilog of the function

foreach (var parameter in declaration.Parameters)
{
Scope.TryGetVariable(parameter.Identifier.Text, out var variable);
Expand Down Expand Up @@ -1562,7 +1569,7 @@ private bool TryRegisterLabels(CompoundStatement body)
{
if (declaration.DeclarationType == DeclarationType.Label)
{
mLabels[declaration.Identifier.Text] = CreateLabel(declaration.Identifier.Text);
mLabels[declaration.Identifier.Text] = CreateLabel(declaration.Identifier.Text, false);
}
}

Expand Down Expand Up @@ -3770,12 +3777,9 @@ private void EmitPushFloatLiteral(FloatLiteral floatLiteral)
// so if our literal is negative, we make it positive
// and later negative it using the negation operator
var value = floatLiteral.Value;
var isNegative = false;
if (value < 0)
{
isNegative = true;
value = -value;
}
var isNegative = BitConverter.DoubleToInt64Bits((double)value) < 0; // double.IsNegative
if (isNegative)
value = Math.Abs(value);

Emit(Instruction.PUSHF(value));
if (isNegative)
Expand All @@ -3801,6 +3805,30 @@ private bool TryEmitIfStatement(IfStatement ifStatement)
{
Trace(ifStatement, $"Emitting if statement: '{ifStatement}'");

// Detect & translate an if statement that directly maps to the if statement instruction
if (ifStatement.Condition is LogicalNotOperator &&
ifStatement.Body.Statements.Count == 1 &&
ifStatement.Body.Statements[0] is GotoStatement &&
((GotoStatement)ifStatement.Body.Statements[0]).Label is Identifier)
{
// emit condition expression, which should push a boolean value to the stack
var gotoStatement = ifStatement.Body.Statements[0] as GotoStatement;
var labelName = (gotoStatement.Label as Identifier)?.Text;
var cond = ifStatement.Condition as LogicalNotOperator;
if (!TryEmitExpression(cond.Operand, false))
{
Error(ifStatement.Condition, "Failed to emit if statement condition");
return false;
}

if (!mLabels.TryGetValue(labelName, out var label))
return false;

Emit(Instruction.IF(label.Index));
return true;
}


// emit condition expression, which should push a boolean value to the stack
if (!TryEmitExpression(ifStatement.Condition, false))
{
Expand Down Expand Up @@ -4584,11 +4612,38 @@ private void EmitUnchecked(Instruction instruction)
mInstructions.Add(instruction);
}

private LabelInfo CreateLabel(string name)
private LabelInfo CreateLabel(string name, bool isGenerated = true)
{
string GenerateUniqueLabelName(string baseName)
{
while (true)
{
string name;
if (false && Matching)
{
name = $"_{mNextLabelIndex++}";
}
else
{
name = baseName + "_" + mNextLabelIndex++;
}
if (!mLabels.ContainsKey(name))
return name;
}
}

var label = new LabelInfo();
label.Index = (ushort)mLabels.Count;
label.Name = name + "_" + mNextLabelIndex++;

// HACK: reuse original labels when recompiling
if (!isGenerated && name.StartsWith("_") && !mLabels.ContainsKey(name))
{
label.Name = name;
}
else
{
label.Name = GenerateUniqueLabelName(name);
}

mLabels.Add(label.Name, label);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,11 @@ private bool TryParseFunctionDeclaration(FlowScriptParser.FunctionDeclarationSta
if (!TryGet(context, "Expected function index", context.IntLiteral, out var indexNode))
return false;

UIntLiteral indexIntLiteral = null;
if (!TryFunc(indexNode, "Failed to parse function index", () => TryParseUIntLiteral(indexNode, out indexIntLiteral)))
IIntLiteral indexIntLiteral = null;
if (!TryFunc(indexNode, "Failed to parse function index", () => TryParseIntLiteral(indexNode, out indexIntLiteral)))
return false;

functionDeclaration.Index = indexIntLiteral;
functionDeclaration.Index = (uint)indexIntLiteral.Value;
}

// Parse identifier
Expand Down Expand Up @@ -584,7 +584,7 @@ private bool TryParseVariableDeclaration(FlowScriptParser.VariableDeclarationSta
{
// Parse size
var sizeLiteral = context.arraySignifier().IntLiteral();
if (!(sizeLiteral != null && TryParseUIntLiteral(sizeLiteral, out var size)))
if (!(sizeLiteral != null && TryParseIntLiteral(sizeLiteral, out var size)))
{
var arrayInitializer = variableDeclaration.Initializer as InitializerList;
if (arrayInitializer == null)
Expand All @@ -593,10 +593,10 @@ private bool TryParseVariableDeclaration(FlowScriptParser.VariableDeclarationSta
return false;
}

size = (uint)arrayInitializer.Expressions.Count;
size = new UIntLiteral((uint)arrayInitializer.Expressions.Count);
}

((ArrayVariableDeclaration)variableDeclaration).Size = size;
((ArrayVariableDeclaration)variableDeclaration).Size = (uint)size.Value;
}

LogTrace($"Done parsing variable declaration: {variableDeclaration}");
Expand Down Expand Up @@ -635,6 +635,11 @@ private bool TryParseVariableModifier(FlowScriptParser.VariableModifierContext c
modifier = CreateAstNode<VariableModifier>(countNode);
modifier.Kind = VariableModifierKind.Count;
}
else if (TryGet(context, context.Local, out var localNode))
{
modifier = CreateAstNode<VariableModifier>(localNode);
modifier.Kind = VariableModifierKind.Local;
}
else
{
LogError(context, "Invalid variable modifier");
Expand All @@ -653,13 +658,13 @@ private bool TryParseVariableModifierIndex(FlowScriptParser.VariableModifierCont
{
if (TryGet(context, context.IntLiteral, out var indexNode))
{
if (!TryParseUIntLiteral(indexNode, out var index))
if (!TryParseIntLiteral(indexNode, out var index))
{
LogError(indexNode.Symbol, "Invalid variable index");
return false;
}

modifier.Index = index;
modifier.Index = (uint)index.Value;
}

return true;
Expand Down Expand Up @@ -1398,7 +1403,7 @@ private bool TryParseLiteral(FlowScriptParser.ConstantContext context, out Expre
if (!TryParseIntLiteral(intLiteralContext, out var intLiteral))
return false;

expression = intLiteral;
expression = (Expression)intLiteral;
}
else if (TryGet(context, context.FloatLiteral, out var floatLiteralContext))
{
Expand Down Expand Up @@ -1438,13 +1443,13 @@ private bool TryParseBoolLiteral(ITerminalNode node, out BoolLiteral literal)
return true;
}

private bool TryParseIntLiteral(ITerminalNode node, out IntLiteral literal)
private bool TryParseIntLiteral(ITerminalNode node, out IIntLiteral literal)
{
literal = CreateAstNode<IntLiteral>(node);

int value = 0;
literal = default;
long value = 0;
int sign = 1;
string intString = node.Symbol.Text;

if (intString.StartsWith("-"))
{
sign = -1;
Expand All @@ -1458,56 +1463,37 @@ private bool TryParseIntLiteral(ITerminalNode node, out IntLiteral literal)

if (intString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
// hex number
if (!int.TryParse(intString.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value))
// Hexadecimal number
if (!long.TryParse(intString.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value))
{
LogError(node.Symbol, "Invalid hexidecimal integer value");
LogError(node.Symbol, "Invalid hexadecimal integer value");
return false;
}
}
else
{
// assume decimal
if (!int.TryParse(intString, out value))
// Assume decimal
if (!long.TryParse(intString, out value))
{
LogError(node.Symbol, "Invalid decimal integer value");
return false;
}
}

literal.Value = value * sign;

return true;
}

private bool TryParseUIntLiteral(ITerminalNode node, out UIntLiteral literal)
{
literal = CreateAstNode<UIntLiteral>(node);

uint value = 0;
string intString = node.Symbol.Text;

if (intString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
var parsedValue = value * sign;
if (parsedValue < 0)
{
// hex number
if (!uint.TryParse(intString.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value))
{
LogError(node.Symbol, "Invalid hexidecimal integer value");
return false;
}
var temp = CreateAstNode<IntLiteral>(node);
temp.Value = (int)parsedValue;
literal = temp;
}
else
{
// assume decimal
if (!uint.TryParse(intString, out value))
{
LogError(node.Symbol, "Invalid decimal integer value");
return false;
}
var temp = CreateAstNode<UIntLiteral>(node);
temp.Value = (uint)parsedValue;
literal = temp;
}

literal.Value = value;

return true;
}

Expand Down Expand Up @@ -1610,13 +1596,13 @@ private bool TryParseParameter(FlowScriptParser.ParameterContext context, out Pa
else
{
var sizeLiteral = context.arraySignifier().IntLiteral();
if (!(sizeLiteral != null && TryParseUIntLiteral(sizeLiteral, out var size)))
if (!(sizeLiteral != null && TryParseIntLiteral(sizeLiteral, out var size)))
{
LogError(context, "Array parameter must have array size specified");
return false;
}

((ArrayParameter)parameter).Size = size;
((ArrayParameter)parameter).Size = (uint)size.Value;
}

LogTrace($"Parsed parameter: {parameter}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public override void Visit(FunctionDeclaration functionDeclaration)

public override void Visit(VariableDeclaration variableDeclaration)
{
if (variableDeclaration.Modifier.Kind != VariableModifierKind.Local)
if (variableDeclaration.Modifier is not null)
{
Write(KeywordDictionary.ModifierTypeToKeyword[variableDeclaration.Modifier.Kind]);
if (variableDeclaration.Modifier.Index != null)
Expand All @@ -221,19 +221,13 @@ public override void Visit(VariableDeclaration variableDeclaration)
WriteUnsignedIntegerLiteral(variableDeclaration.Modifier.Index);
WriteCloseParenthesis();
}

Write(" ");
Visit(variableDeclaration.Type);
Write(" ");
Visit(variableDeclaration.Identifier);
}
else
{
Visit(variableDeclaration.Type);
Write(" ");
Visit(variableDeclaration.Identifier);
}

Visit(variableDeclaration.Type);
Write(" ");
Visit(variableDeclaration.Identifier);

if (variableDeclaration.Initializer != null)
{
Write(" = ");
Expand Down
Loading

0 comments on commit 73ee27a

Please sign in to comment.