merge add
This commit is contained in:
@@ -99,7 +99,7 @@ var track_types = function(slot_types, instr) {
|
||||
slot_types[text(instr[1])] = T_RECORD
|
||||
} else if (op == "function") {
|
||||
slot_types[text(instr[1])] = T_FUNCTION
|
||||
} else if (op == "invoke") {
|
||||
} else if (op == "invoke" || op == "tail_invoke") {
|
||||
slot_types[text(instr[2])] = T_UNKNOWN
|
||||
} else if (op == "load_field" || op == "load_index" || op == "load_dynamic") {
|
||||
slot_types[text(instr[1])] = T_UNKNOWN
|
||||
@@ -107,6 +107,9 @@ var track_types = function(slot_types, instr) {
|
||||
slot_types[text(instr[1])] = T_UNKNOWN
|
||||
} else if (op == "length") {
|
||||
slot_types[text(instr[1])] = T_INT
|
||||
} else if (op == "add" || op == "subtract" || op == "multiply" ||
|
||||
op == "divide" || op == "modulo" || op == "pow" || op == "negate") {
|
||||
slot_types[text(instr[1])] = T_UNKNOWN
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
32111
fold.cm.mcode
32111
fold.cm.mcode
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
197
mcode.cm
197
mcode.cm
@@ -273,157 +273,19 @@ var mcode = function(ast) {
|
||||
return node.kind == "null"
|
||||
}
|
||||
|
||||
// emit_add_decomposed: int path -> text path -> float path -> disrupt
|
||||
// emit_add_decomposed: emit generic add (VM dispatches int/float/text)
|
||||
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
|
||||
var emit_add_decomposed = function() {
|
||||
var dest = _bp_dest
|
||||
var left = _bp_left
|
||||
var right = _bp_right
|
||||
var t0 = 0
|
||||
var t1 = 0
|
||||
var left_is_int = is_known_int(_bp_ln)
|
||||
var left_is_text = is_known_text(_bp_ln)
|
||||
var left_is_num = is_known_number(_bp_ln)
|
||||
var right_is_int = is_known_int(_bp_rn)
|
||||
var right_is_text = is_known_text(_bp_rn)
|
||||
var right_is_num = is_known_number(_bp_rn)
|
||||
var not_int = null
|
||||
var not_text = null
|
||||
var done = null
|
||||
var err = null
|
||||
|
||||
// Both sides known int
|
||||
if (left_is_int && right_is_int) {
|
||||
emit_3("add_int", dest, left, right)
|
||||
// Known text+text → concat directly (skip numeric check in VM)
|
||||
if (is_known_text(_bp_ln) && is_known_text(_bp_rn)) {
|
||||
emit_3("concat", _bp_dest, _bp_left, _bp_right)
|
||||
return null
|
||||
}
|
||||
// Both sides known text
|
||||
if (left_is_text && right_is_text) {
|
||||
emit_3("concat", dest, left, right)
|
||||
return null
|
||||
}
|
||||
// Both sides known number (but not both int)
|
||||
if (left_is_num && right_is_num) {
|
||||
if (left_is_int && right_is_int) {
|
||||
emit_3("add_int", dest, left, right)
|
||||
} else {
|
||||
emit_3("add_float", dest, left, right)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
not_int = gen_label("add_ni")
|
||||
not_text = gen_label("add_nt")
|
||||
done = gen_label("add_done")
|
||||
err = gen_label("add_err")
|
||||
|
||||
// Int path
|
||||
t0 = alloc_slot()
|
||||
if (!left_is_int) {
|
||||
emit_2("is_int", t0, left)
|
||||
emit_jump_cond("jump_false", t0, not_int)
|
||||
}
|
||||
t1 = alloc_slot()
|
||||
if (!right_is_int) {
|
||||
emit_2("is_int", t1, right)
|
||||
emit_jump_cond("jump_false", t1, not_int)
|
||||
}
|
||||
emit_3("add_int", dest, left, right)
|
||||
emit_jump(done)
|
||||
|
||||
// Text path
|
||||
emit_label(not_int)
|
||||
if (!left_is_text) {
|
||||
emit_2("is_text", t0, left)
|
||||
emit_jump_cond("jump_false", t0, not_text)
|
||||
}
|
||||
if (!right_is_text) {
|
||||
emit_2("is_text", t1, right)
|
||||
emit_jump_cond("jump_false", t1, not_text)
|
||||
}
|
||||
emit_3("concat", dest, left, right)
|
||||
emit_jump(done)
|
||||
|
||||
// Float path
|
||||
emit_label(not_text)
|
||||
if (!left_is_num) {
|
||||
emit_2("is_num", t0, left)
|
||||
emit_jump_cond("jump_false", t0, err)
|
||||
}
|
||||
if (!right_is_num) {
|
||||
emit_2("is_num", t1, right)
|
||||
emit_jump_cond("jump_false", t1, err)
|
||||
}
|
||||
emit_3("add_float", dest, left, right)
|
||||
emit_jump(done)
|
||||
|
||||
emit_label(err)
|
||||
emit_0("disrupt")
|
||||
emit_label(done)
|
||||
emit_3("add", _bp_dest, _bp_left, _bp_right)
|
||||
return null
|
||||
}
|
||||
|
||||
// emit_numeric_binop: int path -> float path -> disrupt
|
||||
// reads _bp_dest, _bp_left, _bp_right, _bp_ln, _bp_rn from closure
|
||||
var emit_numeric_binop = function(int_op, float_op) {
|
||||
var dest = _bp_dest
|
||||
var left = _bp_left
|
||||
var right = _bp_right
|
||||
var t0 = 0
|
||||
var t1 = 0
|
||||
var left_is_int = is_known_int(_bp_ln)
|
||||
var left_is_num = is_known_number(_bp_ln)
|
||||
var right_is_int = is_known_int(_bp_rn)
|
||||
var right_is_num = is_known_number(_bp_rn)
|
||||
var not_int = null
|
||||
var done = null
|
||||
var err = null
|
||||
|
||||
// Both sides known int
|
||||
if (left_is_int && right_is_int) {
|
||||
emit_3(int_op, dest, left, right)
|
||||
return null
|
||||
}
|
||||
// Both sides known number (but not both int)
|
||||
if (left_is_num && right_is_num) {
|
||||
emit_3(float_op, dest, left, right)
|
||||
return null
|
||||
}
|
||||
|
||||
not_int = gen_label("num_ni")
|
||||
done = gen_label("num_done")
|
||||
err = gen_label("num_err")
|
||||
|
||||
t0 = alloc_slot()
|
||||
if (!left_is_int) {
|
||||
emit_2("is_int", t0, left)
|
||||
emit_jump_cond("jump_false", t0, not_int)
|
||||
}
|
||||
t1 = alloc_slot()
|
||||
if (!right_is_int) {
|
||||
emit_2("is_int", t1, right)
|
||||
emit_jump_cond("jump_false", t1, not_int)
|
||||
}
|
||||
emit_3(int_op, dest, left, right)
|
||||
emit_jump(done)
|
||||
|
||||
emit_label(not_int)
|
||||
if (!left_is_num) {
|
||||
emit_2("is_num", t0, left)
|
||||
emit_jump_cond("jump_false", t0, err)
|
||||
}
|
||||
if (!right_is_num) {
|
||||
emit_2("is_num", t1, right)
|
||||
emit_jump_cond("jump_false", t1, err)
|
||||
}
|
||||
emit_3(float_op, dest, left, right)
|
||||
emit_jump(done)
|
||||
|
||||
emit_label(err)
|
||||
emit_0("disrupt")
|
||||
emit_label(done)
|
||||
return null
|
||||
}
|
||||
// emit_numeric_binop removed — generic ops emitted directly via passthrough
|
||||
|
||||
// emit_eq_decomposed: identical -> int -> float -> text -> null -> bool -> mismatch(false)
|
||||
// reads _bp_dest, _bp_left, _bp_right from closure
|
||||
@@ -649,41 +511,9 @@ var mcode = function(ast) {
|
||||
return null
|
||||
}
|
||||
|
||||
// emit_neg_decomposed: int path -> float path -> disrupt
|
||||
// emit_neg_decomposed: emit generic negate (VM dispatches int/float)
|
||||
var emit_neg_decomposed = function(dest, src, src_node) {
|
||||
var t0 = 0
|
||||
var not_int = null
|
||||
var done = null
|
||||
var err = null
|
||||
|
||||
if (is_known_int(src_node)) {
|
||||
emit_2("neg_int", dest, src)
|
||||
return null
|
||||
}
|
||||
if (is_known_number(src_node)) {
|
||||
emit_2("neg_float", dest, src)
|
||||
return null
|
||||
}
|
||||
|
||||
not_int = gen_label("neg_ni")
|
||||
done = gen_label("neg_done")
|
||||
err = gen_label("neg_err")
|
||||
|
||||
t0 = alloc_slot()
|
||||
emit_2("is_int", t0, src)
|
||||
emit_jump_cond("jump_false", t0, not_int)
|
||||
emit_2("neg_int", dest, src)
|
||||
emit_jump(done)
|
||||
|
||||
emit_label(not_int)
|
||||
emit_2("is_num", t0, src)
|
||||
emit_jump_cond("jump_false", t0, err)
|
||||
emit_2("neg_float", dest, src)
|
||||
emit_jump(done)
|
||||
|
||||
emit_label(err)
|
||||
emit_0("disrupt")
|
||||
emit_label(done)
|
||||
emit_2("negate", dest, src)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -695,14 +525,6 @@ var mcode = function(ast) {
|
||||
_bp_right = right
|
||||
if (op_str == "add") {
|
||||
emit_add_decomposed()
|
||||
} else if (op_str == "subtract") {
|
||||
emit_numeric_binop("sub_int", "sub_float")
|
||||
} else if (op_str == "multiply") {
|
||||
emit_numeric_binop("mul_int", "mul_float")
|
||||
} else if (op_str == "divide") {
|
||||
emit_numeric_binop("div_int", "div_float")
|
||||
} else if (op_str == "modulo") {
|
||||
emit_numeric_binop("mod_int", "mod_float")
|
||||
} else if (op_str == "eq") {
|
||||
emit_eq_decomposed()
|
||||
} else if (op_str == "ne") {
|
||||
@@ -716,7 +538,8 @@ var mcode = function(ast) {
|
||||
} else if (op_str == "ge") {
|
||||
emit_relational("ge_int", "ge_float", "ge_text")
|
||||
} else {
|
||||
// Passthrough for bitwise, pow, in, etc.
|
||||
// Passthrough for subtract, multiply, divide, modulo,
|
||||
// bitwise, pow, in, etc.
|
||||
emit_3(op_str, dest, left, right)
|
||||
}
|
||||
return null
|
||||
|
||||
45275
mcode.cm.mcode
45275
mcode.cm.mcode
File diff suppressed because it is too large
Load Diff
45615
parse.cm.mcode
45615
parse.cm.mcode
File diff suppressed because it is too large
Load Diff
45
qbe_emit.cm
45
qbe_emit.cm
@@ -277,6 +277,51 @@ var qbe_emit = function(ir, qbe) {
|
||||
continue
|
||||
}
|
||||
|
||||
// --- Generic arithmetic (VM dispatches int/float) ---
|
||||
|
||||
if (op == "add") {
|
||||
p = fresh()
|
||||
emit(qbe.add(p, "%ctx", s(a2), s(a3)))
|
||||
emit(` ${s(a1)} =l copy %${p}`)
|
||||
wb(a1)
|
||||
continue
|
||||
}
|
||||
if (op == "subtract") {
|
||||
p = fresh()
|
||||
emit(qbe.sub(p, "%ctx", s(a2), s(a3)))
|
||||
emit(` ${s(a1)} =l copy %${p}`)
|
||||
wb(a1)
|
||||
continue
|
||||
}
|
||||
if (op == "multiply") {
|
||||
p = fresh()
|
||||
emit(qbe.mul(p, "%ctx", s(a2), s(a3)))
|
||||
emit(` ${s(a1)} =l copy %${p}`)
|
||||
wb(a1)
|
||||
continue
|
||||
}
|
||||
if (op == "divide") {
|
||||
p = fresh()
|
||||
emit(qbe.div(p, "%ctx", s(a2), s(a3)))
|
||||
emit(` ${s(a1)} =l copy %${p}`)
|
||||
wb(a1)
|
||||
continue
|
||||
}
|
||||
if (op == "modulo") {
|
||||
p = fresh()
|
||||
emit(qbe.mod(p, "%ctx", s(a2), s(a3)))
|
||||
emit(` ${s(a1)} =l copy %${p}`)
|
||||
wb(a1)
|
||||
continue
|
||||
}
|
||||
if (op == "negate") {
|
||||
p = fresh()
|
||||
emit(qbe.neg(p, "%ctx", s(a2)))
|
||||
emit(` ${s(a1)} =l copy %${p}`)
|
||||
wb(a1)
|
||||
continue
|
||||
}
|
||||
|
||||
// --- String concat ---
|
||||
|
||||
if (op == "concat") {
|
||||
|
||||
22826
qbe_emit.cm.mcode
22826
qbe_emit.cm.mcode
File diff suppressed because it is too large
Load Diff
@@ -2392,7 +2392,13 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
/* Text */
|
||||
else if (strcmp(op, "concat") == 0) { ABC3(MACH_CONCAT); }
|
||||
/* Generic arithmetic */
|
||||
else if (strcmp(op, "add") == 0) { ABC3(MACH_ADD); }
|
||||
else if (strcmp(op, "subtract") == 0) { ABC3(MACH_SUB); }
|
||||
else if (strcmp(op, "multiply") == 0) { ABC3(MACH_MUL); }
|
||||
else if (strcmp(op, "divide") == 0) { ABC3(MACH_DIV); }
|
||||
else if (strcmp(op, "modulo") == 0) { ABC3(MACH_MOD); }
|
||||
else if (strcmp(op, "pow") == 0) { ABC3(MACH_POW); }
|
||||
else if (strcmp(op, "negate") == 0) { AB2(MACH_NEG); }
|
||||
/* Typed integer comparisons */
|
||||
else if (strcmp(op, "eq_int") == 0) { ABC3(MACH_EQ_INT); }
|
||||
else if (strcmp(op, "ne_int") == 0) { ABC3(MACH_NE_INT); }
|
||||
|
||||
@@ -43,6 +43,10 @@ var streamline = function(ir, log) {
|
||||
add_float: true, sub_float: true, mul_float: true,
|
||||
div_float: true, mod_float: true
|
||||
}
|
||||
var numeric_ops = {
|
||||
add: true, subtract: true, multiply: true,
|
||||
divide: true, modulo: true, pow: true
|
||||
}
|
||||
var bool_result_ops = {
|
||||
eq_int: true, ne_int: true, lt_int: true, gt_int: true,
|
||||
le_int: true, ge_int: true,
|
||||
@@ -159,10 +163,12 @@ var streamline = function(ir, log) {
|
||||
slot_types[text(instr[1])] = T_FUNCTION
|
||||
} else if (op == "length") {
|
||||
slot_types[text(instr[1])] = T_INT
|
||||
} else if (op == "neg_int") {
|
||||
slot_types[text(instr[1])] = T_INT
|
||||
} else if (op == "negate" || op == "neg_int") {
|
||||
slot_types[text(instr[1])] = T_UNKNOWN
|
||||
} else if (op == "neg_float") {
|
||||
slot_types[text(instr[1])] = T_FLOAT
|
||||
} else if (numeric_ops[op] == true) {
|
||||
slot_types[text(instr[1])] = T_UNKNOWN
|
||||
} else if (op == "bitnot" || op == "bitand" || op == "bitor" ||
|
||||
op == "bitxor" || op == "shl" || op == "shr" || op == "ushr") {
|
||||
slot_types[text(instr[1])] = T_INT
|
||||
@@ -266,6 +272,12 @@ var streamline = function(ir, log) {
|
||||
merge_backward(backward_types, instr[3], T_INT)
|
||||
} else if (op == "neg_int" || op == "bitnot") {
|
||||
merge_backward(backward_types, instr[2], T_INT)
|
||||
} else if (op == "subtract" || op == "multiply" ||
|
||||
op == "divide" || op == "modulo" || op == "pow") {
|
||||
merge_backward(backward_types, instr[2], T_NUM)
|
||||
merge_backward(backward_types, instr[3], T_NUM)
|
||||
} else if (op == "negate") {
|
||||
merge_backward(backward_types, instr[2], T_NUM)
|
||||
} else if (op == "add_float" || op == "sub_float" || op == "mul_float" ||
|
||||
op == "div_float" || op == "mod_float" ||
|
||||
op == "eq_float" || op == "ne_float" || op == "lt_float" ||
|
||||
@@ -395,6 +407,9 @@ var streamline = function(ir, log) {
|
||||
} else if (op == "neg_float") {
|
||||
slot = instr[1]
|
||||
typ = T_FLOAT
|
||||
} else if (op == "negate") {
|
||||
slot = instr[1]
|
||||
typ = T_UNKNOWN
|
||||
} else if (op == "concat") {
|
||||
slot = instr[1]
|
||||
typ = T_TEXT
|
||||
|
||||
38994
streamline.cm.mcode
38994
streamline.cm.mcode
File diff suppressed because it is too large
Load Diff
10603
tokenize.cm.mcode
10603
tokenize.cm.mcode
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@ var slot_positions = {
|
||||
// Unary — dest, src
|
||||
move: [0, 1],
|
||||
not: [0, 1],
|
||||
negate: [0, 1],
|
||||
neg_int: [0, 1],
|
||||
neg_float: [0, 1],
|
||||
bitnot: [0, 1],
|
||||
@@ -123,7 +124,7 @@ var slot_positions = {
|
||||
var writes_dest = {
|
||||
access: true, int: true, true: true, false: true, null: true,
|
||||
function: true, array: true, record: true,
|
||||
move: true, not: true, neg_int: true, neg_float: true, bitnot: true,
|
||||
move: true, not: true, negate: true, neg_int: true, neg_float: true, bitnot: true,
|
||||
length: true, typeof: true,
|
||||
is_int: true, is_text: true, is_num: true,
|
||||
is_bool: true, is_null: true, is_array: true,
|
||||
|
||||
Reference in New Issue
Block a user