Unable to lower RelativeAddress/RelativeOffset on 16-bit arch: Assertion failed

I'm getting another compile fail from any code containing even simple structs for 16 bit, with the above error.

Here's the backtrace:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff6055bb66 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff60726080 libsystem_pthread.dylib`pthread_kill + 333
    frame #2: 0x00007fff604b71ae libsystem_c.dylib`abort + 127
    frame #3: 0x00007fff6047f1ac libsystem_c.dylib`__assert_rtn + 320
    frame #4: 0x00000001088f47d8 swift`llvm::ConstantExpr::getTrunc(C=0x000000011683ead0, Ty=0x0000000117845c38, OnlyIfReduced=false) at Constants.cpp:1622
    frame #5: 0x0000000100c401f9 swift`clang::CodeGen::ConstantAggregateBuilderBase::getRelativeOffset(this=0x00007ffeefbf5c70, offsetType=0x0000000117845c38, target=0x000000011683e738) at ConstantInitBuilder.cpp:142
    frame #6: 0x000000010031260a swift`clang::CodeGen::ConstantAggregateBuilderBase::addTaggedRelativeOffset(this=0x00007ffeefbf5c70, type=0x0000000117845c38, address=0x000000011683e5c8, tag=0) at ConstantInitBuilder.h:237
    frame #7: 0x00000001002f8d9a swift`swift::irgen::ConstantAggregateBuilderBase::addRelativeAddress(this=0x00007ffeefbf5c70, reference=ConstantReference @ 0x00007ffeefbf5b08) at ConstantBuilder.h:92
    frame #8: 0x00000001003ee59c swift`(anonymous namespace)::WitnessTableBuilder::buildAccessFunction(this=0x00007ffeefbf6130, wtable=0x000000011683e288) at GenProto.cpp:1996
    frame #9: 0x00000001003edd86 swift`swift::irgen::IRGenModule::emitSILWitnessTable(this=0x00007ffeefbf6e80, wt=0x0000000115843b48) at GenProto.cpp:2252
    frame #10: 0x00000001002fc04e swift`swift::irgen::IRGenerator::emitGlobalTopLevel(this=0x00007ffeefbf8588, emitForParallelEmission=false) at GenDecl.cpp:1084
    frame #11: 0x0000000100483ffd swift`performIRGeneration(Opts=0x00007ffeefbfc180, M=0x000000011581c6a0, SILMod=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbf89b0, ModuleName=(Data = "uSwift.ll", Length = 9), PSPs=0x00007ffeefbfa580, LLVMContext=0x0000000116807920, SF=0x000000011581c758, outModuleHash=0x00007ffeefbf9378, StartElem=0) at IRGen.cpp:795
    frame #12: 0x0000000100484dcb swift`swift::performIRGeneration(Opts=0x00007ffeefbfc180, SF=0x000000011581c758, SILMod=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbf8c78, ModuleName=(Data = "uSwift.ll", Length = 9), PSPs=0x00007ffeefbfa580, LLVMContext=0x0000000116807920, StartElem=0, outModuleHash=0x00007ffeefbf9378) at IRGen.cpp:1121
    frame #13: 0x000000010011f2cc swift`generateIR(IRGenOpts=0x00007ffeefbfc180, SM=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbf9370, PSPs=0x00007ffeefbfa580, OutputFilename=(Data = "uSwift.ll", Length = 9), MSF=swift::ModuleOrSourceFile @ 0x00007ffeefbf8ca0, IRModule=0x00007ffeefbf9380, HashGlobal=0x00007ffeefbf9378, parallelOutputFilenames=(Data = "uSwift.ll", Length = 1)) at FrontendTool.cpp:1131
    frame #14: 0x00000001000f89ad swift`performCompileStepsPostSILGen(Instance=0x000000011581b000, Invocation=0x00007ffeefbfbaf8, SM=unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > @ 0x00007ffeefbfa560, astGuaranteedToCorrespondToSIL=true, MSF=swift::ModuleOrSourceFile @ 0x00007ffeefbf94f8, PSPs=0x00007ffeefbfa580, moduleIsPublic=true, ReturnValue=0x00007ffeefbfaf74, observer=0x0000000000000000, Stats=0x0000000000000000) at FrontendTool.cpp:1384
    frame #15: 0x00000001000ea273 swift`performCompile(Instance=0x000000011581b000, Invocation=0x00007ffeefbfbaf8, Args=ArrayRef<const char *> @ 0x00007ffeefbfa780, ReturnValue=0x00007ffeefbfaf74, observer=0x0000000000000000, Stats=0x0000000000000000) at FrontendTool.cpp:1002
    frame #16: 0x00000001000e7352 swift`swift::performFrontend(Args=ArrayRef<const char *> @ 0x00007ffeefbfb188, Argv0="/Users/carlpeto/avr/swift/build/Ninja-DebugAssert+stdlib-ReleaseAssert/swift-macosx-x86_64/bin/swift", MainAddr=0x000000010000af80, observer=0x0000000000000000) at FrontendTool.cpp:1842
    frame #17: 0x000000010000d6a5 swift`run_driver(ExecName=(Data = "swift", Length = 5), argv=const llvm::ArrayRef<const char *> @ 0x00007ffeefbfc8e8) at driver.cpp:122
    frame #18: 0x000000010000bf5d swift`main(argc_=20, argv_=0x00007ffeefbff788) at driver.cpp:246
    frame #19: 0x00007fff6040b015 libdyld.dylib`start + 1
    frame #20: 0x00007fff6040b015 libdyld.dylib`start + 1

