fix issue 37: missing type check when assigning values to array elements

pull/81/head
Dibyendu Majumdar 9 years ago
parent c7126c8e7f
commit 9573fb6c5b

@ -288,10 +288,13 @@ OP_RAVI_SETUPVALF, /* A B UpValue[B] := tonumber(R(A)) */
OP_RAVI_SETUPVALAI, /* A B UpValue[B] := toarrayint(R(A)) */
OP_RAVI_SETUPVALAF, /* A B UpValue[B] := toarrayflt(R(A)) */
OP_RAVI_SETTABLE_AII,/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of ints, and RK(C) is an int */
OP_RAVI_SETTABLE_AFF,/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of floats, and RK(C) is an float */
} OpCode;
#define NUM_OPCODES (cast(int, OP_RAVI_SETUPVALAF) + 1)
#define NUM_OPCODES (cast(int, OP_RAVI_SETTABLE_AFF) + 1)
/*===========================================================================
Notes:

@ -737,6 +737,10 @@ public:
llvm::Value *emit_boolean_testfalse(RaviFunctionDef *def, llvm::Value *reg,
bool donot);
llvm::Instruction *emit_tointeger(RaviFunctionDef *def, llvm::Value *reg);
llvm::Instruction *emit_tofloat(RaviFunctionDef *def, llvm::Value *reg);
// L->top = ci->top
void emit_refresh_L_top(RaviFunctionDef *def);
@ -987,10 +991,10 @@ public:
llvm::Value *proto, int A, int B, int C);
void emit_SETTABLE_AF(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C);
llvm::Value *proto, int A, int B, int C, bool known_int);
void emit_SETTABLE_AI(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C);
llvm::Value *proto, int A, int B, int C, bool known_float);
void emit_MOVEAI(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B);

@ -6,8 +6,8 @@ local function fannkuch(n1)
local n:integer = 11
local p: integer[], q :integer[], s: integer[], sign: integer, maxflips: integer, sum: integer = {}, {}, {}, 1, 0, 0
for i=1,n do
p[i] = i;
q[i] = i;
p[i] = i
q[i] = i
s[i] = i
end
repeat

@ -165,7 +165,7 @@ function tryme()
end
return j
end
-- assert(ravi.compile(tryme))
assert(ravi.compile(tryme))
assert(tryme() == 55.0)
print("test 12 OK")

@ -758,10 +758,19 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
if (op == OP_SETTABLE) {
/* table value set - if array access then use specialized versions */
if (var->ravi_type == RAVI_TARRAYFLT && var->u.ind.key_type == RAVI_TNUMINT)
op = OP_RAVI_SETTABLE_AF;
else if (var->ravi_type == RAVI_TARRAYINT && var->u.ind.key_type == RAVI_TNUMINT)
op = OP_RAVI_SETTABLE_AI;
if (var->ravi_type == RAVI_TARRAYFLT &&
var->u.ind.key_type == RAVI_TNUMINT) {
if (!(ex->ravi_type == RAVI_TNUMFLT || ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYFLT))
op = OP_RAVI_SETTABLE_AF;
else
op = OP_RAVI_SETTABLE_AFF;
} else if (var->ravi_type == RAVI_TARRAYINT &&
var->u.ind.key_type == RAVI_TNUMINT) {
if (!(ex->ravi_type == RAVI_TNUMINT || ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYINT))
op = OP_RAVI_SETTABLE_AI;
else
op = OP_RAVI_SETTABLE_AII;
}
}
int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);

@ -131,6 +131,9 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"SETUPVALAI",
"SETUPVALAF",
"SETTABLE_AII",/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of ints, and RK(C) is an int */
"SETTABLE_AFF",/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of floats, and RK(C) is an float */
NULL
};
@ -247,6 +250,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
, opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RAVI_SETUPVALAI */
, opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RAVI_SETUPVALAF */
, opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLE_AII A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of ints, and RK(C) is an int */
, opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLE_AFF A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of floats, and RK(C) is an float */
};

