Skip to content

Commit 9e52737

Browse files
committed
done
1 parent 8ee5af9 commit 9e52737

File tree

5 files changed

+138
-59
lines changed

5 files changed

+138
-59
lines changed

integration_tests/test_list_01.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
from ltypes import i32
22

33
def test_list_i32():
4-
a: list[i32]
5-
a = [0, 1, 2, 3, 4]
6-
# i: i32
4+
a: list[i32] = [0, 1, 2, 3, 4]
5+
i: i32
76

8-
# for i in range(10):
9-
# a.append(i + 5)
7+
for i in range(10):
8+
a.append(i + 5)
109

11-
# for i in range(15):
12-
# assert a[i] == i
10+
for i in range(15):
11+
assert a[i] == i
1312

1413
test_list_i32()

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,71 +1143,48 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
11431143
}
11441144

11451145
void visit_ListConstant(const ASR::ListConstant_t& x) {
1146-
llvm::Value* initial_capacity = llvm::ConstantInt::get(context, llvm::APInt(32, x.n_args));
11471146
ASR::List_t* list_type = ASR::down_cast<ASR::List_t>(x.m_type);
11481147
llvm::Type* llvm_el_type = get_el_type(list_type->m_type);
11491148
std::string type_code = ASRUtils::get_type_code(list_type->m_type);
11501149
int32_t type_size = ASRUtils::extract_kind_from_ttype_t(list_type->m_type);
1151-
llvm::Type* const_list_type = list_api->get_list_type(el_type, type_code, type_size);
1150+
llvm::Type* const_list_type = list_api->get_list_type(llvm_el_type, type_code, type_size);
11521151
llvm::Value* const_list = builder->CreateAlloca(const_list_type, nullptr, "const_list");
11531152
list_api->list_init(type_code, const_list, *module, x.n_args, x.n_args);
11541153
for( size_t i = 0; i < x.n_args; i++ ) {
11551154
this->visit_expr(*x.m_args[i]);
11561155
llvm::Value* item = tmp;
11571156
llvm::Value* pos = llvm::ConstantInt::get(context, llvm::APInt(32, i));
1158-
list_api->write_item(const_list, pos, item, "i32");
1157+
list_api->write_item(const_list, pos, item);
11591158
}
11601159
tmp = const_list;
11611160
}
11621161

11631162
void visit_ListAppend(const ASR::ListAppend_t& x) {
1164-
ASR::Variable_t *l = EXPR2VAR(x.m_a);
1165-
uint32_t v_h = get_hash((ASR::asr_t*)l);
1166-
LFORTRAN_ASSERT(llvm_symtab.find(v_h) != llvm_symtab.end());
1167-
llvm::Value *plist = llvm_symtab[v_h];
1163+
uint64_t ptr_loads_copy = ptr_loads;
1164+
ptr_loads = 0;
1165+
this->visit_expr(*x.m_a);
1166+
ptr_loads = ptr_loads_copy;
1167+
llvm::Value* plist = tmp;
11681168

11691169
this->visit_expr_wrapper(x.m_ele, true);
1170-
llvm::Value *ele = tmp;
1171-
1172-
ASR::ttype_t *el_type = ASR::down_cast<ASR::List_t>(l->m_type)->m_type;
1173-
if (is_a<ASR::Integer_t>(*el_type)) {
1174-
int kind = ASR::down_cast<ASR::Integer_t>(el_type)->m_kind;
1175-
if (kind == 4) {
1176-
llvm::Value *plist2 = CreateLoad(plist);
1177-
lcompilers_list_append(plist2, ele, get_el_type(el_type), "i32");
1178-
} else {
1179-
throw CodeGenError("Integer kind not supported yet in ListAppend", x.base.base.loc);
1180-
}
1181-
1182-
} else {
1183-
throw CodeGenError("List type not supported yet in ListAppend", x.base.base.loc);
1184-
}
1170+
llvm::Value *item = tmp;
11851171

1172+
ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(ASRUtils::expr_type(x.m_a));
1173+
std::string type_code = ASRUtils::get_type_code(asr_list->m_type);
1174+
list_api->append(plist, item, *module, type_code);
11861175
}
11871176