This is the original swift code...

import AVR
import Swift

typealias IntegerLiteralType = UInt8

pinMode(pin: 4, mode: INPUT)

setupTimerIntervalInterruptCallback(tenthsOfAMillisecond: 1000) {
}

struct MyStruct {
  var internal1: Int8
  var internal2: Int8
  var internal3: Int16
  var internal4: Int16
  var internal5: Int8
}

while(true) {
}

In the swift compiler layer, the trap occurs in IRGen, when lowering a constant using addRelativeAddress.

This is the method in ConstantBuilder.h:

  /// Add a tagged relative reference to the given address.  The direct
  /// target must be defined within the current image, but it might be
  /// a "GOT-equivalent", i.e. a pointer to an external object; if so,
  /// set the low bit of the offset to indicate that this is true.
  void addRelativeAddress(ConstantReference reference) {
    addTaggedRelativeOffset(IGM().RelativeAddressTy,
                            reference.getValue(),
                            unsigned(reference.isIndirect()));
  }

This is calling into clang code and there's a bit of a mismatch that is causing the trap.

The clang code is building the relevant LLVM IR:

ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
                                                llvm::Constant *target) {
  // Compute the address of the relative-address slot.
  auto base = getAddrOfCurrentPosition(offsetType);

  // Subtract.
  base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);
  target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);
  llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);

  // Truncate to the relative-address type if necessary.
  if (Builder.CGM.IntPtrTy != offsetType) {
    offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
  }

  return offset;
}

In this case, the architecture is 16 bit so Builder.CGM.IntPtrTy is a 16 bit integer.

The offsetType comes from the swift IRGen layer, IRGenModule.RelativeAddressTy.

In swift, I read this as hard coded to be a 32 bit integer using a union in the IRGenModule class.

I think this is the code in question...

  llvm::Type *VoidTy;                  /// void (usually {})
  llvm::IntegerType *Int1Ty;           /// i1
  llvm::IntegerType *Int8Ty;           /// i8
  llvm::IntegerType *Int16Ty;          /// i16
  union {
    llvm::IntegerType *Int32Ty;          /// i32
    llvm::IntegerType *RelativeAddressTy;
  };
  union {
    llvm::PointerType *Int32PtrTy;            /// i32 *
    llvm::PointerType *RelativeAddressPtrTy;
  };
  llvm::IntegerType *Int64Ty;          /// i64
  union {
    llvm::IntegerType *SizeTy;         /// usually i32 or i64
    llvm::IntegerType *IntPtrTy;
    llvm::IntegerType *MetadataKindTy;
    llvm::IntegerType *OnceTy;
    llvm::IntegerType *FarRelativeAddressTy;
    llvm::IntegerType *ProtocolDescriptorRefTy;
  };
  llvm::IntegerType *ObjCBoolTy;       /// i8 or i1
  union {
    llvm::PointerType *Int8PtrTy;      /// i8*
    llvm::PointerType *WitnessTableTy;
    llvm::PointerType *ObjCSELTy;
    llvm::PointerType *FunctionPtrTy;
    llvm::PointerType *CaptureDescriptorPtrTy;
  };
  union {
    llvm::PointerType *Int8PtrPtrTy;   /// i8**
    llvm::PointerType *WitnessTablePtrTy;
  };

So in this case I think clang reads this as "the offset does not match the standard integer/pointer type for the target/platform, so it must be longer, add an i32 trunc instruction into the IR". In this case, the integer type is 16-bit so clang traps when you try to insert a trunc from 16 bit to 32 bit.