@ -1448,8 +1448,27 @@ newframe: /* reentry point when frame changes (call/return) */
TValue *rb = RKB(i);
TValue *rc = RKC(i);
lua_Integer idx = ivalue(rb);
lua_Integer value = ivalue(rc);
raviH_set_int_inline(L, t, idx, value);
if (ttisinteger(rc)) {
raviH_set_int_inline(L, t, idx, ivalue(rc));
}
else if (ttisfloat(rc)) {
raviH_set_int_inline(L, t, idx, (lua_Integer) fltvalue(rc));
}
else {
lua_Integer j;
if (tointeger(rc, &j)) {
raviH_set_int_inline(L, t, idx, j);
}
else
luaG_runerror(L, "integer expected");
}
} break;
case OP_RAVI_SETTABLE_AII: {
Table *t = hvalue(ra);
TValue *rb = RKB(i);
TValue *rc = RKC(i);
lua_Integer idx = ivalue(rb);
raviH_set_int_inline(L, t, idx, ivalue(rc));
} break;
case OP_RAVI_SETTABLE_AF: {
Table *t = hvalue(ra);
@ -1459,9 +1478,24 @@ newframe: /* reentry point when frame changes (call/return) */
if (ttisfloat(rc)) {
raviH_set_float_inline(L, t, idx, fltvalue(rc));
}
else {
else if (ttisinteger(rc)) {
raviH_set_float_inline(L, t, idx, ((lua_Number)ivalue(rc)));
}
else {
lua_Number j;
if (tonumber(rc, &j)) {
raviH_set_float_inline(L, t, idx, j);
}
else
luaG_runerror(L, "number expected");
}
} break;
case OP_RAVI_SETTABLE_AFF: {
Table *t = hvalue(ra);
TValue *rb = RKB(i);
TValue *rc = RKC(i);
lua_Integer idx = ivalue(rb);
raviH_set_float_inline(L, t, idx, fltvalue(rc));
} break;
case OP_RAVI_SETUPVALI: {

@ -147,8 +147,8 @@ llvm::Instruction *RaviCodeGenerator::emit_load_base(RaviFunctionDef *def) {
// emit code to obtain address of register at location A
llvm::Value *RaviCodeGenerator::emit_gep_register(RaviFunctionDef *def,
llvm::Instruction *base_ptr,
int A) {
llvm::Instruction *base_ptr,
int A) {
llvm::Value *dest;
if (A == 0) {
// If A is 0 we can use the base pointer which is &base[0]
@ -170,7 +170,7 @@ llvm::Instruction *RaviCodeGenerator::emit_load_reg_n(RaviFunctionDef *def,
lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_pdoubleT);
#else
llvm::Value *rb_n = def->builder->CreateBitCast(rb, def->types->plua_NumberT);
//llvm::Value *rb_n = emit_gep(def, "value.value_.n", rb, 0, 0, 0);
// llvm::Value *rb_n = emit_gep(def, "value.value_.n", rb, 0, 0, 0);
llvm::Instruction *lhs = def->builder->CreateLoad(rb_n);
lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
#endif
@ -238,7 +238,7 @@ void RaviCodeGenerator::emit_store_reg_n(RaviFunctionDef *def,
#else
llvm::Value *ra_n =
def->builder->CreateBitCast(dest_ptr, def->types->plua_NumberT);
//llvm::Value *ra_n = emit_gep(def, "value.value_.n", dest_ptr, 0, 0, 0);
// llvm::Value *ra_n = emit_gep(def, "value.value_.n", dest_ptr, 0, 0, 0);
llvm::Instruction *store = def->builder->CreateStore(result, ra_n);
store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
#endif
@ -399,9 +399,8 @@ llvm::Instruction *RaviCodeGenerator::emit_load_local_int(RaviFunctionDef *def,
}
// emit code to obtain address of register or constant at location B
llvm::Value *RaviCodeGenerator::emit_gep_register_or_constant(RaviFunctionDef *def,
llvm::Instruction *base_ptr,
int B) {
llvm::Value *RaviCodeGenerator::emit_gep_register_or_constant(
RaviFunctionDef *def, llvm::Instruction *base_ptr, int B) {
// Load pointer to k
llvm::Value *k_ptr = def->k_ptr;
llvm::Value *rb;
@ -436,7 +435,7 @@ void RaviCodeGenerator::emit_refresh_L_top(RaviFunctionDef *def) {
llvm::Value *RaviCodeGenerator::emit_gep_L_top(RaviFunctionDef *def) {
// Get pointer to L->top
return emit_gep(def, "L.top", def->L, 0, 4);
return emit_gep(def, "L.top", def->L, 0, 4);
}
// L->top = R(B)
@ -452,16 +451,131 @@ void RaviCodeGenerator::emit_set_L_top_toreg(RaviFunctionDef *def,
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_luaState_topT);
}
llvm::Instruction *RaviCodeGenerator::emit_tointeger(RaviFunctionDef *def,
llvm::Value *reg) {
llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
llvm::Value *value =
TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "value");
llvm::Value *reg_type = emit_load_type(def, reg);
// Is reg an integer?
llvm::Value *cmp1 =
emit_is_value_of_type(def, reg_type, LUA__TNUMINT, "reg.is.integer");
llvm::BasicBlock *convert_reg =
llvm::BasicBlock::Create(def->jitState->context(), "convert.reg");
llvm::BasicBlock *copy_reg =
llvm::BasicBlock::Create(def->jitState->context(), "copy.reg");
llvm::BasicBlock *load_val =
llvm::BasicBlock::Create(def->jitState->context(), "load.val");
llvm::BasicBlock *failed_conversion = llvm::BasicBlock::Create(
def->jitState->context(), "if.conversion.failed");
// If reg is integer then copy reg, else convert reg
def->builder->CreateCondBr(cmp1, copy_reg, convert_reg);
// Convert RB
def->f->getBasicBlockList().push_back(convert_reg);
def->builder->SetInsertPoint(convert_reg);
llvm::Value *var_isint =
CreateCall2(def->builder, def->luaV_tointegerF, reg, value);
llvm::Value *tobool = def->builder->CreateICmpEQ(
var_isint, def->types->kInt[0], "conversion.failed");
// Did conversion fail?
def->builder->CreateCondBr(tobool, failed_conversion, load_val);
// Conversion failed, so raise error
def->f->getBasicBlockList().push_back(failed_conversion);
def->builder->SetInsertPoint(failed_conversion);
emit_raise_lua_error(def, "integer expected");
def->builder->CreateBr(load_val);
// Conversion OK
def->f->getBasicBlockList().push_back(copy_reg);
def->builder->SetInsertPoint(copy_reg);
llvm::Value *i = emit_load_reg_i(def, reg);
emit_store_local_int(def, i, value);
def->builder->CreateBr(load_val);
def->f->getBasicBlockList().push_back(load_val);
def->builder->SetInsertPoint(load_val);
return emit_load_local_int(def, value);
}
llvm::Instruction *RaviCodeGenerator::emit_tofloat(RaviFunctionDef *def,
llvm::Value *reg) {
llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
llvm::Value *value =
TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "value");
llvm::Value *reg_type = emit_load_type(def, reg);
// Is reg an number?
llvm::Value *cmp1 =
emit_is_value_of_type(def, reg_type, LUA__TNUMFLT, "reg.is.float");
llvm::BasicBlock *convert_reg =
llvm::BasicBlock::Create(def->jitState->context(), "convert.reg");
llvm::BasicBlock *copy_reg =
llvm::BasicBlock::Create(def->jitState->context(), "copy.reg");
llvm::BasicBlock *load_val =
llvm::BasicBlock::Create(def->jitState->context(), "load.val");
llvm::BasicBlock *failed_conversion = llvm::BasicBlock::Create(
def->jitState->context(), "if.conversion.failed");
// If reg is integer then copy reg, else convert reg
def->builder->CreateCondBr(cmp1, copy_reg, convert_reg);
// Convert RB
def->f->getBasicBlockList().push_back(convert_reg);
def->builder->SetInsertPoint(convert_reg);
llvm::Value *var_isfloat =
CreateCall2(def->builder, def->luaV_tonumberF, reg, value);
llvm::Value *tobool = def->builder->CreateICmpEQ(
var_isfloat, def->types->kInt[0], "conversion.failed");
// Did conversion fail?
def->builder->CreateCondBr(tobool, failed_conversion, load_val);
// Conversion failed, so raise error
def->f->getBasicBlockList().push_back(failed_conversion);
def->builder->SetInsertPoint(failed_conversion);
emit_raise_lua_error(def, "number expected");
def->builder->CreateBr(load_val);
// Conversion OK
def->f->getBasicBlockList().push_back(copy_reg);
def->builder->SetInsertPoint(copy_reg);
llvm::Value *i = emit_load_reg_n(def, reg);
emit_store_local_n(def, i, value);
def->builder->CreateBr(load_val);
def->f->getBasicBlockList().push_back(load_val);
def->builder->SetInsertPoint(load_val);
return emit_load_local_n(def, value);
}
// (int)(L->top - ra)
llvm::Value *RaviCodeGenerator::emit_num_stack_elements(RaviFunctionDef *def, llvm::Value *L_top, llvm::Value *ra) {
llvm::Value *RaviCodeGenerator::emit_num_stack_elements(RaviFunctionDef *def,
llvm::Value *L_top,
llvm::Value *ra) {
llvm::Instruction *top_ptr = def->builder->CreateLoad(L_top, "L_top");
llvm::Value *top_asint = def->builder->CreatePtrToInt(top_ptr, def->types->C_intptr_t, "L_top_as_intptr");
llvm::Value *ra_asint = def->builder->CreatePtrToInt(ra, def->types->C_intptr_t, "ra_as_intptr");
llvm::Value *result = def->builder->CreateSub(top_asint, ra_asint, "num_stack_elements");
return def->builder->CreateTrunc(result, def->types->C_intT, "num_stack_elements");
llvm::Value *top_asint = def->builder->CreatePtrToInt(
top_ptr, def->types->C_intptr_t, "L_top_as_intptr");
llvm::Value *ra_asint =
def->builder->CreatePtrToInt(ra, def->types->C_intptr_t, "ra_as_intptr");
llvm::Value *result =
def->builder->CreateSub(top_asint, ra_asint, "num_stack_elements");
return def->builder->CreateTrunc(result, def->types->C_intT,
"num_stack_elements");
}
// Check if we can compile
// The cases we can compile will increase over time
bool RaviCodeGenerator::canCompile(Proto *p) {
@ -552,7 +666,9 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_RAVI_GETTABLE_AI:
case OP_RAVI_GETTABLE_AF:
case OP_RAVI_SETTABLE_AI:
case OP_RAVI_SETTABLE_AII:
case OP_RAVI_SETTABLE_AF:
case OP_RAVI_SETTABLE_AFF:
case OP_RAVI_TOARRAYI:
case OP_RAVI_TOARRAYF:
case OP_RAVI_MOVEAI:
@ -1125,20 +1241,22 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p, bool doDump,
int C = GETARG_C(i);
emit_GETTABLE_AI(def, L_ci, proto, A, B, C);
} break;
case OP_RAVI_SETTABLE_AII:
case OP_RAVI_SETTABLE_AI: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_SETTABLE_AI(def, L_ci, proto, A, B, C);
emit_SETTABLE_AI(def, L_ci, proto, A, B, C, op == OP_RAVI_SETTABLE_AII);
} break;
case OP_RAVI_GETTABLE_AF: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_GETTABLE_AF(def, L_ci, proto, A, B, C);
} break;
case OP_RAVI_SETTABLE_AFF:
case OP_RAVI_SETTABLE_AF: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_SETTABLE_AF(def, L_ci, proto, A, B, C);
emit_SETTABLE_AF(def, L_ci, proto, A, B, C, op == OP_RAVI_SETTABLE_AFF);
} break;
case OP_RAVI_TOARRAYI: {
emit_TOARRAY(def, L_ci, proto, A, RAVI_TARRAYINT, "integer[] expected");

@ -186,7 +186,7 @@ void RaviCodeGenerator::emit_GETTABLE_AI(RaviFunctionDef *def,
void RaviCodeGenerator::emit_SETTABLE_AI(RaviFunctionDef *def,
llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C) {
int A, int B, int C, bool known_int) {
//#define raviH_set_int_inline(L, t, key, value)
//{ unsigned ukey = (unsigned)((key));
@ -209,7 +209,7 @@ void RaviCodeGenerator::emit_SETTABLE_AI(RaviFunctionDef *def,
llvm::Value *rb = emit_gep_register_or_constant(def, base_ptr, B);
llvm::Value *rc = emit_gep_register_or_constant(def, base_ptr, C);
llvm::Instruction *key = emit_load_reg_i(def, rb);
llvm::Instruction *value = emit_load_reg_i(def, rc);
llvm::Instruction *value = known_int ? emit_load_reg_i(def, rc) : emit_tointeger(def, rc);
llvm::Instruction *t = emit_load_reg_h(def, ra);
llvm::Instruction *data = emit_load_reg_h_intarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
@ -243,7 +243,7 @@ void RaviCodeGenerator::emit_SETTABLE_AI(RaviFunctionDef *def,
void RaviCodeGenerator::emit_SETTABLE_AF(RaviFunctionDef *def,
llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C) {
int A, int B, int C, bool known_float) {
//#define raviH_set_float_inline(L, t, key, value)
//{ unsigned ukey = (unsigned)((key));
@ -273,53 +273,13 @@ void RaviCodeGenerator::emit_SETTABLE_AF(RaviFunctionDef *def,
llvm::Value *rb = emit_gep_register_or_constant(def, base_ptr, B);
llvm::Value *rc = emit_gep_register_or_constant(def, base_ptr, C);
llvm::Instruction *key = emit_load_reg_i(def, rb);
llvm::Instruction *rc_type = emit_load_type(def, rc);
// Is RC a float?
llvm::Value *cmp =
emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rc.is.float");
llvm::BasicBlock *convert_rc =
llvm::BasicBlock::Create(def->jitState->context(), "convert.rc");
llvm::BasicBlock *load_rc =
llvm::BasicBlock::Create(def->jitState->context(), "load.rc");
llvm::BasicBlock *set_af =
llvm::BasicBlock::Create(def->jitState->context(), "set.af");
// If RC is floating then load RC, else convert RC
def->builder->CreateCondBr(cmp, load_rc, convert_rc);
// Load RC
def->f->getBasicBlockList().push_back(load_rc);
def->builder->SetInsertPoint(load_rc);
// Copy RC to local
auto src = emit_load_reg_n(def, rc);
emit_store_local_n(def, src, nc);
def->builder->CreateBr(set_af);
// Convert int to float
def->f->getBasicBlockList().push_back(convert_rc);
def->builder->SetInsertPoint(convert_rc);
llvm::Instruction *ivalue = emit_load_reg_i(def, rc);
llvm::Value *floatvalue =
def->builder->CreateSIToFP(ivalue, def->types->lua_NumberT);
emit_store_local_n(def, floatvalue, nc);
def->builder->CreateBr(set_af);
def->f->getBasicBlockList().push_back(set_af);
def->builder->SetInsertPoint(set_af);
llvm::Instruction *load_nc = emit_load_local_n(def, nc);
llvm::Instruction *value = known_float ? emit_load_reg_n(def, rc) : emit_tofloat(def, rc);
llvm::Instruction *t = emit_load_reg_h(def, ra);
llvm::Instruction *data = emit_load_reg_h_floatarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *ukey = def->builder->CreateTrunc(key, def->types->C_intT);
cmp = def->builder->CreateICmpULT(ukey, len);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.in.range", def->f);
llvm::BasicBlock *else_block =
@ -331,14 +291,14 @@ void RaviCodeGenerator::emit_SETTABLE_AF(RaviFunctionDef *def,
llvm::Value *ptr = def->builder->CreateGEP(data, ukey);
llvm::Instruction *storeinst = def->builder->CreateStore(load_nc, ptr);
llvm::Instruction *storeinst = def->builder->CreateStore(value, ptr);
storeinst->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_pdoubleT);
def->builder->CreateBr(end_block);
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
CreateCall4(def->builder, def->raviH_set_floatF, def->L, t, ukey, load_nc);
CreateCall4(def->builder, def->raviH_set_floatF, def->L, t, ukey, value);
def->builder->CreateBr(end_block);
def->f->getBasicBlockList().push_back(end_block);

Loading…
Cancel
Save