mirror of
https://github.com/corda/corda.git
synced 2025-06-18 15:18:16 +00:00
enforce more strong typing in compiler
This commit is contained in:
@ -1253,15 +1253,6 @@ Value* loadLocal(Context* c, ir::Type type, unsigned index)
|
|||||||
fprintf(stderr, "load local %p at %d\n", c->locals[index].value, index);
|
fprintf(stderr, "load local %p at %d\n", c->locals[index].value, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(c,
|
|
||||||
type.flavor() != ir::Type::Object
|
|
||||||
|| c->locals[index].value->type.flavor() == ir::Type::Object
|
|
||||||
// TODO: this is a very java-specific hole in the type system. Get
|
|
||||||
// rid of it:
|
|
||||||
|| c->locals[index].value->type.flavor() == ir::Type::Address
|
|
||||||
// TODO Temporary hack for Subroutine test!!!
|
|
||||||
|| c->locals[index].value->type.flavor() == ir::Type::Invalid);
|
|
||||||
|
|
||||||
return c->locals[index].value;
|
return c->locals[index].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2522,7 +2513,10 @@ class MyCompiler: public Compiler {
|
|||||||
{
|
{
|
||||||
// TODO: once type information is flowed properly, enable this assert.
|
// TODO: once type information is flowed properly, enable this assert.
|
||||||
// Some time later, we can remove the parameter.
|
// Some time later, we can remove the parameter.
|
||||||
// assert(&c, a->type == type);
|
assert(&c,
|
||||||
|
a->type == type
|
||||||
|
// TODO Temporary hack for Subroutine test!!!
|
||||||
|
|| a->type.flavor() == ir::Type::Invalid);
|
||||||
appendReturn(&c, type.size(), static_cast<Value*>(a));
|
appendReturn(&c, type.size(), static_cast<Value*>(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2641,7 +2635,8 @@ class MyCompiler: public Compiler {
|
|||||||
TargetBytesPerWord,
|
TargetBytesPerWord,
|
||||||
truncateType.size(),
|
truncateType.size(),
|
||||||
static_cast<Value*>(src),
|
static_cast<Value*>(src),
|
||||||
extendType.size(),
|
extendType.size() < TargetBytesPerWord ? TargetBytesPerWord
|
||||||
|
: extendType.size(),
|
||||||
dst);
|
dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -2724,7 +2719,7 @@ class MyCompiler: public Compiler {
|
|||||||
(isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b))
|
(isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b))
|
||||||
or(isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b)));
|
or(isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b)));
|
||||||
|
|
||||||
Value* result = value(&c, a->type);
|
Value* result = value(&c, type);
|
||||||
|
|
||||||
appendCombine(&c,
|
appendCombine(&c,
|
||||||
op,
|
op,
|
||||||
|
132
src/compile.cpp
132
src/compile.cpp
@ -1345,15 +1345,34 @@ ir::Value* loadLocal(Context* context,
|
|||||||
ir::Type type,
|
ir::Type type,
|
||||||
unsigned index)
|
unsigned index)
|
||||||
{
|
{
|
||||||
return context->compiler->loadLocal(
|
ir::Value* result = context->compiler->loadLocal(
|
||||||
type, translateLocalIndex(context, footprint, index));
|
type, translateLocalIndex(context, footprint, index));
|
||||||
|
|
||||||
|
assert(context->thread,
|
||||||
|
(type.flavor() != ir::Type::Object && type == result->type)
|
||||||
|
|| (type.flavor() == ir::Type::Object
|
||||||
|
&& (result->type.flavor() == ir::Type::Object
|
||||||
|
|| result->type.flavor() == ir::Type::Address))
|
||||||
|
// TODO Temporary hack for Subroutine test!!!
|
||||||
|
|| result->type.flavor() == ir::Type::Invalid
|
||||||
|
|| result->type.flavor() == ir::Type::Integer);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void storeLocal(Context* context,
|
void storeLocal(Context* context,
|
||||||
unsigned footprint,
|
unsigned footprint,
|
||||||
|
ir::Type type UNUSED,
|
||||||
ir::Value* value,
|
ir::Value* value,
|
||||||
unsigned index)
|
unsigned index)
|
||||||
{
|
{
|
||||||
|
assert(context->thread,
|
||||||
|
(type.flavor() != ir::Type::Object && type == value->type)
|
||||||
|
|| (type.flavor() == ir::Type::Object
|
||||||
|
&& (value->type.flavor() == ir::Type::Object
|
||||||
|
|| value->type.flavor() == ir::Type::Address))
|
||||||
|
// TODO Temporary hack for Subroutine test!!!
|
||||||
|
|| value->type.flavor() == ir::Type::Invalid
|
||||||
|
|| value->type.flavor() == ir::Type::Integer);
|
||||||
context->compiler->storeLocal
|
context->compiler->storeLocal
|
||||||
(footprint, value, translateLocalIndex(context, footprint, index));
|
(footprint, value, translateLocalIndex(context, footprint, index));
|
||||||
}
|
}
|
||||||
@ -1783,7 +1802,7 @@ class Frame {
|
|||||||
void pushInt(ir::Value* o)
|
void pushInt(ir::Value* o)
|
||||||
{
|
{
|
||||||
assert(t,
|
assert(t,
|
||||||
o->type.flavor() == ir::Type::Integer
|
o->type == types.i4
|
||||||
// TODO Temporary hack for Subroutine test!!!
|
// TODO Temporary hack for Subroutine test!!!
|
||||||
|| o->type.flavor() == ir::Type::Invalid);
|
|| o->type.flavor() == ir::Type::Invalid);
|
||||||
pushSmall(o);
|
pushSmall(o);
|
||||||
@ -1791,7 +1810,7 @@ class Frame {
|
|||||||
|
|
||||||
void pushFloat(ir::Value* o)
|
void pushFloat(ir::Value* o)
|
||||||
{
|
{
|
||||||
assert(t, o->type.flavor() == ir::Type::Float);
|
assert(t, o->type == types.f4);
|
||||||
pushSmall(o);
|
pushSmall(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1827,7 +1846,7 @@ class Frame {
|
|||||||
void pushLong(ir::Value* o)
|
void pushLong(ir::Value* o)
|
||||||
{
|
{
|
||||||
assert(t,
|
assert(t,
|
||||||
o->type.flavor() == ir::Type::Integer
|
o->type == types.i8
|
||||||
// TODO Temporary hack for Subroutine test!!!
|
// TODO Temporary hack for Subroutine test!!!
|
||||||
|| o->type.flavor() == ir::Type::Invalid);
|
|| o->type.flavor() == ir::Type::Invalid);
|
||||||
pushLarge(o);
|
pushLarge(o);
|
||||||
@ -1835,7 +1854,7 @@ class Frame {
|
|||||||
|
|
||||||
void pushDouble(ir::Value* o)
|
void pushDouble(ir::Value* o)
|
||||||
{
|
{
|
||||||
assert(t, o->type.flavor() == ir::Type::Float);
|
assert(t, o->type == types.f8);
|
||||||
pushLarge(o);
|
pushLarge(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1890,22 +1909,34 @@ class Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void storeInt(unsigned index) {
|
void storeInt(unsigned index) {
|
||||||
storeLocal(context, 1, popInt(), index);
|
storeLocal(context, 1, types.i4, popInt(), index);
|
||||||
|
storedInt(translateLocalIndex(context, 1, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void storeFloat(unsigned index)
|
||||||
|
{
|
||||||
|
storeLocal(context, 1, types.f4, popInt(), index);
|
||||||
storedInt(translateLocalIndex(context, 1, index));
|
storedInt(translateLocalIndex(context, 1, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void storeLong(unsigned index) {
|
void storeLong(unsigned index) {
|
||||||
storeLocal(context, 2, popLong(), index);
|
storeLocal(context, 2, types.i8, popLong(), index);
|
||||||
|
storedLong(translateLocalIndex(context, 2, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void storeDouble(unsigned index)
|
||||||
|
{
|
||||||
|
storeLocal(context, 2, types.f8, popLong(), index);
|
||||||
storedLong(translateLocalIndex(context, 2, index));
|
storedLong(translateLocalIndex(context, 2, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void storeObject(unsigned index) {
|
void storeObject(unsigned index) {
|
||||||
storeLocal(context, 1, popObject(), index);
|
storeLocal(context, 1, types.object, popObject(), index);
|
||||||
storedObject(translateLocalIndex(context, 1, index));
|
storedObject(translateLocalIndex(context, 1, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void storeObjectOrAddress(unsigned index) {
|
void storeObjectOrAddress(unsigned index) {
|
||||||
storeLocal(context, 1, popQuiet(types.i4), index);
|
storeLocal(context, 1, types.object, popQuiet(types.object), index);
|
||||||
|
|
||||||
assert(t, sp >= 1);
|
assert(t, sp >= 1);
|
||||||
assert(t, sp - 1 >= localSize());
|
assert(t, sp - 1 >= localSize());
|
||||||
@ -3534,6 +3565,7 @@ handleEntrance(MyThread* t, Frame* frame)
|
|||||||
unsigned index = savedTargetIndex(t, method);
|
unsigned index = savedTargetIndex(t, method);
|
||||||
storeLocal(frame->context,
|
storeLocal(frame->context,
|
||||||
1,
|
1,
|
||||||
|
frame->types.object,
|
||||||
loadLocal(frame->context, 1, frame->types.object, 0),
|
loadLocal(frame->context, 1, frame->types.object, 0),
|
||||||
index);
|
index);
|
||||||
frame->set(index, Frame::Object);
|
frame->set(index, Frame::Object);
|
||||||
@ -3847,10 +3879,8 @@ intrinsic(MyThread* t, Frame* frame, object target)
|
|||||||
{
|
{
|
||||||
ir::Value* address = popLongAddress(frame);
|
ir::Value* address = popLongAddress(frame);
|
||||||
frame->popObject();
|
frame->popObject();
|
||||||
frame->pushInt(c->load(ir::SignExtend,
|
frame->pushInt(c->load(
|
||||||
types.i1,
|
ir::SignExtend, types.i1, c->memory(address, types.i1), types.i4));
|
||||||
c->memory(address, types.i1),
|
|
||||||
types.address));
|
|
||||||
return true;
|
return true;
|
||||||
} else if (MATCH(methodName(t, target), "putByte")
|
} else if (MATCH(methodName(t, target), "putByte")
|
||||||
and MATCH(methodSpec(t, target), "(JB)V"))
|
and MATCH(methodSpec(t, target), "(JB)V"))
|
||||||
@ -3867,10 +3897,8 @@ intrinsic(MyThread* t, Frame* frame, object target)
|
|||||||
{
|
{
|
||||||
ir::Value* address = popLongAddress(frame);
|
ir::Value* address = popLongAddress(frame);
|
||||||
frame->popObject();
|
frame->popObject();
|
||||||
frame->pushInt(c->load(ir::SignExtend,
|
frame->pushInt(c->load(
|
||||||
types.i2,
|
ir::SignExtend, types.i2, c->memory(address, types.i2), types.i4));
|
||||||
c->memory(address, types.i2),
|
|
||||||
types.address));
|
|
||||||
return true;
|
return true;
|
||||||
} else if ((MATCH(methodName(t, target), "putShort")
|
} else if ((MATCH(methodName(t, target), "putShort")
|
||||||
and MATCH(methodSpec(t, target), "(JS)V"))
|
and MATCH(methodSpec(t, target), "(JS)V"))
|
||||||
@ -4201,7 +4229,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
c->load(ir::SignExtend,
|
c->load(ir::SignExtend,
|
||||||
types.f4,
|
types.f4,
|
||||||
c->memory(array, types.f4, TargetArrayBody, index),
|
c->memory(array, types.f4, TargetArrayBody, index),
|
||||||
types.f8));
|
types.f4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iaload:
|
case iaload:
|
||||||
@ -4209,7 +4237,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
c->load(ir::SignExtend,
|
c->load(ir::SignExtend,
|
||||||
types.i4,
|
types.i4,
|
||||||
c->memory(array, types.i4, TargetArrayBody, index),
|
c->memory(array, types.i4, TargetArrayBody, index),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case baload:
|
case baload:
|
||||||
@ -4217,7 +4245,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
c->load(ir::SignExtend,
|
c->load(ir::SignExtend,
|
||||||
types.i1,
|
types.i1,
|
||||||
c->memory(array, types.i1, TargetArrayBody, index),
|
c->memory(array, types.i1, TargetArrayBody, index),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case caload:
|
case caload:
|
||||||
@ -4225,7 +4253,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
c->load(ir::ZeroExtend,
|
c->load(ir::ZeroExtend,
|
||||||
types.i2,
|
types.i2,
|
||||||
c->memory(array, types.i2, TargetArrayBody, index),
|
c->memory(array, types.i2, TargetArrayBody, index),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case daload:
|
case daload:
|
||||||
@ -4249,7 +4277,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
c->load(ir::SignExtend,
|
c->load(ir::SignExtend,
|
||||||
types.i2,
|
types.i2,
|
||||||
c->memory(array, types.i2, TargetArrayBody, index),
|
c->memory(array, types.i2, TargetArrayBody, index),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -4546,11 +4574,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dconst_0:
|
case dconst_0:
|
||||||
frame->pushDouble(c->constant(doubleToBits(0.0), types.f4));
|
frame->pushDouble(c->constant(doubleToBits(0.0), types.f8));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dconst_1:
|
case dconst_1:
|
||||||
frame->pushDouble(c->constant(doubleToBits(1.0), types.f4));
|
frame->pushDouble(c->constant(doubleToBits(1.0), types.f8));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dneg: {
|
case dneg: {
|
||||||
@ -4723,7 +4751,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
ir::SignExtend,
|
ir::SignExtend,
|
||||||
types.i1,
|
types.i1,
|
||||||
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CharField:
|
case CharField:
|
||||||
@ -4731,7 +4759,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
ir::ZeroExtend,
|
ir::ZeroExtend,
|
||||||
types.i2,
|
types.i2,
|
||||||
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ShortField:
|
case ShortField:
|
||||||
@ -4739,7 +4767,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
ir::SignExtend,
|
ir::SignExtend,
|
||||||
types.i2,
|
types.i2,
|
||||||
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FloatField:
|
case FloatField:
|
||||||
@ -4755,7 +4783,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
ir::SignExtend,
|
ir::SignExtend,
|
||||||
types.i4,
|
types.i4,
|
||||||
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
c->memory(table, types.i4, targetFieldOffset(context, field)),
|
||||||
types.address));
|
types.i4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DoubleField:
|
case DoubleField:
|
||||||
@ -4869,12 +4897,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
|
|
||||||
case i2b: {
|
case i2b: {
|
||||||
frame->pushInt(c->truncateThenExtend(
|
frame->pushInt(c->truncateThenExtend(
|
||||||
ir::SignExtend, types.address, types.i1, frame->popInt()));
|
ir::SignExtend, types.i4, types.i1, frame->popInt()));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case i2c: {
|
case i2c: {
|
||||||
frame->pushInt(c->truncateThenExtend(
|
frame->pushInt(c->truncateThenExtend(
|
||||||
ir::ZeroExtend, types.address, types.i2, frame->popInt()));
|
ir::ZeroExtend, types.i4, types.i2, frame->popInt()));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case i2d: {
|
case i2d: {
|
||||||
@ -4892,7 +4920,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
|
|
||||||
case i2s: {
|
case i2s: {
|
||||||
frame->pushInt(c->truncateThenExtend(
|
frame->pushInt(c->truncateThenExtend(
|
||||||
ir::SignExtend, types.address, types.i2, frame->popInt()));
|
ir::SignExtend, types.i4, types.i2, frame->popInt()));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case iadd:
|
case iadd:
|
||||||
@ -5033,6 +5061,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
|
|
||||||
storeLocal(context,
|
storeLocal(context,
|
||||||
1,
|
1,
|
||||||
|
types.i4,
|
||||||
c->binaryOp(lir::Add,
|
c->binaryOp(lir::Add,
|
||||||
types.i4,
|
types.i4,
|
||||||
c->constant(count, types.i4),
|
c->constant(count, types.i4),
|
||||||
@ -5324,29 +5353,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
} goto next;
|
} goto next;
|
||||||
|
|
||||||
case istore:
|
case istore:
|
||||||
case fstore:
|
|
||||||
frame->storeInt(codeBody(t, code, ip++));
|
frame->storeInt(codeBody(t, code, ip++));
|
||||||
break;
|
break;
|
||||||
|
case fstore:
|
||||||
|
frame->storeFloat(codeBody(t, code, ip++));
|
||||||
|
break;
|
||||||
|
|
||||||
case istore_0:
|
case istore_0:
|
||||||
case fstore_0:
|
|
||||||
frame->storeInt(0);
|
frame->storeInt(0);
|
||||||
break;
|
break;
|
||||||
|
case fstore_0:
|
||||||
|
frame->storeFloat(0);
|
||||||
|
break;
|
||||||
|
|
||||||
case istore_1:
|
case istore_1:
|
||||||
case fstore_1:
|
|
||||||
frame->storeInt(1);
|
frame->storeInt(1);
|
||||||
break;
|
break;
|
||||||
|
case fstore_1:
|
||||||
|
frame->storeFloat(1);
|
||||||
|
break;
|
||||||
|
|
||||||
case istore_2:
|
case istore_2:
|
||||||
case fstore_2:
|
|
||||||
frame->storeInt(2);
|
frame->storeInt(2);
|
||||||
break;
|
break;
|
||||||
|
case fstore_2:
|
||||||
|
frame->storeFloat(2);
|
||||||
|
break;
|
||||||
|
|
||||||
case istore_3:
|
case istore_3:
|
||||||
case fstore_3:
|
|
||||||
frame->storeInt(3);
|
frame->storeInt(3);
|
||||||
break;
|
break;
|
||||||
|
case fstore_3:
|
||||||
|
frame->storeFloat(3);
|
||||||
|
break;
|
||||||
|
|
||||||
case jsr:
|
case jsr:
|
||||||
case jsr_w: {
|
case jsr_w: {
|
||||||
@ -5648,29 +5687,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case lstore:
|
case lstore:
|
||||||
case dstore:
|
|
||||||
frame->storeLong(codeBody(t, code, ip++));
|
frame->storeLong(codeBody(t, code, ip++));
|
||||||
break;
|
break;
|
||||||
|
case dstore:
|
||||||
|
frame->storeDouble(codeBody(t, code, ip++));
|
||||||
|
break;
|
||||||
|
|
||||||
case lstore_0:
|
case lstore_0:
|
||||||
case dstore_0:
|
|
||||||
frame->storeLong(0);
|
frame->storeLong(0);
|
||||||
break;
|
break;
|
||||||
|
case dstore_0:
|
||||||
|
frame->storeDouble(0);
|
||||||
|
break;
|
||||||
|
|
||||||
case lstore_1:
|
case lstore_1:
|
||||||
case dstore_1:
|
|
||||||
frame->storeLong(1);
|
frame->storeLong(1);
|
||||||
break;
|
break;
|
||||||
|
case dstore_1:
|
||||||
|
frame->storeDouble(1);
|
||||||
|
break;
|
||||||
|
|
||||||
case lstore_2:
|
case lstore_2:
|
||||||
case dstore_2:
|
|
||||||
frame->storeLong(2);
|
frame->storeLong(2);
|
||||||
break;
|
break;
|
||||||
|
case dstore_2:
|
||||||
|
frame->storeDouble(2);
|
||||||
|
break;
|
||||||
|
|
||||||
case lstore_3:
|
case lstore_3:
|
||||||
case dstore_3:
|
|
||||||
frame->storeLong(3);
|
frame->storeLong(3);
|
||||||
break;
|
break;
|
||||||
|
case dstore_3:
|
||||||
|
frame->storeDouble(3);
|
||||||
|
break;
|
||||||
|
|
||||||
case monitorenter: {
|
case monitorenter: {
|
||||||
ir::Value* target = frame->popObject();
|
ir::Value* target = frame->popObject();
|
||||||
@ -6152,6 +6201,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
|
|||||||
|
|
||||||
storeLocal(context,
|
storeLocal(context,
|
||||||
1,
|
1,
|
||||||
|
types.i4,
|
||||||
c->binaryOp(lir::Add,
|
c->binaryOp(lir::Add,
|
||||||
types.i4,
|
types.i4,
|
||||||
c->constant(count, types.i4),
|
c->constant(count, types.i4),
|
||||||
|
Reference in New Issue
Block a user