Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify tmp registers #1010

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open

Conversation

ushirask
Copy link
Contributor

@ushirask ushirask commented May 9, 2022

Purpose

Verify register kinds in BIR
Part of #995

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

@ushirask ushirask requested a review from jclark as a code owner May 9, 2022 05:37
@@ -10,12 +10,15 @@ class VerifyContext {
private final Module mod;
private final t:Context tc;
private final FunctionDefn defn;
final FunctionCode code;
boolean[] tmpRegisterUsed = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tmpRegisterUsed looks like it's final too.

I suggest you make both of them private, and then add methods to VerifyContext to encapsulate how you use them.

Copy link
Contributor Author

@ushirask ushirask May 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make tmpRegisterUsed final since we modify the boolean values?

|DecimalArithmeticBinaryInsn|CompareInsn|ListConstructInsn|ListGetInsn|MappingConstructInsn
|MappingGetInsn|StringConcatInsn|EqualityInsn;

type ResultInsn IntArithmeticBinaryInsn|IntNoPanicArithmeticBinaryInsn|IntBitwiseBinaryInsn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be simpler to do something like readonly & record { *ResultInsnBase; readonly ... } (if jBallerina accepts it)

@@ -10,6 +10,7 @@ class VerifyContext {
private final Module mod;
private final t:Context tc;
private final FunctionDefn defn;
private final boolean[] tmpRegisterUsed = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just pass it as a param and not make VC stateful.

Comment on lines 155 to 161
Register narrowed = r.underlying;
while narrowed is NarrowRegister {
narrowed = narrowed.underlying;
}
if !t:isSubtype(vc.typeContext(), r.semType, narrowed.semType) {
return vc.invalidErr("narrow register is not a subtype of narrowed register", <Position>r.pos);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to check the every time we read form a NarrowRegister, just checking when we first narrow (ie: TypeMerge/TypeBr) is enough. That overlaps with my work.

type ResultInsn readonly & record { *ResultInsnBase; };

function verifyInsnRegisterKinds(VerifyContext vc, Insn insn) returns Error? {
if insn is ResultInsn {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use if insn is ResultInsnBase { instead?


function verifyInsnRegisterKinds(VerifyContext vc, Insn insn) returns Error? {
if insn is ResultInsn {
if (vc.getNumTmpRegisters() > insn.result.number) && vc.getUsedTmpRegisters(insn.result.number) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if tmpRegisterUsed[insn.result.number] {

Pre-populate the tmpRegisterUsed array with false upto registers.length(). Then you don't have to check the length.

@ushirask ushirask requested a review from manuranga May 19, 2022 06:02
Comment on lines 130 to 132
if r is FinalRegister {
return vc.invalidErr("invalid register kind final for insn: " + r.kind, <Position>r.pos);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this check at verifyListSet/verifyMappingSet?

Comment on lines 100 to 107
if insn is BranchInsn|CatchInsn {
return;
}
else if insn is CallInsn {
foreach Operand arg in insn.args {
check verifyRegisterKind(vc, arg, tmpRegisterUsed, insn.pos);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to match and get rid of the if

var { operand } => {
check verifyRegisterKind(vc, operand, tmpRegisterUsed, insn.pos);
}
var { operands } => {
Copy link
Contributor

@manuranga manuranga May 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do var { operands } | { args: operands } => { not sure if it works in jBallerina, if not I think a issue needs to be created.

Anyway I think CallInsn needs to be changed to have operands instead of args for consistency. Please also create an issue for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do var { operands } | var { args: operands } => {

Comment on lines 92 to 93
if tmpRegisterUsed[insn.result.number] {
return vc.invalidErr("tmp register defined in multiple places", insn.pos);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should call this tmpRegisterInit. defined doesn't sound right. Can we say multiple assignments to a tmp register ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}
}

function verifyRegisterKind(VerifyContext vc, Operand r, boolean[] tmpRegisterInit, Position pos) returns Error? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current name doesn't explain what it does. How about verifyTmpOprandInitialized

}
}

function verifyTmpOprandInitialized(VerifyContext vc, Operand r, boolean[] tmpRegisterInit, Position pos) returns Error? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verifyTmpOperandInitialized

@@ -67,18 +67,59 @@ class VerifyContext {

public function verifyFunctionCode(Module mod, FunctionDefn defn, FunctionCode code) returns Error? {
VerifyContext cx = new(mod, defn);
boolean[] tmpRegisterInit = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a second though, let's call this tmpRegisterInitialized to match with the func name.

}
}

function verifyInsnRegisterKinds(VerifyContext vc, Insn insn, boolean[] tmpRegisterInit) returns Error? {
Copy link
Contributor

@manuranga manuranga May 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verifyTmpRegisters

Comment on lines 277 to 279
if insn.operands[0] is FinalRegister {
return vc.invalidErr("invalid register kind final for ListSetInsn", insn.pos);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong.

import ballerina/io;
public function main() {
    final int[] i = [1, 2, 3];
    i[0] = 4;
    io:println(i);
}

Above is a valid Ballerina program.

Comment on lines 305 to 307
if insn.operands[0] is FinalRegister {
return vc.invalidErr("invalid register kind final for MappingSetInsn", insn.pos);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@ushirask ushirask requested a review from manuranga May 23, 2022 03:39
if matched is bir:TmpRegister {
bir:AssignTmpRegister result = cx.createAssignTmpRegister(matched.semType, matched.pos);
bir:AssignInsn insn = { result, operand: matched, pos : stmt.startPos };
matched = result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a match we are only reading matched, aren't we ? why do we need AssignTmpRegister?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a case like

match x + 1 {
    2 => { 
        return "1";
    }
    4 => {
        return "2";
    }
}

even though matched is a TmpRegister it will be used in multiple blocks for Equality instructions, so to avoid that I think we can either do something like this or change all expr code gens to create AssignTmpRegister instead of Tmp depending on the situation.

Copy link
Contributor

@manuranga manuranga May 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll have to change the definition of TmpRegister to, assigned once, but can be used form multiple blocks.
@jclark what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is already the case, the problem is when the TmpRegister is used in a different block than the block it was initially assigned.

Copy link
Contributor

@manuranga manuranga May 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but can be used multiple times

I meant

but can be used from multiple block

let me edit.

@manuranga manuranga changed the title Verify register kinds Verify tmp registers May 25, 2022
@ushirask ushirask requested a review from manuranga May 26, 2022 05:25
@manuranga manuranga requested a review from jclark May 26, 2022 05:51
@manuranga
Copy link
Contributor

@jclark this is ready for you to review.

}
}

function verifyTmpRegisters(VerifyContext vc, Insn insn, boolean[] tmpRegisterInitialized) returns Error? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's call this verifyTmpRegisterAssignment

@@ -67,18 +67,34 @@ class VerifyContext {

public function verifyFunctionCode(Module mod, FunctionDefn defn, FunctionCode code) returns Error? {
VerifyContext cx = new(mod, defn);
boolean[] tmpRegisterInitialized = [];
if code.registers.length() > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaner to do tmpRegisterIntialized.setLength(code.registers.length());


function verifyTmpRegisterAssignment(VerifyContext vc, Insn insn, boolean[] tmpRegisterInitialized) returns Error? {
if insn is ResultInsnBase {
if tmpRegisterInitialized[insn.result.number] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add int num = insn.result.number;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants