GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit e2ff5a00 authored by Kunshan Wang's avatar Kunshan Wang

Test the text IR builder

parent 44a051e9
......@@ -15,7 +15,8 @@ libraryDependencies := Seq(
"com.github.jnr" % "jnr-ffi" % "2.0.3",
"com.github.jnr" % "jffi" % "1.2.9",
"com.github.jnr" % "jnr-posix" % "3.0.17",
"org.scalatest" %% "scalatest" % "2.2.0"
"org.scalatest" %% "scalatest" % "2.2.0" % "test",
"junit" % "junit" % "4.12" % "test"
)
antlr4Settings
......
......@@ -13,7 +13,7 @@ import DefaultTypes._
* have two different prefixes and one is not a prefix of the other, they are guaranteed to give a unique name
* each time nextName is called. The "hint" argument provides a human-readable suffix to a name.
* <p>
* The global name prefix "@" is assumed. It is not recommended to use local names in generated code, since they
* It is not recommended to use local names in generated code, since they
* strictly aliases of @funcvername.localname.
* <p>
* Example:
......@@ -25,14 +25,16 @@ import DefaultTypes._
*/
class NameFactory(prefix: String) {
private var num = 0
def nextName(): MuName = nextName(null)
def nextName(hint: String = null): MuName = {
def nextName(hint: String): MuName = {
val myNum = num
num += 1
if (hint == null) {
"@%s_%04d".format(prefix, myNum)
"%s_%04d".format(prefix, myNum)
} else {
"@%s_%04d_%s".format(prefix, myNum, hint)
"%s_%04d_%s".format(prefix, myNum, hint)
}
}
}
......@@ -52,7 +54,12 @@ class FuncDefBuilder(name: MuName, version: MuName, sig: MuName) {
// Automatic name generation
private val paramNamer = new NameFactory(version + ".param")
private val bbNamer = new NameFactory(version + ".bb")
private val instNamer = new NameFactory(version + ".inst")
@BeanProperty
val instNamer = new NameFactory(version + ".inst")
// Some convenient functions because the client may frequently request new names.
def nextInstName(hint: String): String = instNamer.nextName(hint)
def nextInstName(): String = instNamer.nextName()
/**
* Add a parameter.
......@@ -66,14 +73,6 @@ class FuncDefBuilder(name: MuName, version: MuName, sig: MuName) {
paramName
}
/** The entry block. */
@BeanProperty
val entry = new BasicBlock()
entry.name = "entry"
@BeanProperty
var curBB = entry
/**
* Create a new basic block and add to the funcDef.
* @param hint: A human-readable suffix of the basic block name, or null if not needed.
......@@ -86,6 +85,13 @@ class FuncDefBuilder(name: MuName, version: MuName, sig: MuName) {
bb
}
/** The entry block. */
@BeanProperty
val entry = newBB("entry")
@BeanProperty
var curBB = entry
/**
* Add the instruction into the current basic block.
* @param inst: The instruction to add
......
package uvm.clientsupport.text;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({})
public class ClientMuIRBuilderTests {
}
package uvm.clientsupport.text;
import static org.junit.Assert.*;
import org.junit.Test;
public class MuIRBuilderTest {
@Test
public void nameFactoryTest() {
String prefix1 = "@mylang.type";
NameFactory nf1 = new NameFactory(prefix1);
String prefix2 = "@yourlang.func";
NameFactory nf2 = new NameFactory(prefix2);
String name11 = nf1.nextName("int32");
String name21 = nf2.nextName("append");
String name12 = nf1.nextName("StringBuilder");
String name22 = nf2.nextName();
assertNotEquals(name11, name12);
assertNotEquals(name11, name21);
assertNotEquals(name21, name12);
assertNotEquals(name21, name22);
assertStartsWith(name11, prefix1);
assertStartsWith(name12, prefix1);
assertStartsWith(name21, prefix2);
assertStartsWith(name22, prefix2);
}
public void assertStartsWith(String main, String prefix) {
assertTrue(String.format("%s does not start with %s", main, prefix), main.startsWith(prefix));
}
public void assertEndsWith(String main, String suffix) {
assertTrue(String.format("%s does not end with %s", main, suffix), main.endsWith(suffix));
}
@Test
public void funcBuildingTest() {
FuncDefBuilder b = new FuncDefBuilder("@mylang.internal.add", "@mylang.internal.add.v1", "@foosig");
String xMuName = b.addParam("x");
String yMN = b.addParam("y");
InstBinOp add = new InstBinOp();
add.setName(b.nextInstName("add_x_y"));
assertEndsWith(add.getName(), "add_x_y");
add.setOp("ADD");
add.setOpndTy("@i32");
add.setOp1(xMuName);
add.setOp2(yMN);
b.emit(add);
FuncDef fd = b.getFuncDef();
BasicBlock entry = fd.getBbs().get(0);
assertEndsWith(entry.getName(), "entry");
Instruction inst0 = entry.getInsts().get(0);
assertEquals(add, inst0);
BasicBlock bb2 = b.newBB("nextBlock");
assertTrue(fd.getBbs().contains(bb2));
InstBranch br = new InstBranch();
br.setName(b.nextInstName("initial_jump"));
br.setDest(bb2.getName());
b.emit(br);
assertTrue(entry.getInsts().contains(br));
b.setCurBB(bb2);
InstBinOp sub = new InstBinOp();
sub.setName(b.nextInstName("sub"));
sub.setOp("SUB");
sub.setOpndTy("@i32");
sub.setOp1(xMuName);
sub.setOp2(yMN);
b.emit(sub);
assertFalse(entry.getInsts().contains(sub));
assertTrue(bb2.getInsts().contains(sub));
System.out.println(TextIRWriter.funcDefToText(fd));
}
@Test
public void customBuilderTest() {
class CustomFuncDefBuilder extends FuncDefBuilder {
public final String xMuName;
public final String yMuName;
public CustomFuncDefBuilder(String name) {
super(name, name+".v1", "@ThisKindOfFunctionAlwaysHasThisSignature");
xMuName = addParam("x");
yMuName = addParam("y");
}
public String emitAddI32(String hint, String op1, String op2) {
InstBinOp add = new InstBinOp();
String name = nextInstName(hint);
add.setName(name);
add.setOp("ADD"); // because this function is dedicated to adding.
add.setOpndTy("@i32"); // because this function is dedicated to i32.
add.setOp1(op1);
add.setOp2(op2);
emit(add);
return name;
}
public void emitJumpIfNegative(String hint, String opnd, String dest) {
InstCmp lt = new InstCmp();
String ltName = nextInstName(hint+"_compare");
lt.setName(ltName);
lt.setOp("SLT");
lt.setOpndTy("@i32");
lt.setOp1(opnd);
lt.setOp2("@CONST_I32_NEG_1"); // Please define this constant at the top level.
emit(lt);
InstBranch2 br2 = new InstBranch2();
String br2Name = nextInstName(hint+"_branch");
br2.setName(br2Name);
br2.setCond(ltName);
br2.setIfTrue(dest);
BasicBlock bbNew = newBB(hint+"_cont");
br2.setIfFalse(bbNew.getName());
emit(br2);
setCurBB(bbNew); // Behave as if it is a straight-line code, but it has just branched.
}
}
CustomFuncDefBuilder b = new CustomFuncDefBuilder("myAdder");
String xMN = b.xMuName;
String yMN = b.yMuName;
String zMN = b.emitAddI32("add", xMN, yMN);
BasicBlock excHandler = b.newBB("handle_negative");
b.emitJumpIfNegative("guard_positive", zMN, excHandler.getName());
FuncDef fd = b.getFuncDef();
BasicBlock entry = b.getEntry();
assertTrue(entry.getInsts().get(0) instanceof InstBinOp);
assertTrue(entry.getInsts().get(1) instanceof InstCmp);
assertTrue(entry.getInsts().get(2) instanceof InstBranch2);
System.out.println(TextIRWriter.funcDefToText(fd));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment