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