11881177
void visit_ListItem(const ASR::ListItem_t& x) {
1189-
ASR::Variable_t *l = EXPR2VAR(x.m_a);
1190-
uint32_t v_h = get_hash((ASR::asr_t*)l);
1191-
LFORTRAN_ASSERT(llvm_symtab.find(v_h) != llvm_symtab.end());
1192-
llvm::Value *plist = llvm_symtab[v_h];
1178+
uint64_t ptr_loads_copy = ptr_loads;
1179+
ptr_loads = 0;
1180+
this->visit_expr(*x.m_a);
1181+
ptr_loads = ptr_loads_copy;
1182+
llvm::Value* plist = tmp;
11931183

11941184
this->visit_expr_wrapper(x.m_pos, true);
11951185
llvm::Value *pos = tmp;
11961186

1197-
ASR::ttype_t *el_type = ASR::down_cast<ASR::List_t>(l->m_type)->m_type;
1198-
if (is_a<ASR::Integer_t>(*el_type)) {
1199-
int kind = ASR::down_cast<ASR::Integer_t>(el_type)->m_kind;
1200-
if (kind == 4) {
1201-
llvm::Value *plist2 = CreateLoad(plist);
1202-
tmp = lcompilers_list_item(plist2, pos, get_el_type(el_type), "i32");
1203-
} else {
1204-
throw CodeGenError("Integer kind not supported as index in ListItem", x.base.base.loc);
1205-
}
1206-
1207-
} else {
1208-
throw CodeGenError("List type not supported yet in ListItem", x.base.base.loc);
1209-
}
1210-
1187+
tmp = list_api->read_item(plist, pos);
12111188
}
12121189

