@@ -318,6 +318,51 @@ auto FunctionContext::GetReturnTypeInfo(TypeInFile type)
318
318
return result;
319
319
}
320
320
321
+ // Given a type used for an LLVM value, return the type that we use to store
322
+ // that value in memory. This is the same type unless the type is a
323
+ // non-multiple-of-8 integer type, which we explicitly widen to a multiple of 8
324
+ // for Clang compatibility and to make our generated IR easier for LLVM to
325
+ // handle.
326
+ static auto GetWidenedMemoryType (llvm::Type* type) -> llvm::Type* {
327
+ if (auto * int_type = dyn_cast<llvm::IntegerType>(type)) {
328
+ auto width = llvm::alignToPowerOf2 (int_type->getBitWidth (), 8 );
329
+ if (width != int_type->getBitWidth ()) {
330
+ return llvm::IntegerType::get (type->getContext (), width);
331
+ }
332
+ }
333
+ return type;
334
+ }
335
+
336
+ auto FunctionContext::LoadObject (TypeInFile type, llvm::Value* addr,
337
+ llvm::Twine name) -> llvm::Value* {
338
+ auto * llvm_type = GetType (type);
339
+ auto * load_type = GetWidenedMemoryType (llvm_type);
340
+
341
+ // TODO: Include alias and alignment information.
342
+ llvm::Value* value = builder ().CreateLoad (load_type, addr, name);
343
+
344
+ if (load_type != llvm_type) {
345
+ value = builder ().CreateTrunc (value, llvm_type);
346
+ }
347
+ return value;
348
+ }
349
+
350
+ auto FunctionContext::StoreObject (TypeInFile type, llvm::Value* value,
351
+ llvm::Value* addr) -> void {
352
+ // TODO: Include alias and alignment information.
353
+ auto * llvm_type = GetType (type);
354
+ CARBON_CHECK (value->getType () == llvm_type);
355
+
356
+ // Don't emit a store of `iN` if N is not a multiple of 8. See `LoadObject`.
357
+ auto * store_type = GetWidenedMemoryType (llvm_type);
358
+ if (store_type != llvm_type) {
359
+ // TODO: Should we consider creating a sext if the value is signed?
360
+ value = builder ().CreateZExt (value, store_type);
361
+ }
362
+
363
+ builder ().CreateStore (value, addr);
364
+ }
365
+
321
366
auto FunctionContext::CopyValue (TypeInFile type, SemIR::InstId source_id,
322
367
SemIR::InstId dest_id) -> void {
323
368
switch (GetValueRepr (type).repr .kind ) {
@@ -326,7 +371,7 @@ auto FunctionContext::CopyValue(TypeInFile type, SemIR::InstId source_id,
326
371
case SemIR::ValueRepr::None:
327
372
break ;
328
373
case SemIR::ValueRepr::Copy:
329
- builder (). CreateStore ( GetValue (source_id), GetValue (dest_id));
374
+ StoreObject (type, GetValue (source_id), GetValue (dest_id));
330
375
break ;
331
376
case SemIR::ValueRepr::Pointer:
332
377
CopyObject (type, source_id, dest_id);
0 commit comments