mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-02-13 20:26:23 +00:00
Draft_1 for compile assembly to a machine code
This commit is contained in:
parent
dbbfe450e5
commit
e5f4515cb1
@ -31,7 +31,7 @@ public class ToolBar extends JFrame {
|
|||||||
public ToolBar() throws HeadlessException {
|
public ToolBar() throws HeadlessException {
|
||||||
|
|
||||||
introLogger.info("");
|
introLogger.info("");
|
||||||
introLogger.info("♢ EthereumJ [v0.5.1] ");
|
introLogger.info("♢ EthereumJ [v0.5.1] by RomanJ");
|
||||||
introLogger.info("♢ Code by Roman Mandeleil, (c) 2014.");
|
introLogger.info("♢ Code by Roman Mandeleil, (c) 2014.");
|
||||||
introLogger.info("♢ Contribution: Nick Savers ");
|
introLogger.info("♢ Contribution: Nick Savers ");
|
||||||
introLogger.info("♢ Based on a design by Vitalik Buterin.");
|
introLogger.info("♢ Based on a design by Vitalik Buterin.");
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
package org.ethereum.serpent;
|
package org.ethereum.serpent;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
import org.ethereum.util.ByteUtil;
|
||||||
|
import org.ethereum.vm.OpCode;
|
||||||
|
import org.spongycastle.util.BigIntegers;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* www.ethereumJ.com
|
||||||
@ -20,4 +29,93 @@ public class SerpentCompiler {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String compileAssemblyToMachine(String code){
|
||||||
|
|
||||||
|
StringBuffer assemblyCode = new StringBuffer();
|
||||||
|
String[] lexaArr = code.split("\\s+");
|
||||||
|
|
||||||
|
List<String> lexaList = new ArrayList<String>();
|
||||||
|
Collections.addAll(lexaList, lexaArr);
|
||||||
|
|
||||||
|
// Encode push_n numbers
|
||||||
|
for (int i = 0; i < lexaList.size(); ++i){
|
||||||
|
|
||||||
|
String lexa = lexaList.get(i);
|
||||||
|
|
||||||
|
if (OpCode.contains(lexa) ||
|
||||||
|
lexa.contains("REF_") ||
|
||||||
|
lexa.contains("LABEL_")) continue;
|
||||||
|
|
||||||
|
int bytesNum = ByteUtil.numBytes( lexa );
|
||||||
|
|
||||||
|
String num = lexaList.remove(i);
|
||||||
|
BigInteger bNum = new BigInteger(num);
|
||||||
|
byte[] bytes = BigIntegers.asUnsignedByteArray(bNum);
|
||||||
|
if (bytes.length == 0)bytes = new byte[]{0};
|
||||||
|
|
||||||
|
for (int j = bytes.length; j > 0 ; --j){
|
||||||
|
|
||||||
|
lexaList.add(i, (bytes[j-1] & 0xFF) +"");
|
||||||
|
}
|
||||||
|
|
||||||
|
lexaList.add(i, "PUSH" + bytesNum);
|
||||||
|
i = i + bytesNum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc label pos & remove labels
|
||||||
|
HashMap<String, Integer> labels = new HashMap<String, Integer>();
|
||||||
|
for (int i = 0; i < lexaList.size(); ++i){
|
||||||
|
|
||||||
|
String lexa = lexaList.get(i);
|
||||||
|
if (!lexa.contains("LABEL_")) continue;
|
||||||
|
|
||||||
|
String label = lexaList.remove(i);
|
||||||
|
String labelNum = label.split("LABEL_")[1];
|
||||||
|
|
||||||
|
labels.put(labelNum, i);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode all ref occurrence
|
||||||
|
for (int i = 0; i < lexaList.size(); ++i){
|
||||||
|
|
||||||
|
String lexa = lexaList.get(i);
|
||||||
|
if (!lexa.contains("REF_")) continue;
|
||||||
|
|
||||||
|
String ref = lexaList.remove(i);
|
||||||
|
String labelNum = ref.split("REF_")[1];
|
||||||
|
|
||||||
|
Integer pos = labels.get(labelNum);
|
||||||
|
int bytesNum = ByteUtil.numBytes( pos.toString() );
|
||||||
|
|
||||||
|
lexaList.add(i, pos.toString());
|
||||||
|
|
||||||
|
for (int j = 0; j < (4 - bytesNum) ; ++j)
|
||||||
|
lexaList.add(i, "0");
|
||||||
|
|
||||||
|
lexaList.add(i, "PUSH4");
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String lexa : lexaList){
|
||||||
|
|
||||||
|
if (OpCode.contains(lexa))
|
||||||
|
assemblyCode.append( OpCode.byteVal(lexa) );
|
||||||
|
else{
|
||||||
|
|
||||||
|
assemblyCode.append( lexa );
|
||||||
|
}
|
||||||
|
assemblyCode.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return assemblyCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,8 @@ public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
|
|||||||
@Override
|
@Override
|
||||||
public String visitInt_val(@NotNull SerpentParser.Int_valContext ctx) {
|
public String visitInt_val(@NotNull SerpentParser.Int_valContext ctx) {
|
||||||
|
|
||||||
|
// todo: (!!!) ensure that not encode value more than 32 bytes (!!!)
|
||||||
|
|
||||||
if (ctx.OP_NOT() != null)
|
if (ctx.OP_NOT() != null)
|
||||||
return visitExpression(ctx.expression()) + " NOT";
|
return visitExpression(ctx.expression()) + " NOT";
|
||||||
|
|
||||||
|
@ -82,4 +82,28 @@ public class ByteUtil {
|
|||||||
return 0;
|
return 0;
|
||||||
return new BigInteger(1, b).intValue();
|
return new BigInteger(1, b).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the number of bytes need
|
||||||
|
* to encode the number
|
||||||
|
*
|
||||||
|
* @param val - number
|
||||||
|
* @return number of min bytes used to encode the number
|
||||||
|
*/
|
||||||
|
public static int numBytes(String val){
|
||||||
|
|
||||||
|
BigInteger bInt = new BigInteger(val);
|
||||||
|
int bytes = 0;
|
||||||
|
|
||||||
|
while(!bInt.equals(BigInteger.ZERO)){
|
||||||
|
|
||||||
|
bInt = bInt.shiftRight(8);
|
||||||
|
++bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes == 0) ++bytes;
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.ethereum.vm;
|
package org.ethereum.vm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instruction set for the Ethereum Virtual Machine
|
* Instruction set for the Ethereum Virtual Machine
|
||||||
@ -136,9 +135,13 @@ public enum OpCode {
|
|||||||
private byte opcode;
|
private byte opcode;
|
||||||
|
|
||||||
private static final Map<Byte, OpCode> intToTypeMap = new HashMap<Byte, OpCode>();
|
private static final Map<Byte, OpCode> intToTypeMap = new HashMap<Byte, OpCode>();
|
||||||
|
private static final Map<String, Byte> stringToByteMap = new HashMap<String, Byte>();
|
||||||
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (OpCode type : OpCode.values()) {
|
for (OpCode type : OpCode.values()) {
|
||||||
intToTypeMap.put(type.opcode, type);
|
intToTypeMap.put(type.opcode, type);
|
||||||
|
stringToByteMap.put(type.name(), type.opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,4 +159,13 @@ public enum OpCode {
|
|||||||
public int asInt() {
|
public int asInt() {
|
||||||
return opcode;
|
return opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean contains(String code){
|
||||||
|
|
||||||
|
return stringToByteMap.containsKey(code.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte byteVal(String code){
|
||||||
|
return stringToByteMap.get(code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
|
|
||||||
#***
|
|
||||||
# Starting to gather some properties the system going to support
|
|
||||||
#***
|
|
||||||
client.name=EthereumJ [v0.5.1] by RomanJ
|
|
||||||
|
|
||||||
# if the system will work as a server also
|
# if the system will work as a server also
|
||||||
# accept for incoming connections [true/false]
|
# accept for incoming connections [true/false]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.ethereum.serpent;
|
package org.ethereum.serpent;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -1211,23 +1212,34 @@ public class SerpentCompileTest {
|
|||||||
|
|
||||||
Assert.assertEquals(expected, result);
|
Assert.assertEquals(expected, result);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
*
|
|
||||||
a = msg.datasize
|
|
||||||
b = msg.sender
|
|
||||||
c = msg.value
|
|
||||||
d = tx.gasprice
|
|
||||||
e = tx.origin
|
|
||||||
f = tx.gas
|
|
||||||
g = contract.balance
|
|
||||||
h = block.prevhash
|
|
||||||
i = block.coinbase
|
|
||||||
j = block.timestamp
|
|
||||||
k = block.number
|
|
||||||
l = block.difficulty
|
|
||||||
m = block.gaslimit
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
@Test // compile to machine code 1
|
||||||
|
public void test42(){
|
||||||
|
|
||||||
|
String code = "x = 256 \n" +
|
||||||
|
"while x > 1: \n" +
|
||||||
|
" if (x % 2) == 0: \n" +
|
||||||
|
" x = x / 2 \n" +
|
||||||
|
" else: \n " +
|
||||||
|
" x = 3 * x + 1 \n" ;
|
||||||
|
|
||||||
|
String expected = "97 1 0 96 0 84 96 1 96 0 83 11 12 13 99 0 0 0 53 89 96 0 96 2 96 0 83 6 12 13 99 0 0 0 39 89 96 2 96 0 83 4 96 0 84 99 0 0 0 51 88 96 1 96 0 83 96 3 2 1 96 0 84 99 0 0 0 6 88";
|
||||||
|
|
||||||
|
String asmResult = SerpentCompiler.compile(code);
|
||||||
|
String machineCode = SerpentCompiler.compileAssemblyToMachine(asmResult);
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, machineCode.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test // todo delete this one
|
||||||
|
public void testFoo(){
|
||||||
|
|
||||||
|
System.out.println(ByteUtil.numBytes("65536"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user