I think there are two ways to solve this issue and I wanted to ask what everyone thinks is the best approach?

I don't really understand these relative offsets very well so I'll need advice.

First approach:
Change RelativeAddressTy and RelativeAddressPtrTy to be platform dependent instead of hard coded to 32 bit. This seems cleaner but might have performance/complexity implications or introduce bugs.

Second approach:
Patch clang::ConstantAggregateBuilderBase::getRelativeOffset so that it will either trunc or zero extend as appropriate. This seems safer but might have implications that I haven't thought of and is a patch outside the standard swift tree (in clang) so that's not ideal I guess.

Both patches seem relatively significant changes, just to add a feature to swift/clang that will be very rarely used (16-bit support) so I'm unsure what's the best approach. I'm also open to any suggestions for better or less intrusive modifications?

Cheers,
Carl

Was it really necessary to open the thread under such a scary title?

Best Regards,
Adrian

Happy to change it. New to the forums. What is scary? How would you rather I called it?

Carl

The new shorter title is good enough, I think ;)

Cool. Thanks. Was trying to make sure people who google for the error find it. I'll keep titles shorter in future.

2 Likes

I think it’s reasonable to change RelativePointerTy to be 16-bit on your target. Note that you’ll eventually need to do a lot of work to support that in the runtime headers.

Chances are whatever metadata structure is getting emitted here isn't really necessary for an embedded zero-runtime target too. This is another place where, for the OP's purposes, having a no-metadata compiler flag might help make progress.

Yeah, a lot of these structures are probably really undesirable on a 16-bit target. But in case they are, it would be good to make a quick run through the metadata structures to see if any of them would be obviously poorly-packed if we used a 16-bit relative address.

How about this as a patch?

diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 53629b8ade..7b2b0a591f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -166,6 +166,8 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
   Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
   Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
   SizeTy = DataLayout.getIntPtrType(getLLVMContext(), /*addrspace*/ 0);
+  RelativeAddressTy = SizeTy;
+  RelativeAddressPtrTy = RelativeAddressTy->getPointerTo();
 
   auto CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader());
   assert(CI && "no clang module loader");
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index fa24169e16..f3381a0403 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -488,14 +488,10 @@ public:
   llvm::IntegerType *Int1Ty;           /// i1
   llvm::IntegerType *Int8Ty;           /// i8
   llvm::IntegerType *Int16Ty;          /// i16