12131190
void visit_ArrayItem(const ASR::ArrayItem_t& x) {
@@ -2856,10 +2833,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
28562833
bool is_target_list = ASR::is_a<ASR::List_t>(*ASRUtils::expr_type(x.m_target));
28572834
bool is_value_list = ASR::is_a<ASR::List_t>(*ASRUtils::expr_type(x.m_value));
28582835
if( is_target_list && is_value_list ) {
2836+
uint64_t ptr_loads_copy = ptr_loads;
2837+
ptr_loads = 0;
28592838
this->visit_expr(*x.m_target);
28602839
llvm::Value* target_list = tmp;
28612840
this->visit_expr(*x.m_value);
28622841
llvm::Value* value_list = tmp;
2842+
ptr_loads = ptr_loads_copy;
28632843
ASR::List_t* value_asr_list = ASR::down_cast<ASR::List_t>(
28642844
ASRUtils::expr_type(x.m_value));
28652845
std::string value_type_code = ASRUtils::get_type_code(value_asr_list->m_type);

src/libasr/codegen/llvm_utils.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ namespace LFortran {
4747
std::vector<llvm::Value*> args = {arg_size};
4848
return builder.CreateCall(fn, args);
4949
}
50+
51+
llvm::Value* lfortran_realloc(llvm::LLVMContext &context, llvm::Module &module,
52+
llvm::IRBuilder<> &builder, llvm::Value* ptr, llvm::Value* arg_size) {
53+
std::string func_name = "_lfortran_realloc";
54+
llvm::Function *fn = module.getFunction(func_name);
55+
if (!fn) {
56+
llvm::FunctionType *function_type = llvm::FunctionType::get(
57+
llvm::Type::getInt8PtrTy(context), {
58+
llvm::Type::getInt8PtrTy(context),
59+
llvm::Type::getInt32Ty(context)
60+
}, true);
61+
fn = llvm::Function::Create(function_type,
62+
llvm::Function::ExternalLinkage, func_name, module);
63+
}
64+
std::vector<llvm::Value*> args = {
65+
builder.CreateBitCast(ptr, llvm::Type::getInt8PtrTy(context)),
66+
arg_size
67+
};
68+
return builder.CreateCall(fn, args);
69+
}
5070
} // namespace LLVM
5171

5272
LLVMUtils::LLVMUtils(llvm::LLVMContext& context,
@@ -191,6 +211,7 @@ namespace LFortran {
191211
void LLVMList::list_deepcopy(llvm::Value* src, llvm::Value* dest,
192212
std::string& src_type_code,
193213
llvm::Module& module) {
214+
LFORTRAN_ASSERT(src->getType() == dest->getType());
194215
llvm::Value* src_end_point = builder->CreateLoad(get_pointer_to_current_end_point(src));
195216
llvm::Value* src_capacity = builder->CreateLoad(get_pointer_to_current_capacity(src));
196217
llvm::Value* dest_end_point_ptr = get_pointer_to_current_end_point(dest);
@@ -203,9 +224,67 @@ namespace LFortran {
203224
llvm::APInt(32, type_size)), src_capacity);
204225
llvm::Value* copy_data = LLVM::lfortran_malloc(context, module, *builder,
205226
arg_size);
227+
llvm::Type* el_type = std::get<2>(typecode2listtype[src_type_code]);
228+
copy_data = builder->CreateBitCast(copy_data, el_type->getPointerTo());
206229
builder->CreateMemCpy(copy_data, llvm::MaybeAlign(), src_data,
207230
llvm::MaybeAlign(), arg_size);
208231
builder->CreateStore(copy_data, get_pointer_to_list_data(dest));
209232
}
210233

234+
void LLVMList::write_item(llvm::Value* list, llvm::Value* pos, llvm::Value* item) {
235+
llvm::Value* list_data = builder->CreateLoad(get_pointer_to_list_data(list));
236+
llvm::Value* element_ptr = llvm_utils->create_ptr_gep(list_data, pos);
237+
builder->CreateStore(item, element_ptr);
238+
}
239+
240+
llvm::Value* LLVMList::read_item(llvm::Value* list, llvm::Value* pos) {
241+
llvm::Value* list_data = builder->CreateLoad(get_pointer_to_list_data(list));
242+
llvm::Value* element_ptr = llvm_utils->create_ptr_gep(list_data, pos);
243+
return builder->CreateLoad(element_ptr);
244+
}
245+
246+
void LLVMList::resize_if_needed(llvm::Value* list, llvm::Value* n,
247+
llvm::Value* capacity, int32_t type_size,
248+
llvm::Type* el_type, llvm::Module& module) {
249+
llvm::Value *cond = builder->CreateICmpEQ(n, capacity);
250+
llvm::Function *fn = builder->GetInsertBlock()->getParent();
251+
llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn);
252+
llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else");
253+
llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont");
254+
builder->CreateCondBr(cond, thenBB, elseBB);
255+
builder->SetInsertPoint(thenBB);
256+
llvm::Value* arg_size = builder->CreateMul(llvm::ConstantInt::get(context,
257+
llvm::APInt(32, 2 * type_size)),
258+
capacity);
259+
llvm::Value* copy_data_ptr = get_pointer_to_list_data(list);
260+
llvm::Value* copy_data = builder->CreateLoad(copy_data_ptr);
261+
copy_data = LLVM::lfortran_realloc(context, module, *builder,
262+
copy_data, arg_size);
263+
copy_data = builder->CreateBitCast(copy_data, el_type->getPointerTo());
264+
builder->CreateStore(copy_data, copy_data_ptr);
265+
builder->CreateBr(mergeBB);
266+
llvm_utils->start_new_block(elseBB);
267+
llvm_utils->start_new_block(mergeBB);
268+
}
269+
270+
void LLVMList::shift_end_point_by_one(llvm::Value* list) {
271+
llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list);
272+
llvm::Value* end_point = builder->CreateLoad(end_point_ptr);
273+
end_point = builder->CreateAdd(end_point, llvm::ConstantInt::get(context, llvm::APInt(32, 1)));
274+
builder->CreateStore(end_point, end_point_ptr);
275+
}
276+
277+
void LLVMList::append(llvm::Value* list, llvm::Value* item,
278+
llvm::Module& module,
279+
std::string& type_code) {
280+
llvm::Value* current_end_point = builder->CreateLoad(get_pointer_to_current_end_point(list));
281+
llvm::Value* current_capacity = builder->CreateLoad(get_pointer_to_current_capacity(list));
282+
int type_size = std::get<1>(typecode2listtype[type_code]);
283+
llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]);
284+
resize_if_needed(list, current_end_point, current_capacity,
285+
type_size, el_type, module);
286+
write_item(list, current_end_point, item);
287+
shift_end_point_by_one(list);
288+
}
289+
211290
} // namespace LFortran

