@@ -47,6 +47,26 @@ namespace LFortran {
47
47
std::vector<llvm::Value*> args = {arg_size};
48
48
return builder.CreateCall (fn, args);
49
49
}
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
+ }
50
70
} // namespace LLVM
51
71
52
72
LLVMUtils::LLVMUtils (llvm::LLVMContext& context,
@@ -191,6 +211,7 @@ namespace LFortran {
191
211
void LLVMList::list_deepcopy (llvm::Value* src, llvm::Value* dest,
192
212
std::string& src_type_code,
193
213
llvm::Module& module ) {
214
+ LFORTRAN_ASSERT (src->getType () == dest->getType ());
194
215
llvm::Value* src_end_point = builder->CreateLoad (get_pointer_to_current_end_point (src));
195
216
llvm::Value* src_capacity = builder->CreateLoad (get_pointer_to_current_capacity (src));
196
217
llvm::Value* dest_end_point_ptr = get_pointer_to_current_end_point (dest);
@@ -203,9 +224,67 @@ namespace LFortran {
203
224
llvm::APInt (32 , type_size)), src_capacity);
204
225
llvm::Value* copy_data = LLVM::lfortran_malloc (context, module , *builder,
205
226
arg_size);
227
+ llvm::Type* el_type = std::get<2 >(typecode2listtype[src_type_code]);
228
+ copy_data = builder->CreateBitCast (copy_data, el_type->getPointerTo ());
206
229
builder->CreateMemCpy (copy_data, llvm::MaybeAlign (), src_data,
207
230
llvm::MaybeAlign (), arg_size);
208
231
builder->CreateStore (copy_data, get_pointer_to_list_data (dest));
209
232
}
210
233
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
+
211
290
} // namespace LFortran
0 commit comments