-  union {
-    llvm::IntegerType *Int32Ty;          /// i32
-    llvm::IntegerType *RelativeAddressTy;
-  };
-  union {
-    llvm::PointerType *Int32PtrTy;            /// i32 *
-    llvm::PointerType *RelativeAddressPtrTy;
-  };
+  llvm::IntegerType *Int32Ty;          /// i32
+  llvm::IntegerType *RelativeAddressTy;
+  llvm::PointerType *Int32PtrTy;            /// i32 *
+  llvm::PointerType *RelativeAddressPtrTy;
   llvm::IntegerType *Int64Ty;          /// i64
   union {
     llvm::IntegerType *SizeTy;         /// usually i32 or i64

I don't know if this would be appropriate to upstream though? I'm a bit inexperienced and don't know all the angles. It solves the problem and I'm able to produce roughly correct LLVM IR, which I can compile to 16 bit AVR assembly language. :grin:

Here's the original source...

import AVR
import Swift

typealias IntegerLiteralType = UInt8

struct MyStruct {
  var internal1: Int8
  var internal2: Int8
  var internal3: Int16
  var internal4: Int16
  var internal5: Int8
}

while(true) {
}

Producing the following LLVM IR...

; ModuleID = 'main_clean.ll'
source_filename = "main.ll"
target datalayout = "e-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"
target triple = "avr-atmel-linux-gnueabihf"

%swift.type_metadata_record = type { i16 }
%swift.type = type { i16 }
%T4main8MyStructV = type <{ %Ts4Int8V, %Ts4Int8V, %Ts5Int16V, %Ts5Int16V, %Ts4Int8V }>
%Ts5Int16V = type <{ i16 }>
%Ts4Int8V = type <{ i8 }>
%swift.opaque = type opaque
%swift.refcounted = type { %swift.type*, i16 }
%swift.metadata_response = type { %swift.type*, i16 }

@"$S4main8MyStructVWV" = internal constant [11 x i8*] [i8* bitcast (%swift.opaque* ([6 x i8]*, [6 x i8]*, %swift.type*)* @"$S4main8MyStructVwCP" to i8*), i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy7_2 to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy7_2 to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy7_2 to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy7_2 to i8*), i8* bitcast (i32 (%swift.opaque*, i32, %swift.type*)* @"$S4main8MyStructVwet" to i8*), i8* bitcast (void (%swift.opaque*, i32, i32, %swift.type*)* @"$S4main8MyStructVwst" to i8*), i8* inttoptr (i16 7 to i8*), i8* inttoptr (i16 1 to i8*), i8* inttoptr (i16 8 to i8*)], align 2
@0 = private constant [5 x i8] c"main\00"
@"$S4mainMXM" = linkonce_odr hidden constant <{ i32, i32, i16 }> <{ i32 0, i32 0, i16 sub (i16 ptrtoint ([5 x i8]* @0 to i16), i16 ptrtoint (i16* getelementptr inbounds (<{ i32, i32, i16 }>, <{ i32, i32, i16 }>* @"$S4mainMXM", i32 0, i32 2) to i16)) }>, section ".rodata", align 4
@1 = private constant [9 x i8] c"MyStruct\00"
@"$S4main8MyStructVMn" = hidden constant <{ i32, i16, i16, i16, i16, i32, i32 }> <{ i32 81, i16 sub (i16 ptrtoint (<{ i32, i32, i16 }>* @"$S4mainMXM" to i16), i16 ptrtoint (i16* getelementptr inbounds (<{ i32, i16, i16, i16, i16, i32, i32 }>, <{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn", i32 0, i32 1) to i16)), i16 sub (i16 ptrtoint ([9 x i8]* @1 to i16), i16 ptrtoint (i16* getelementptr inbounds (<{ i32, i16, i16, i16, i16, i32, i32 }>, <{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn", i32 0, i32 2) to i16)), i16 sub (i16 ptrtoint (%swift.metadata_response (i16)* @"$S4main8MyStructVMa" to i16), i16 ptrtoint (i16* getelementptr inbounds (<{ i32, i16, i16, i16, i16, i32, i32 }>, <{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn", i32 0, i32 3) to i16)), i16 sub (i16 ptrtoint ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF" to i16), i16 ptrtoint (i16* getelementptr inbounds (<{ i32, i16, i16, i16, i16, i32, i32 }>, <{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn", i32 0, i32 4) to i16)), i32 5, i32 2 }>, section ".rodata", align 4
@"$S4main8MyStructVMf" = internal constant <{ i8**, i16, <{ i32, i16, i16, i16, i16, i32, i32 }>*, i32, i32, i32, i32, i32 }> <{ i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @"$S4main8MyStructVWV", i32 0, i32 0), i16 512, <{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn", i32 0, i32 1, i32 2, i32 4, i32 6 }>, align 2
@"symbolic \01____ 4main8MyStructV" = linkonce_odr hidden constant <{ [1 x i8], i16, i8 }> <{ [1 x i8] c"\01", i16 sub (i16 ptrtoint (<{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn" to i16), i16 ptrtoint (i16* getelementptr inbounds (<{ [1 x i8], i16, i8 }>, <{ [1 x i8], i16, i8 }>* @"symbolic \01____ 4main8MyStructV", i32 0, i32 1) to i16)), i8 0 }>, section "swift5_typeref", align 1
@"symbolic s4Int8V" = linkonce_odr hidden constant <{ [7 x i8], i8 }> <{ [7 x i8] c"s4Int8V", i8 0 }>, section "swift5_typeref", align 1
@2 = private constant [10 x i8] c"internal1\00", section "swift5_reflstr"
@3 = private constant [10 x i8] c"internal2\00", section "swift5_reflstr"
@"symbolic s5Int16V" = linkonce_odr hidden constant <{ [8 x i8], i8 }> <{ [8 x i8] c"s5Int16V", i8 0 }>, section "swift5_typeref", align 1
@4 = private constant [10 x i8] c"internal3\00", section "swift5_reflstr"
@5 = private constant [10 x i8] c"internal4\00", section "swift5_reflstr"
@6 = private constant [10 x i8] c"internal5\00", section "swift5_reflstr"
@"$S4main8MyStructVMF" = internal constant { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 } { i16 sub (i16 ptrtoint (<{ [1 x i8], i16, i8 }>* @"symbolic \01____ 4main8MyStructV" to i16), i16 ptrtoint ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF" to i16)), i32 0, i16 0, i16 12, i32 5, i32 2, i16 sub (i16 ptrtoint (<{ [7 x i8], i8 }>* @"symbolic s4Int8V" to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 6) to i16)), i16 sub (i16 ptrtoint ([10 x i8]* @2 to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 7) to i16)), i32 2, i16 sub (i16 ptrtoint (<{ [7 x i8], i8 }>* @"symbolic s4Int8V" to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 9) to i16)), i16 sub (i16 ptrtoint ([10 x i8]* @3 to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 10) to i16)), i32 2, i16 sub (i16 ptrtoint (<{ [8 x i8], i8 }>* @"symbolic s5Int16V" to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 12) to i16)), i16 sub (i16 ptrtoint ([10 x i8]* @4 to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 13) to i16)), i32 2, i16 sub (i16 ptrtoint (<{ [8 x i8], i8 }>* @"symbolic s5Int16V" to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 15) to i16)), i16 sub (i16 ptrtoint ([10 x i8]* @5 to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 16) to i16)), i32 2, i16 sub (i16 ptrtoint (<{ [7 x i8], i8 }>* @"symbolic s4Int8V" to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 18) to i16)), i16 sub (i16 ptrtoint ([10 x i8]* @6 to i16), i16 ptrtoint (i16* getelementptr inbounds ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }, { i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF", i32 0, i32 19) to i16)) }, section "swift5_fieldmd", align 4
@"\01l_type_metadata_table" = private constant [1 x %swift.type_metadata_record] [%swift.type_metadata_record { i16 sub (i16 ptrtoint (<{ i32, i16, i16, i16, i16, i32, i32 }>* @"$S4main8MyStructVMn" to i16), i16 ptrtoint ([1 x %swift.type_metadata_record]* @"\01l_type_metadata_table" to i16)) }], section "swift5_type_metadata", align 4
@__swift_reflection_version = linkonce_odr hidden constant i16 3
@_swift1_autolink_entries = private constant [6 x i8] c"-lavr\00", section ".swift1_autolink_entries", align 2
@llvm.used = appending global [4 x i8*] [i8* bitcast ([1 x %swift.type_metadata_record]* @"\01l_type_metadata_table" to i8*), i8* bitcast ({ i16, i32, i16, i16, i32, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16, i32, i16, i16 }* @"$S4main8MyStructVMF" to i8*), i8* bitcast (i16* @__swift_reflection_version to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @_swift1_autolink_entries, i32 0, i32 0)], section "llvm.metadata"

@"$S4main8MyStructVN" = hidden alias %swift.type, bitcast (i16* getelementptr inbounds (<{ i8**, i16, <{ i32, i16, i16, i16, i16, i32, i32 }>*, i32, i32, i32, i32, i32 }>, <{ i8**, i16, <{ i32, i16, i16, i16, i16, i32, i32 }>*, i32, i32, i32, i32, i32 }>* @"$S4main8MyStructVMf", i32 0, i32 1) to %swift.type*)

; Function Attrs: norecurse noreturn nounwind readnone
define protected i16 @main(i16, i8** nocapture readnone) local_unnamed_addr #0 {
entry:
  br label %2

; <label>:2:                                      ; preds = %2, %entry
  br label %2
}

...SNIP...

And compiling to this assembly...

	.text
	.file	"main.ll"
	.protected	main            ; -- Begin function main
	.globl	main
	.p2align	1
	.type	main,@function
main:                                   ; @main
; %bb.0:                                ; %entry
LBB0_1:                                 ; =>This Inner Loop Header: Depth=1
	rjmp	LBB0_1
.Lfunc_end0:
	.size	main, .Lfunc_end0-main
                                        ; -- End function
	.hidden	$S4main8MyStructV9internal1s4Int8Vvg ; -- Begin function $S4main8MyStructV9internal1s4Int8Vvg
	.globl	$S4main8MyStructV9internal1s4Int8Vvg
	.p2align	1
	.type	$S4main8MyStructV9internal1s4Int8Vvg,@function
$S4main8MyStructV9internal1s4Int8Vvg:   ; @"$S4main8MyStructV9internal1s4Int8Vvg"
; %bb.0:                                ; %entry
                                        ; kill: def $r24 killed $r24 killed $r25r24
	ret
.Lfunc_end1:
	.size	$S4main8MyStructV9internal1s4Int8Vvg, .Lfunc_end1-($S4main8MyStructV9internal1s4Int8Vvg)
                                        ; -- End function
	.hidden	$S4main8MyStructV9internal1s4Int8Vvs ; -- Begin function $S4main8MyStructV9internal1s4Int8Vvs
	.globl	$S4main8MyStructV9internal1s4Int8Vvs
	.p2align	1
	.type	$S4main8MyStructV9internal1s4Int8Vvs,@function
$S4main8MyStructV9internal1s4Int8Vvs:   ; @"$S4main8MyStructV9internal1s4Int8Vvs"
; %bb.0:                                ; %entry
	mov	r26, r22
	mov	r27, r23
	st	X, r24
	ret
.Lfunc_end2:
	.size	$S4main8MyStructV9internal1s4Int8Vvs, .Lfunc_end2-($S4main8MyStructV9internal1s4Int8Vvs)
                                        ; -- End function
	.hidden	$S4main8MyStructV9internal1s4Int8VvM ; -- Begin function $S4main8MyStructV9internal1s4Int8VvM
	.globl	$S4main8MyStructV9internal1s4Int8VvM
	.p2align	1
	.type	$S4main8MyStructV9internal1s4Int8VvM,@function
$S4main8MyStructV9internal1s4Int8VvM:   ; @"$S4main8MyStructV9internal1s4Int8VvM"
; %bb.0:                                ; %entry
	mov	r24, r22
	mov	r25, r23
	ldi	r22, pm_lo8(($S4main8MyStructV9internal1s4Int8VvM.resume.0))
	ldi	r23, pm_hi8(($S4main8MyStructV9internal1s4Int8VvM.resume.0))
	ret
.Lfunc_end3:
	.size	$S4main8MyStructV9internal1s4Int8VvM, .Lfunc_end3-($S4main8MyStructV9internal1s4Int8VvM)
                                        ; -- End function
	.p2align	1               ; -- Begin function $S4main8MyStructV9internal1s4Int8VvM.resume.0
	.type	$S4main8MyStructV9internal1s4Int8VvM.resume.0,@function
$S4main8MyStructV9internal1s4Int8VvM.resume.0: ; @"$S4main8MyStructV9internal1s4Int8VvM.resume.0"
; %bb.0:                                ; %entryresume.0
	ret
.Lfunc_end4:
	.size	$S4main8MyStructV9internal1s4Int8VvM.resume.0, .Lfunc_end4-($S4main8MyStructV9internal1s4Int8VvM.resume.0)
                                        ; -- End function
	.hidden	$S4main8MyStructV9internal2s4Int8Vvg ; -- Begin function $S4main8MyStructV9internal2s4Int8Vvg
	.globl	$S4main8MyStructV9internal2s4Int8Vvg
	.p2align	1
	.type	$S4main8MyStructV9internal2s4Int8Vvg,@function
$S4main8MyStructV9internal2s4Int8Vvg:   ; @"$S4main8MyStructV9internal2s4Int8Vvg"
; %bb.0:                                ; %entry
	mov	r24, r25
	ret
.Lfunc_end5:
	.size	$S4main8MyStructV9internal2s4Int8Vvg, .Lfunc_end5-($S4main8MyStructV9internal2s4Int8Vvg)
                                        ; -- End function
	.hidden	$S4main8MyStructV9internal2s4Int8Vvs ; -- Begin function $S4main8MyStructV9internal2s4Int8Vvs
	.globl	$S4main8MyStructV9internal2s4Int8Vvs
	.p2align	1
	.type	$S4main8MyStructV9internal2s4Int8Vvs,@function
$S4main8MyStructV9internal2s4Int8Vvs:   ; @"$S4main8MyStructV9internal2s4Int8Vvs"
; %bb.0:                                ; %entry
	mov	r30, r22
	mov	r31, r23
	std	Z+1, r24
	ret
.Lfunc_end6:
	.size	$S4main8MyStructV9internal2s4Int8Vvs, .Lfunc_end6-($S4main8MyStructV9internal2s4Int8Vvs)
                                        ; -- End function
	.hidden	$S4main8MyStructV9internal2s4Int8VvM ; -- Begin function $S4main8MyStructV9internal2s4Int8VvM
	.globl	$S4main8MyStructV9internal2s4Int8VvM
	.p2align	1
	.type	$S4main8MyStructV9internal2s4Int8VvM,@function
$S4main8MyStructV9internal2s4Int8VvM:   ; @"$S4main8MyStructV9internal2s4Int8VvM"
; %bb.0:                                ; %entry
	mov	r24, r22
	mov	r25, r23
	adiw	r24, 1
	ldi	r22, pm_lo8(($S4main8MyStructV9internal2s4Int8VvM.resume.0))
	ldi	r23, pm_hi8(($S4main8MyStructV9internal2s4Int8VvM.resume.0))
	ret
.Lfunc_end7:
	.size	$S4main8MyStructV9internal2s4Int8VvM, .Lfunc_end7-($S4main8MyStructV9internal2s4Int8VvM)
                                        ; -- End function
	.p2align	1               ; -- Begin function $S4main8MyStructV9internal2s4Int8VvM.resume.0
	.type	$S4main8MyStructV9internal2s4Int8VvM.resume.0,@function

...SNIP...

LBB26_9:
	andi	r20, 1
	cpi	r20, 0
	brne	LBB26_11
; %bb.10:
	adiw	r30, 7
	ldi	r24, 0
	st	Z, r24
LBB26_11:
	ret
.Lfunc_end26:
	.size	$S4main8MyStructVwst, .Lfunc_end26-($S4main8MyStructVwst)
                                        ; -- End function
	.hidden	$S4main8MyStructVMa     ; -- Begin function $S4main8MyStructVMa
	.globl	$S4main8MyStructVMa
	.p2align	1
	.type	$S4main8MyStructVMa,@function
$S4main8MyStructVMa:                    ; @"$S4main8MyStructVMa"
; %bb.0:                                ; %entry
	ldi	r22, lo8(($S4main8MyStructVMf)+2)
	ldi	r23, hi8(($S4main8MyStructVMf)+2)
	ldi	r24, 0
	ldi	r25, 0
	ret
.Lfunc_end27:
	.size	$S4main8MyStructVMa, .Lfunc_end27-($S4main8MyStructVMa)
                                        ; -- End function
	.type	$S4main8MyStructVWV,@object ; @"$S4main8MyStructVWV"
	.section	.rodata,"a",@progbits
	.p2align	1
$S4main8MyStructVWV:
	.short	($S4main8MyStructVwCP)
	.short	__swift_noop_void_return
	.short	__swift_memcpy7_2
	.short	__swift_memcpy7_2
	.short	__swift_memcpy7_2
	.short	__swift_memcpy7_2
	.short	($S4main8MyStructVwet)
	.short	($S4main8MyStructVwst)
	.short	7
	.short	1
	.short	8
	.size	$S4main8MyStructVWV, 22

	.type	__unnamed_1,@object     ; @0
__unnamed_1:
	.asciz	"main"
	.size	__unnamed_1, 5

	.hidden	$S4mainMXM              ; @"$S4mainMXM"
	.type	$S4mainMXM,@object
	.weak	$S4mainMXM
	.p2align	2
$S4mainMXM:
	.long	0                       ; 0x0
	.long	0                       ; 0x0
	.short	(__unnamed_1-($S4mainMXM))-8
	.size	$S4mainMXM, 10

	.type	__unnamed_2,@object     ; @1
__unnamed_2:
	.asciz	"MyStruct"
	.size	__unnamed_2, 9

	.hidden	$S4main8MyStructVMn     ; @"$S4main8MyStructVMn"
	.type	$S4main8MyStructVMn,@object
	.globl	$S4main8MyStructVMn
	.p2align	2
$S4main8MyStructVMn:
	.long	81                      ; 0x51
	.short	(($S4mainMXM)-($S4main8MyStructVMn))-4
	.short	(__unnamed_2-($S4main8MyStructVMn))-6
	.short	(($S4main8MyStructVMa)-($S4main8MyStructVMn))-8
	.short	(($S4main8MyStructVMF)-($S4main8MyStructVMn))-10
	.long	5                       ; 0x5
	.long	2                       ; 0x2
	.size	$S4main8MyStructVMn, 20

	.type	$S4main8MyStructVMf,@object ; @"$S4main8MyStructVMf"
	.p2align	1
$S4main8MyStructVMf:
	.short	($S4main8MyStructVWV)
	.short	512                     ; 0x200
	.short	($S4main8MyStructVMn)
	.long	0                       ; 0x0
	.long	1                       ; 0x1
	.long	2                       ; 0x2
	.long	4                       ; 0x4
	.long	6                       ; 0x6
	.size	$S4main8MyStructVMf, 26

	.hidden	"symbolic ____ 4main8MyStructV" ; @"symbolic \01____ 4main8MyStructV"
	.type	"symbolic ____ 4main8MyStructV",@object
	.section	swift5_typeref,"a",@progbits
	.weak	"symbolic ____ 4main8MyStructV"
"symbolic ____ 4main8MyStructV":
	.byte	1
	.short	(($S4main8MyStructVMn)-"symbolic ____ 4main8MyStructV")-1
	.byte	0                       ; 0x0
	.size	"symbolic ____ 4main8MyStructV", 4

	.hidden	"symbolic s4Int8V"      ; @"symbolic s4Int8V"
	.type	"symbolic s4Int8V",@object
	.weak	"symbolic s4Int8V"
"symbolic s4Int8V":
	.ascii	"s4Int8V"
	.byte	0                       ; 0x0
	.size	"symbolic s4Int8V", 8

	.type	__unnamed_3,@object     ; @2
	.section	swift5_reflstr,"a",@progbits
__unnamed_3:
	.asciz	"internal1"
	.size	__unnamed_3, 10

	.type	__unnamed_4,@object     ; @3
__unnamed_4:
	.asciz	"internal2"
	.size	__unnamed_4, 10

	.hidden	"symbolic s5Int16V"     ; @"symbolic s5Int16V"
	.type	"symbolic s5Int16V",@object
	.section	swift5_typeref,"a",@progbits
	.weak	"symbolic s5Int16V"
"symbolic s5Int16V":
	.ascii	"s5Int16V"
	.byte	0                       ; 0x0
	.size	"symbolic s5Int16V", 9

	.type	__unnamed_5,@object     ; @4
	.section	swift5_reflstr,"a",@progbits
__unnamed_5:
	.asciz	"internal3"
	.size	__unnamed_5, 10

	.type	__unnamed_6,@object     ; @5
__unnamed_6:
	.asciz	"internal4"
	.size	__unnamed_6, 10

	.type	__unnamed_7,@object     ; @6
__unnamed_7:
	.asciz	"internal5"
	.size	__unnamed_7, 10

	.type	$S4main8MyStructVMF,@object ; @"$S4main8MyStructVMF"
	.section	swift5_fieldmd,"a",@progbits
	.p2align	2
$S4main8MyStructVMF:
	.short	"symbolic ____ 4main8MyStructV"-($S4main8MyStructVMF)
	.long	0                       ; 0x0
	.short	0                       ; 0x0
	.short	12                      ; 0xc
	.long	5                       ; 0x5
	.long	2                       ; 0x2
	.short	("symbolic s4Int8V"-($S4main8MyStructVMF))-18
	.short	(__unnamed_3-($S4main8MyStructVMF))-20
	.long	2                       ; 0x2
	.short	("symbolic s4Int8V"-($S4main8MyStructVMF))-26
	.short	(__unnamed_4-($S4main8MyStructVMF))-28
	.long	2                       ; 0x2
	.short	("symbolic s5Int16V"-($S4main8MyStructVMF))-34
	.short	(__unnamed_5-($S4main8MyStructVMF))-36
	.long	2                       ; 0x2
	.short	("symbolic s5Int16V"-($S4main8MyStructVMF))-42
	.short	(__unnamed_6-($S4main8MyStructVMF))-44
	.long	2                       ; 0x2
	.short	("symbolic s4Int8V"-($S4main8MyStructVMF))-50
	.short	(__unnamed_7-($S4main8MyStructVMF))-52
	.size	$S4main8MyStructVMF, 54

	.type	l_type_metadata_table,@object ; @"\01l_type_metadata_table"
	.section	swift5_type_metadata,"a",@progbits
	.p2align	2
l_type_metadata_table:
	.short	($S4main8MyStructVMn)-l_type_metadata_table
	.size	l_type_metadata_table, 2

	.hidden	__swift_reflection_version ; @__swift_reflection_version
	.type	__swift_reflection_version,@object
	.section	.rodata,"a",@progbits
	.weak	__swift_reflection_version
__swift_reflection_version:
	.short	3                       ; 0x3
	.size	__swift_reflection_version, 2

	.type	_swift1_autolink_entries,@object ; @_swift1_autolink_entries
	.section	.swift1_autolink_entries,"a",@progbits
	.p2align	1
_swift1_autolink_entries:
	.asciz	"-lavr"
	.size	_swift1_autolink_entries, 6


	.globl	$S4main8MyStructVN
	.hidden	$S4main8MyStructVN
.set $S4main8MyStructVN, ($S4main8MyStructVMf)+2
	; Declaring this symbol tells the CRT that it should
	;copy all variables from program memory to RAM on startup
	.globl	__do_copy_data
	; Declaring this symbol tells the CRT that it should
	;clear the zeroed data section on startup
	.globl	__do_clear_bss

Mostly it's working I think. It won't link at the moment due to missing runtime (swift_retain).

However, @Joe_Groff has a point, it would be really good to start figuring out how I might turn off metadata emission on this platform. Do you have any pointers where I might look first?

Please open a PR if you'd like us to do code review. We won't merge it without your approval.

@John_McCall PR created! My first. Exciting. :slight_smile: Improve the compiler around 16-bit pointers by carlos4242 · Pull Request #20694 · apple/swift · GitHub

2 Likes