src/libasr/codegen/llvm_utils.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ namespace LFortran {
1919
llvm::Value* CreateInBoundsGEP(llvm::IRBuilder<> &builder, llvm::Value *x, std::vector<llvm::Value *> &idx);
2020
llvm::Value* lfortran_malloc(llvm::LLVMContext &context, llvm::Module &module,
2121
llvm::IRBuilder<> &builder, llvm::Value* arg_size);
22+
llvm::Value* lfortran_realloc(llvm::LLVMContext &context, llvm::Module &module,
23+
llvm::IRBuilder<> &builder, llvm::Value* ptr, llvm::Value* arg_size);
2224
}
2325

2426
class LLVMUtils {
@@ -56,25 +58,40 @@ namespace LFortran {
5658

5759
std::map<std::string, std::tuple<llvm::Type*, int32_t, llvm::Type*>> typecode2listtype;
5860

59-
public:
61+
void resize_if_needed(llvm::Value* list, llvm::Value* n,
62+
llvm::Value* capacity, int32_t type_size,
63+
llvm::Type* el_type, llvm::Module& module);
6064

61-
LLVMList(llvm::LLVMContext& context_, LLVMUtils* llvm_utils,
62-
llvm::IRBuilder<>* builder);
65+
void shift_end_point_by_one(llvm::Value* list);
6366

64-
llvm::Type* get_list_type(llvm::Type* el_type, std::string& type_code,
65-
int32_t type_size);
67+
public:
68+
69+
LLVMList(llvm::LLVMContext& context_, LLVMUtils* llvm_utils,
70+
llvm::IRBuilder<>* builder);
71+
72+
llvm::Type* get_list_type(llvm::Type* el_type, std::string& type_code,
73+
int32_t type_size);
74+
75+
void list_init(std::string& type_code, llvm::Value* list,
76+
llvm::Module& module, int32_t initial_capacity=1,
77+
int32_t n=0);
78+
79+
llvm::Value* get_pointer_to_list_data(llvm::Value* list);
80+
81+
llvm::Value* get_pointer_to_current_end_point(llvm::Value* list);
6682

67-
void list_init(std::string& type_code, llvm::Value* list,
68-
llvm::Module& module, int32_t initial_capacity=1,
69-
int32_t n=0);
83+
llvm::Value* get_pointer_to_current_capacity(llvm::Value* list);
7084

71-
llvm::Value* get_pointer_to_list_data(llvm::Value* list);
85+
void list_deepcopy(llvm::Value* src, llvm::Value* dest,
86+
std::string& src_type_code,
87+
llvm::Module& module);
7288

73-
llvm::Value* get_pointer_to_current_end_point(llvm::Value* list);
89+
llvm::Value* read_item(llvm::Value* list, llvm::Value* pos);
7490

75-
llvm::Value* get_pointer_to_current_capacity(llvm::Value* list);
91+
void write_item(llvm::Value* list, llvm::Value* pos, llvm::Value* item);
7692

77-
void list_deepcopy(llvm::Value* src, llvm::Value* dest);
93+
void append(llvm::Value* list, llvm::Value* item,
94+
llvm::Module& module, std::string& type_code);
7895
};
7996

8097
} // LFortran

src/runtime/impure/lfortran_intrinsics.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,10 @@ LFORTRAN_API char* _lfortran_malloc(int size) {
776776
return (char*)malloc(size);
777777
}
778778

779+
LFORTRAN_API int8_t* _lfortran_realloc(int8_t* ptr, int32_t size) {
780+
return (int8_t*) realloc(ptr, size);
781+
}
782+
779783
LFORTRAN_API void _lfortran_free(char* ptr) {
780784
free((void*)ptr);
781785
}

0 commit comments

Comments
 (0)