# 23593143 lli JIT bitcode parsing creates a main function with wrong argc/argv
# 22804878 - implement LLVM JIT on Solaris SPARC
# 22804891 - implement LLVM JIT on Solaris Intel
# 3.9.X for upstream.
--- include/llvm/Support/ELFRelocs/Sparc.def 2015-06-18 07:05:15.000000000 -0800
+++ include/llvm/Support/ELFRelocs/Sparc.def 2016-06-11 11:39:24.768074060 -0800
@@ -87,3 +87,8 @@
ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82)
ELF_RELOC(R_SPARC_GOTDATA_OP_LOX10, 83)
ELF_RELOC(R_SPARC_GOTDATA_OP, 84)
+ELF_RELOC(R_SPARC_H34, 85)
+ELF_RELOC(R_SPARC_SIZE32, 86)
+ELF_RELOC(R_SPARC_SIZE64, 87)
+ELF_RELOC(R_SPARC_WDISP10, 88)
+ELF_RELOC(R_SPARC_NUM, 89)
--- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h 2016-01-10 09:51:50.000000000 -0900
+++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h 2016-06-11 21:03:29.000000000 -0800
@@ -117,6 +117,11 @@
assert(StubOffset <= AllocationSize && "Not enough space allocated!");
}
+ void setStubOffset(unsigned Value) {
+ StubOffset = Value;
+ assert(StubOffset <= AllocationSize && "Not enough space allocated!");
+ }
+
uintptr_t getObjAddress() const { return ObjAddress; }
};
###
--- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h 2015-11-23 12:47:51.000000000 -0900
+++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h 2016-06-23 07:17:02.829718055 -0800
@@ -49,6 +49,14 @@
void resolvePPC64Relocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
+ void resolveSPARC3264Relocation(const SectionEntry &Section,
+ uint64_t Offset, uint64_t Value,
+ uint32_t Type, int32_t Addend);
+
+ void resolveSPARC64Relocation(const SectionEntry &Section,
+ uint64_t Offset, uint64_t Value,
+ uint32_t Type, int64_t Addend);
+
void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
@@ -73,6 +81,10 @@
return 16;
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
return 44;
+ else if (Arch == Triple::sparc)
+ return 16;
+ else if (Arch == Triple::sparcv9)
+ return 32;
else if (Arch == Triple::x86_64)
return 6; // 2-byte jmp instruction + 32-bit relative address
else if (Arch == Triple::systemz)
###
--- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp 2015-11-24 11:37:01.000000000 -0900
+++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp 2016-07-04 10:45:23.637041765 -0800
@@ -1016,6 +1016,448 @@
}
}
+/// SPARC ELF Relocations - common to 32-bit and 64-bit.
+/// https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-24/index.html
+void RuntimeDyldELF::resolveSPARC3264Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int32_t Addend) {
+ uint64_t *TargetAddress =
+ reinterpret_cast<uint64_t*>(reinterpret_cast<void*>(Section.getAddress()));
+ uint64_t *TargetPtr =
+ reinterpret_cast<uint64_t*>(Section.getAddressWithOffset(Offset));
+ uint32_t Reloc = 0U;
+ uint8_t *TargetPtr8 = nullptr;
+ uint16_t *TargetPtr16 = nullptr;
+ uint32_t *TargetPtr32 = nullptr;
+ uint32_t LoadAddress = Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF;
+ uint32_t TargetValue = 0U;
+ int32_t RS = 0;
+ int32_t RM = 0;
+
+ switch (Type) {
+ default:
+ llvm_unreachable("Unimplemented SPARC32 Relocation Type!");
+ break;
+ case ELF::R_SPARC_NONE:
+ break;
+ case ELF::R_SPARC_SIZE32:
+ *TargetPtr = Section.getSize() + Addend;
+ break;
+ case ELF::R_SPARC_RELATIVE:
+ *TargetPtr = LoadAddress + Addend;
+ break;
+ case ELF::R_SPARC_COPY:
+ Value += Addend;
+ (void) std::memcpy(TargetPtr,
+ reinterpret_cast<void*>(static_cast<uintptr_t>(Value)),
+ Section.getSize());
+ break;
+ case ELF::R_SPARC_8:
+ TargetPtr8 = reinterpret_cast<uint8_t*>(TargetPtr);
+ Value += Addend;
+ *TargetPtr8 = Value;
+ break;
+ case ELF::R_SPARC_16:
+ TargetPtr16 = reinterpret_cast<uint16_t*>(TargetPtr);
+ Value += Addend;
+ *TargetPtr16 = Value;
+ break;
+ case ELF::R_SPARC_32:
+ case ELF::R_SPARC_GLOB_DAT:
+ Value += Addend;
+ *TargetPtr = Value;
+ break;
+ case ELF::R_SPARC_JMP_SLOT:
+ break;
+ case ELF::R_SPARC_TLS_DTPOFF32:
+ Value += Addend;
+ *TargetPtr = Value;
+ break;
+ case ELF::R_SPARC_TLS_TPOFF32:
+ Value += Addend;
+ *TargetPtr = Value - Offset;
+ break;
+ case ELF::R_SPARC_TLS_LE_HIX22:
+ Value -= Offset;
+ Value += Addend;
+ *TargetPtr = (*TargetPtr & 0xFFC00000) | ((~Value) & 0x003FFFFFLL);
+ break;
+ case ELF::R_SPARC_TLS_LE_LOX10:
+ Value -= Offset;
+ Value += Addend;
+ *TargetPtr = (*TargetPtr & 0xFFFFE000) | (Value & 0x000003FFLL);
+ break;
+ case ELF::R_SPARC_DISP8:
+ Value += Addend;
+ TargetPtr8 = reinterpret_cast<uint8_t*>(TargetAddress);
+ *TargetPtr8 = (Value - reinterpret_cast<uintptr_t>(TargetPtr8));
+ break;
+ case ELF::R_SPARC_DISP16:
+ Value += Addend;
+ TargetPtr16 = reinterpret_cast<uint16_t*>(TargetAddress);
+ *TargetPtr16 = (Value - reinterpret_cast<uintptr_t>(TargetPtr16));
+ break;
+ case ELF::R_SPARC_DISP32:
+ Value += Addend;
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetAddress);
+ *TargetPtr32 = (Value - reinterpret_cast<uintptr_t>(TargetPtr32));
+ break;
+ case ELF::R_SPARC_WDISP30:
+ case ELF::R_SPARC_WDISP22:
+ case ELF::R_SPARC_WDISP19:
+ case ELF::R_SPARC_WDISP16:
+ case ELF::R_SPARC_WDISP10:
+ switch (Type) {
+ default:
+ llvm_unreachable("Impossible default case!");
+ break;
+ case ELF::R_SPARC_WDISP30:
+ RS = 2;
+ RM = 0x3FFFFFFF;
+ break;
+ case ELF::R_SPARC_WDISP22:
+ RS = 2;
+ RM = 0x003FFFFF;
+ break;
+ case ELF::R_SPARC_WDISP19:
+ RS = 2;
+ RM = 0x0007FFFF;
+ break;
+ case ELF::R_SPARC_WDISP16:
+ RS = 2;
+ break;
+ case ELF::R_SPARC_WDISP10:
+ RS = 2;
+ break;
+ }
+
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ Reloc = (((Value + Addend) - LoadAddress) >> RS);
+ TargetValue = *TargetPtr32;
+
+ switch (Type) {
+ default:
+ llvm_unreachable("Impossible default case!");
+ break;
+ case ELF::R_SPARC_WDISP16:
+ TargetValue &= ~((0x3 << 20) | 0x3FFF);
+ Reloc = (((Reloc & 0xC000) << (7 - 1)) | (Reloc & 0x3FFFF));
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_WDISP10:
+ TargetValue &= ~((0x3 << 19) | (0xFF << 5));
+ Reloc = (((Reloc & 0x300) << (13 - 2)) | ((Reloc & 0xFF) | (7 - 2)));
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_WDISP30:
+ case ELF::R_SPARC_WDISP22:
+ case ELF::R_SPARC_WDISP19:
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ }
+ break;
+ case ELF::R_SPARC_HI22:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 10;
+ RM = 0x003FFFFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_10:
+ Value += Addend;
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ *TargetPtr32 = Value;
+ break;
+ case ELF::R_SPARC_11:
+ Value += Addend;
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ *TargetPtr32 = Value;
+ break;
+ case ELF::R_SPARC_13:
+ Value += Addend;
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ *TargetPtr32 = Value;
+ break;
+ case ELF::R_SPARC_22:
+ Value += Addend;
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ *TargetPtr32 = Value;
+ break;
+ case ELF::R_SPARC_LO10:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 0;
+ RM = 0x000003FF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_LM22:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 10;
+ RM = 0x003FFFFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_HIX22:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 10;
+ RM = 0x3FFFFF;
+ Reloc = Value + Addend;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc ^= ~0;
+ Reloc >>= RS;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_LOX10:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ Reloc = Value + Addend;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~0x1FFF;
+ Reloc &= 0x3FF;
+ Reloc |= 0x1C00;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_HH22:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 42;
+ RM = 0x003FFFFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_HM10:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 32;
+ RM = 0x000003FF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_H44:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 22;
+ RM = 0x003FFFFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_M44:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 12;
+ RM = 0x000003FF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_L44:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 0;
+ RM = 0x00000FFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_GOT10:
+ assert((Offset != static_cast<uint64_t>(-1)) &&
+ "R_SPARC_GOT10: Invalid offset!");
+ if ((Offset & 1) != 0)
+ Offset &= ~1;
+ else
+ Offset |= 1;
+
+ RS = 0;
+ RM = 0x000003FF;
+ Reloc = (Value + Addend) >> RS;
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_GOT13:
+ assert((Offset != static_cast<uint64_t>(-1)) &&
+ "R_SPARC_GOT13: Invalid offset!");
+ if ((Offset & 1) != 0)
+ Offset &= ~1;
+ else
+ Offset |= 1;
+
+ RS = 0;
+ RM = 0x00001FFF;
+ Reloc = (Value + Addend) >> RS;
+
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_GOT22:
+ assert((Offset != static_cast<uint64_t>(-1)) &&
+ "R_SPARC_GOT22: Invalid offset!");
+ if ((Offset & 1) != 0)
+ Offset &= ~1;
+ else
+ Offset |= 1;
+
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 10;
+ RM = 0x003FFFFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_PC10:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 0;
+ RM =0x000003FF;
+ Reloc = ((Value + Addend) - LoadAddress) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_PC22:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 10;
+ RM = 0x003FFFFF;
+ Reloc = ((Value + Addend) - LoadAddress) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_UA16:
+ TargetPtr8 = reinterpret_cast<uint8_t*>(TargetPtr);
+ TargetPtr8[0] = Value >> 8U;
+ TargetPtr8[1] = Value;
+ break;
+ case ELF::R_SPARC_UA32:
+ TargetPtr8 = reinterpret_cast<uint8_t*>(TargetPtr);
+ TargetPtr8[0] = Value >> 24U;
+ TargetPtr8[1] = Value >> 16U;
+ TargetPtr8[2] = Value >> 8U;
+ TargetPtr8[3] = Value;
+ break;
+ case ELF::R_SPARC_WPLT30:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 2;
+ RM = 0x3FFFFFFF;
+ Reloc = ((Value + Addend) - LoadAddress) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ TargetValue = *TargetPtr32;
+ break;
+ }
+}
+
+/// SPARCV9 ELF Relocatinos - valid in 64-bit only.
+/// https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-24-1/index.html
+void RuntimeDyldELF::resolveSPARC64Relocation(const SectionEntry &Section,
+ uint64_t Offset, uint64_t Value,
+ uint32_t Type, int64_t Addend) {
+ uint64_t *TargetAddress =
+ reinterpret_cast<uint64_t*>(reinterpret_cast<void*>(Section.getAddress()));
+ uint64_t *TargetPtr =
+ reinterpret_cast<uint64_t*>(Section.getAddressWithOffset(Offset));
+ uint32_t Reloc;
+ uintptr_t TargetPtrVal = reinterpret_cast<uintptr_t>(TargetPtr);
+ uint8_t *TargetPtr8 = nullptr;
+ uint16_t *TargetPtr16 = nullptr;
+ uint32_t *TargetPtr32 = nullptr;
+ uint64_t LoadAddress = Section.getLoadAddressWithOffset(Offset);
+ uint64_t TargetValue = 0ULL;
+ int32_t RS;
+ int32_t RM;
+
+ switch (Type) {
+ case ELF::R_SPARC_HI22:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ RS = 10;
+ RM = 0x003FFFFF;
+ Reloc = (Value + Addend) >> RS;
+ TargetValue = *TargetPtr32;
+ TargetValue &= ~RM;
+ Reloc &= RM;
+ *TargetPtr32 = TargetValue | Reloc;
+ break;
+ case ELF::R_SPARC_64:
+ case ELF::R_SPARC_GLOB_DAT:
+ Value += Addend;
+ *TargetPtr = Value;
+ break;
+ case ELF::R_SPARC_RELATIVE:
+ *TargetPtr = LoadAddress + Addend;
+ break;
+ case ELF::R_SPARC_OLO10:
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ *TargetPtr32 = (*TargetPtr32 & ~0x1FFF) | (((Value + Addend) & 0x3FF) +
+ ((Offset >> 8) & 0x1FFF));
+ break;
+ case ELF::R_SPARC_DISP64:
+ Value += Addend;
+ *TargetPtr = (Value - reinterpret_cast<uintptr_t>(TargetPtr));
+ break;
+ case ELF::R_SPARC_REGISTER:
+ Value += Addend;
+ *TargetPtr = Value;
+ break;
+ case ELF::R_SPARC_PLT64:
+ llvm::errs() << __PRETTY_FUNCTION__
+ << ": Warning: Unimplemented R_SPARC_PLT64 Relocation type.\n" ;
+ break;
+ case ELF::R_SPARC_UA64:
+ Value += Addend;
+ if (0 == (TargetPtrVal & 3)) {
+ TargetPtr32 = reinterpret_cast<uint32_t*>(TargetPtr);
+ TargetPtr32[0] = Value >> 32;
+ TargetPtr32[1] = Value;
+ } else {
+ TargetPtr8 = reinterpret_cast<uint8_t*>(TargetPtr);
+ TargetPtr8[0] = Value >> 56;
+ TargetPtr8[0] = Value >> 48;
+ TargetPtr8[0] = Value >> 40;
+ TargetPtr8[0] = Value >> 32;
+ TargetPtr8[0] = Value >> 24;
+ TargetPtr8[0] = Value >> 16;
+ TargetPtr8[0] = Value >> 8;
+ TargetPtr8[0] = Value;
+ }
+ break;
+ default:
+ resolveSPARC3264Relocation(Section, Offset, Value, Type, Addend);
+ break;
+ }
+}
+
void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
uint64_t Offset, uint64_t Value,
uint32_t Type, int64_t Addend) {
@@ -1123,6 +1565,12 @@
case Triple::systemz:
resolveSystemZRelocation(Section, Offset, Value, Type, Addend);
break;
+ case Triple::sparc:
+ resolveSPARC3264Relocation(Section, Offset, Value, Type, Addend);
+ break;
+ case Triple::sparcv9:
+ resolveSPARC64Relocation(Section, Offset, Value, Type, Addend);
+ break;
default:
llvm_unreachable("Unsupported CPU type!");
}
@@ -1590,6 +2038,160 @@
else
addRelocationForSection(RE, Value.SectionID);
}
+ } else if (Arch == Triple::sparc) {
+ DEBUG(dbgs() << "This is a SPARC32 relocation.\n");
+ SectionEntry &Section = Sections[SectionID];
+ uint8_t *Target = Section.getAddressWithOffset(Offset);
+ uint32_t *TargetAddress = reinterpret_cast<uint32_t*>(Target);
+ uint8_t *SectionAddress = Section.getAddress();
+ uintptr_t StubOffset = Section.getStubOffset();
+ uintptr_t StubAddress = static_cast<uintptr_t>(-1);
+
+ if (RelType == ELF::R_SPARC_WDISP30) {
+ // Look up for existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+
+ if (i != Stubs.end()) {
+ DEBUG(dbgs() << " Stub function found\n");
+ StubAddress =
+ reinterpret_cast<uintptr_t>(Section.getAddressWithOffset(i->second));
+
+ resolveRelocation(Section, Offset, StubAddress, RelType, 0);
+ Section.advanceStubOffset(getMaxStubSize());
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+
+ uintptr_t BaseAddress =
+ reinterpret_cast<uintptr_t>(Section.getAddress());
+ uintptr_t StubAlignment = getStubAlignment();
+ StubAddress = BaseAddress + StubOffset;
+ StubAddress = llvm::RoundUpToAlignment(StubAddress, 4U);
+ StubOffset = StubAddress - BaseAddress;
+
+ Stubs[Value] = StubOffset;
+ uint8_t *StubTargetAddr =
+ createStubFunction(reinterpret_cast<uint8_t*>(StubAddress));
+
+ // Creating Hi and Lo relocations for the filled stub instructions.
+ RelocationEntry REhi(SectionID,
+ StubTargetAddr - SectionAddress,
+ ELF::R_SPARC_HI22, Value.Addend);
+ RelocationEntry RElo(SectionID,
+ StubTargetAddr - SectionAddress + 4,
+ ELF::R_SPARC_LO10, Value.Addend);
+
+ if (Value.SymbolName) {
+ addRelocationForSymbol(REhi, Value.SymbolName);
+ addRelocationForSymbol(RElo, Value.SymbolName);
+ } else {
+ addRelocationForSection(REhi, Value.SectionID);
+ addRelocationForSection(RElo, Value.SectionID);
+ }
+
+ resolveRelocation(Section, Offset, StubAddress, RelType, 0);
+ Section.advanceStubOffset(getMaxStubSize());
+ }
+ } else {
+ uintptr_t BaseAddress =
+ reinterpret_cast<uintptr_t>(Section.getAddress());
+ uintptr_t StubAlignment = getStubAlignment();
+ StubAddress = BaseAddress + StubOffset;
+ StubAddress = llvm::RoundUpToAlignment(StubAddress, 4U);
+ StubOffset = StubAddress - BaseAddress;
+
+ RelocationEntry RE(SectionID, Offset, RelType, Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+
+ resolveRelocation(Section, Offset, StubOffset, RelType, 0);
+ Section.advanceStubOffset(getMaxStubSize());
+ }
+ } else if (Arch == Triple::sparcv9) {
+ DEBUG(dbgs() << "This is a SPARC64 relocation.\n");
+
+ SectionEntry &Section = Sections[SectionID];
+ uint8_t *Target = Section.getAddressWithOffset(Offset);
+ uint32_t *TargetAddress = reinterpret_cast<uint32_t*>(Target);
+ uint8_t *SectionAddress = Section.getAddress();
+ uintptr_t StubOffset = Section.getStubOffset();
+ uintptr_t StubAddress = static_cast<uintptr_t>(-1);
+
+ if (RelType == ELF::R_SPARC_WDISP30) {
+ // Look up for existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ DEBUG(dbgs() << " Stub function found\n");
+
+ StubAddress =
+ reinterpret_cast<uintptr_t>(Section.getAddressWithOffset(i->second));
+
+ resolveRelocation(Section, Offset, StubAddress, RelType, 0);
+ Section.advanceStubOffset(getMaxStubSize());
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+
+ uintptr_t BaseAddress =
+ reinterpret_cast<uintptr_t>(Section.getAddress());
+ uintptr_t StubAlignment = getStubAlignment();
+
+ StubAddress = BaseAddress + StubOffset;
+ StubAddress = llvm::RoundUpToAlignment(StubAddress, 8U);
+ StubOffset = StubAddress - BaseAddress;
+ Stubs[Value] = StubOffset;
+
+ uint8_t *StubTargetAddr =
+ createStubFunction(reinterpret_cast<uint8_t*>(StubAddress));
+
+ // Creating Hi and Lo relocations for the filled stub instructions.
+ RelocationEntry REhh(SectionID,
+ StubTargetAddr - SectionAddress,
+ ELF::R_SPARC_HH22, Value.Addend);
+ RelocationEntry REhm(SectionID,
+ StubTargetAddr - SectionAddress + 8,
+ ELF::R_SPARC_HM10, Value.Addend);
+ RelocationEntry RElm(SectionID,
+ StubTargetAddr - SectionAddress + 16,
+ ELF::R_SPARC_LM22, Value.Addend);
+ RelocationEntry RElo(SectionID,
+ StubTargetAddr - SectionAddress + 24,
+ ELF::R_SPARC_LO10, Value.Addend);
+
+ if (Value.SymbolName) {
+ addRelocationForSymbol(REhh, Value.SymbolName);
+ addRelocationForSymbol(REhm, Value.SymbolName);
+ addRelocationForSymbol(RElm, Value.SymbolName);
+ addRelocationForSymbol(RElo, Value.SymbolName);
+ } else {
+ addRelocationForSection(REhh, Value.SectionID);
+ addRelocationForSection(REhm, Value.SectionID);
+ addRelocationForSection(RElm, Value.SectionID);
+ addRelocationForSection(RElo, Value.SectionID);
+ }
+
+ resolveRelocation(Section, Offset, StubAddress, RelType, 0);
+ Section.advanceStubOffset(getMaxStubSize());
+ }
+ } else {
+ uintptr_t BaseAddress =
+ reinterpret_cast<uintptr_t>(Section.getAddress());
+ uintptr_t StubAlignment = getStubAlignment();
+ StubAddress = BaseAddress + StubOffset;
+ StubAddress = llvm::RoundUpToAlignment(StubAddress, 8U);
+ StubOffset = StubAddress - BaseAddress;
+
+ RelocationEntry RE(SectionID, Offset, RelType, Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+
+ resolveRelocation(Section, Offset, StubAddress, RelType, 0);
+ Section.advanceStubOffset(getMaxStubSize());
+ }
} else if (Arch == Triple::systemz &&
(RelType == ELF::R_390_PLT32DBL || RelType == ELF::R_390_GOTENT)) {
// Create function stubs for both PLT and GOT references, regardless of
###
--- lib/ExecutionEngine/ExecutionEngine.cpp 2015-10-13 10:11:02.000000000 -0800
+++ lib/ExecutionEngine/ExecutionEngine.cpp 2016-07-04 21:13:53.782045325 -0800
@@ -36,9 +36,12 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
#include <cmath>
#include <cstring>
-using namespace llvm;
+#include <memory>
#define DEBUG_TYPE "jit"
@@ -326,46 +329,57 @@
return nullptr;
}
+// Why is this in the anon namespace?
namespace {
class ArgvArray {
std::unique_ptr<char[]> Array;
std::vector<std::unique_ptr<char[]>> Values;
+
public:
+ ArgvArray() : Array(), Values() { }
+ ~ArgvArray() { }
+
/// Turn a vector of strings into a nice argv style array of pointers to null
/// terminated strings.
void *reset(LLVMContext &C, ExecutionEngine *EE,
const std::vector<std::string> &InputArgv);
};
} // anonymous namespace
+
void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE,
const std::vector<std::string> &InputArgv) {
- Values.clear(); // Free the old contents.
- Values.reserve(InputArgv.size());
+ Values.clear(); // Free the old contents.
+ Values.resize(InputArgv.size() + 1);
unsigned PtrSize = EE->getDataLayout().getPointerSize();
- Array = make_unique<char[]>((InputArgv.size()+1)*PtrSize);
+ Array = make_unique<char[]>((InputArgv.size() + 1) * PtrSize);
DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array.get() << "\n");
+
Type *SBytePtr = Type::getInt8PtrTy(C);
for (unsigned i = 0; i != InputArgv.size(); ++i) {
- unsigned Size = InputArgv[i].size()+1;
+ unsigned Size = InputArgv[i].size() + 1;
auto Dest = make_unique<char[]>(Size);
- DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*)Dest.get() << "\n");
+
+ DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*) Dest.get() << "\n");
std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest.get());
- Dest[Size-1] = 0;
+ Dest[Size - 1] = '\0';
+ GenericValue *GVP =
+ reinterpret_cast<GenericValue*>(&Array[i * PtrSize]);
// Endian safe: Array[i] = (PointerTy)Dest;
- EE->StoreValueToMemory(PTOGV(Dest.get()),
- (GenericValue*)(&Array[i*PtrSize]), SBytePtr);
+ EE->StoreValueToMemory(PTOGV(Dest.get()), GVP, SBytePtr);
Values.push_back(std::move(Dest));
}
+ GenericValue *GVT =
+ reinterpret_cast<GenericValue*>(&Array[InputArgv.size() * PtrSize]);
+
// Null terminate it
- EE->StoreValueToMemory(PTOGV(nullptr),
- (GenericValue*)(&Array[InputArgv.size()*PtrSize]),
- SBytePtr);
- return Array.get();
+ EE->StoreValueToMemory(PTOGV(0L), GVT, SBytePtr);
+ void *Retval = Array.get();
+ return Retval;
}
void ExecutionEngine::runStaticConstructorsDestructors(Module &module,
@@ -425,16 +439,17 @@
#endif
int ExecutionEngine::runFunctionAsMain(Function *Fn,
- const std::vector<std::string> &argv,
- const char * const * envp) {
+ const std::vector<std::string> &Argv,
+ const char* const *Envp) {
+ LLVMContext &Ctx = Fn->getContext();
std::vector<GenericValue> GVArgs;
GenericValue GVArgc;
- GVArgc.IntVal = APInt(32, argv.size());
+ GVArgc.IntVal = APInt(32, Argv.size());
// Check main() type
unsigned NumArgs = Fn->getFunctionType()->getNumParams();
FunctionType *FTy = Fn->getFunctionType();
- Type* PPInt8Ty = Type::getInt8PtrTy(Fn->getContext())->getPointerTo();
+ Type* PPInt8Ty = Type::getInt8PtrTy(Ctx)->getPointerTo();
// Check the argument types.
if (NumArgs > 3)
@@ -451,19 +466,20 @@
ArgvArray CArgv;
ArgvArray CEnv;
+
if (NumArgs) {
GVArgs.push_back(GVArgc); // Arg #0 = argc.
if (NumArgs > 1) {
// Arg #1 = argv.
- GVArgs.push_back(PTOGV(CArgv.reset(Fn->getContext(), this, argv)));
+ GVArgs.push_back(PTOGV(CArgv.reset(Ctx, this, Argv)));
assert(!isTargetNullPtr(this, GVTOP(GVArgs[1])) &&
"argv[0] was null after CreateArgv");
if (NumArgs > 2) {
std::vector<std::string> EnvVars;
- for (unsigned i = 0; envp[i]; ++i)
- EnvVars.emplace_back(envp[i]);
+ for (unsigned i = 0; Envp[i]; ++i)
+ EnvVars.emplace_back(Envp[i]);
// Arg #2 = envp.
- GVArgs.push_back(PTOGV(CEnv.reset(Fn->getContext(), this, EnvVars)));
+ GVArgs.push_back(PTOGV(CEnv.reset(Ctx, this, EnvVars)));
}
}
}
###
--- lib/ExecutionEngine/MCJIT/MCJIT.cpp 2015-11-05 10:24:56.000000000 -0900
+++ lib/ExecutionEngine/MCJIT/MCJIT.cpp 2016-07-04 09:15:17.759594945 -0800
@@ -43,34 +43,37 @@
}
ExecutionEngine*
-MCJIT::createJIT(std::unique_ptr<Module> M,
+MCJIT::createJIT(std::unique_ptr<Module> MIn,
std::string *ErrorStr,
- std::shared_ptr<MCJITMemoryManager> MemMgr,
- std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver,
- std::unique_ptr<TargetMachine> TM) {
+ std::shared_ptr<MCJITMemoryManager> MemMgrIn,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> ResolverIn,
+ std::unique_ptr<TargetMachine> TMIn) {
// Try to register the program as a source of symbols to resolve against.
//
// FIXME: Don't do this here.
sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr);
- if (!MemMgr || !Resolver) {
+ if (!MemMgrIn || !ResolverIn) {
auto RTDyldMM = std::make_shared<SectionMemoryManager>();
- if (!MemMgr)
- MemMgr = RTDyldMM;
- if (!Resolver)
- Resolver = RTDyldMM;
- }
-
- return new MCJIT(std::move(M), std::move(TM), std::move(MemMgr),
- std::move(Resolver));
-}
-
-MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM,
- std::shared_ptr<MCJITMemoryManager> MemMgr,
- std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver)
- : ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)),
- Ctx(nullptr), MemMgr(std::move(MemMgr)),
- Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver),
+ if (!MemMgrIn)
+ MemMgrIn = RTDyldMM;
+ if (!ResolverIn)
+ ResolverIn = RTDyldMM;
+ }
+
+ return new MCJIT(std::move(MIn), std::move(TMIn), std::move(MemMgrIn),
+ std::move(ResolverIn));
+}
+
+MCJIT::MCJIT(std::unique_ptr<Module> MIn,
+ std::unique_ptr<TargetMachine> TMIn,
+ std::shared_ptr<MCJITMemoryManager> MemMgrIn,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> ResolverIn)
+ : ExecutionEngine(TMIn->createDataLayout(), std::move(MIn)),
+ TM(std::move(TMIn)),
+ Ctx(nullptr), MemMgr(std::move(MemMgrIn)),
+ Resolver(*this, std::move(ResolverIn)),
+ Dyld(*this->MemMgr, this->Resolver),
ObjCache(nullptr) {
// FIXME: We are managing our modules, so we do not want the base class
// ExecutionEngine to manage them as well. To avoid double destruction
@@ -85,6 +88,7 @@
std::unique_ptr<Module> First = std::move(Modules[0]);
Modules.clear();
+ First->setDataLayout(ExecutionEngine::getDataLayout());
OwnedModules.addModule(std::move(First));
RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
}
@@ -148,7 +152,7 @@
legacy::PassManager PM;
// The RuntimeDyld will take ownership of this shortly
- SmallVector<char, 4096> ObjBufferSV;
+ SmallVector<char, 8192> ObjBufferSV;
raw_svector_ostream ObjStream(ObjBufferSV);
// Turn the machine code intermediate representation into bytes in memory
@@ -158,8 +162,8 @@
// Initialize passes.
PM.run(*M);
- // Flush the output buffer to get the generated code into memory
+ // Flush the output buffer to get the generated code into memory
std::unique_ptr<MemoryBuffer> CompiledObjBuffer(
new ObjectMemoryBuffer(std::move(ObjBufferSV)));
@@ -380,7 +384,7 @@
MutexGuard locked(lock);
Mangler Mang;
- SmallString<128> Name;
+ SmallString<512> Name;
TM->getNameWithPrefix(Name, F, Mang);
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
@@ -391,7 +395,8 @@
}
Module *M = F->getParent();
- bool HasBeenAddedButNotLoaded = OwnedModules.hasModuleBeenAddedButNotLoaded(M);
+ bool HasBeenAddedButNotLoaded =
+ OwnedModules.hasModuleBeenAddedButNotLoaded(M);
// Make sure the relevant module has been compiled and loaded.
if (HasBeenAddedButNotLoaded)
@@ -439,10 +444,11 @@
return nullptr;
}
-GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(const char *Name,
- bool AllowInternal,
- ModulePtrSet::iterator I,
- ModulePtrSet::iterator E) {
+GlobalVariable*
+MCJIT::FindGlobalVariableNamedInModulePtrSet(const char *Name,
+ bool AllowInternal,
+ ModulePtrSet::iterator I,
+ ModulePtrSet::iterator E) {
for (; I != E; ++I) {
GlobalVariable *GV = (*I)->getGlobalVariable(Name, AllowInternal);
if (GV && !GV->isDeclaration())
@@ -453,8 +459,9 @@
Function *MCJIT::FindFunctionNamed(const char *FnName) {
- Function *F = FindFunctionNamedInModulePtrSet(
- FnName, OwnedModules.begin_added(), OwnedModules.end_added());
+ Function *F =
+ FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_added(),
+ OwnedModules.end_added());
if (!F)
F = FindFunctionNamedInModulePtrSet(FnName, OwnedModules.begin_loaded(),
OwnedModules.end_loaded());
@@ -464,15 +471,20 @@
return F;
}
-GlobalVariable *MCJIT::FindGlobalVariableNamed(const char *Name, bool AllowInternal) {
- GlobalVariable *GV = FindGlobalVariableNamedInModulePtrSet(
- Name, AllowInternal, OwnedModules.begin_added(), OwnedModules.end_added());
+GlobalVariable *MCJIT::FindGlobalVariableNamed(const char *Name,
+ bool AllowInternal) {
+ GlobalVariable *GV =
+ FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal,
+ OwnedModules.begin_added(),
+ OwnedModules.end_added());
if (!GV)
- GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_loaded(),
- OwnedModules.end_loaded());
+ GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal,
+ OwnedModules.begin_loaded(),
+ OwnedModules.end_loaded());
if (!GV)
- GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal, OwnedModules.begin_finalized(),
- OwnedModules.end_finalized());
+ GV = FindGlobalVariableNamedInModulePtrSet(Name, AllowInternal,
+ OwnedModules.begin_finalized(),
+ OwnedModules.end_finalized());
return GV;
}
@@ -493,41 +505,57 @@
// Handle some common cases first. These cases correspond to common `main'
// prototypes.
if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
+ int Argc;
+ char **Argv;
+ const char **Envp;
+ GenericValue RV;
+ RV.IntVal = APInt(32, 1);
+
switch (ArgValues.size()) {
case 3:
if (FTy->getParamType(0)->isIntegerTy(32) &&
FTy->getParamType(1)->isPointerTy() &&
FTy->getParamType(2)->isPointerTy()) {
int (*PF)(int, char **, const char **) =
- (int(*)(int, char **, const char **))(intptr_t)FPtr;
+ (int(*)(int, char **, const char **))(uintptr_t)FPtr;
+
+ Argc = ArgValues[0].IntVal.getZExtValue();
+ assert(Argc >= 1 && "Invalid argument count!");
+
+ Argv = reinterpret_cast<char**>(ArgValues[1].PointerVal);
+ Envp = reinterpret_cast<const char**>(ArgValues[2].PointerVal);
// Call the function.
- GenericValue rv;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
- (char **)GVTOP(ArgValues[1]),
- (const char **)GVTOP(ArgValues[2])));
- return rv;
+ RV.IntVal = APInt(32, PF(Argc, Argv, Envp));
+ return RV;
}
break;
case 2:
if (FTy->getParamType(0)->isIntegerTy(32) &&
FTy->getParamType(1)->isPointerTy()) {
- int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;
+ int (*PF)(int, char **) =
+ (int(*)(int, char **))(uintptr_t)FPtr;
+
+ Argc = ArgValues[0].IntVal.getZExtValue();
+ assert(Argc >= 1 && "Invalid argument count!");
+
+ Argv = reinterpret_cast<char**>(ArgValues[1].PointerVal);
// Call the function.
- GenericValue rv;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
- (char **)GVTOP(ArgValues[1])));
- return rv;
+ RV.IntVal = APInt(32, PF(Argc, Argv));
+ return RV;
}
break;
case 1:
if (FTy->getNumParams() == 1 &&
FTy->getParamType(0)->isIntegerTy(32)) {
- GenericValue rv;
- int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
- return rv;
+ int (*PF)(int) = (int(*)(int))(uintptr_t)FPtr;
+ Argc = ArgValues[0].IntVal.getZExtValue();
+ assert(Argc == 1 && "Invalid argument count!");
+
+ // Call the function.
+ RV.IntVal = APInt(32, PF(Argc));
+ return RV;
}
break;
}
###
--- include/llvm/Object/ELFObjectFile.h 2016-01-12 11:56:01.000000000 -0900
+++ include/llvm/Object/ELFObjectFile.h 2016-07-03 05:39:54.209691940 -0800
@@ -840,8 +840,9 @@
case ELF::EM_PPC:
return "ELF32-ppc";
case ELF::EM_SPARC:
- case ELF::EM_SPARC32PLUS:
return "ELF32-sparc";
+ case ELF::EM_SPARC32PLUS:
+ return "ELF32-sparc32plus";
case ELF::EM_WEBASSEMBLY:
return "ELF32-wasm";
default:
@@ -860,7 +861,7 @@
case ELF::EM_S390:
return "ELF64-s390";
case ELF::EM_SPARCV9:
- return "ELF64-sparc";
+ return "ELF64-sparcv9";
case ELF::EM_MIPS:
return "ELF64-mips";
case ELF::EM_WEBASSEMBLY:
@@ -908,8 +909,8 @@
return Triple::systemz;
case ELF::EM_SPARC:
- case ELF::EM_SPARC32PLUS:
return IsLittleEndian ? Triple::sparcel : Triple::sparc;
+ case ELF::EM_SPARC32PLUS:
case ELF::EM_SPARCV9:
return Triple::sparcv9;
case ELF::EM_WEBASSEMBLY:
###
--- tools/lli/lli.cpp 2016-01-19 15:32:09.000000000 -0900
+++ tools/lli/lli.cpp 2016-07-03 18:17:05.510434280 -0800
@@ -54,6 +54,8 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h"
#include <cerrno>
+#include <string>
+#include <vector>
#ifdef __CYGWIN__
#include <cygwin/version.h>
@@ -66,176 +68,179 @@
#define DEBUG_TYPE "lli"
-namespace {
- enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy };
+enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy };
- cl::opt<std::string>
- InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-"));
+static cl::opt<std::string>
+InputFile(cl::desc("<input bitcode>"), cl::Positional,
+ cl::init(std::string("-")));
+
+static cl::list<std::string>
+InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
+
+static cl::opt<bool>
+ForceInterpreter("force-interpreter",
+ cl::desc("Force interpretation: disable JIT"),
+ cl::init(false));
+
+static cl::opt<JITKind>
+UseJITKind("jit-kind",
+ cl::desc("Choose underlying JIT kind."),
+ cl::init(JITKind::MCJIT),
+ cl::values(
+ clEnumValN(JITKind::MCJIT, "mcjit",
+ "MCJIT"),
+ clEnumValN(JITKind::OrcMCJITReplacement,
+ "orc-mcjit",
+ "Orc-based MCJIT replacement"),
+ clEnumValN(JITKind::OrcLazy,
+ "orc-lazy",
+ "Orc-based lazy JIT."),
+ clEnumValEnd));
+
+// The MCJIT supports building for a target address space separate from
+// the JIT compilation process. Use a forked process and a copying
+// memory manager with IPC to execute using this functionality.
+static cl::opt<bool>
+RemoteMCJIT("remote-mcjit",
+ cl::desc("Execute MCJIT'ed code in a separate process."),
+ cl::init(false));
+
+// Manually specify the child process for remote execution. This overrides
+// the simulated remote execution that allocates address space for child
+// execution. The child process will be executed and will communicate with
+// lli via stdin/stdout pipes.
+static cl::opt<std::string>
+ChildExecPath("mcjit-remote-process",
+ cl::desc("Specify the filename of the process to launch "
+ "for remote MCJIT execution. If none is specified,"
+ "\n\tremote execution will be simulated in-process."),
+ cl::value_desc("filename"),
+ cl::init(std::string("")));
+
+// Determine optimization level.
+static cl::opt<char>
+OptLevel("O",
+ cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+ "(default = '-O2')"),
+ cl::Prefix,
+ cl::ZeroOrMore,
+ cl::init(' '));
+
+static cl::opt<std::string>
+TargetTriple("mtriple", cl::desc("Override target triple for module"));
+
+static cl::opt<std::string>
+MArch("march",
+ cl::desc("Architecture to generate assembly for (see --version)"));
+
+static cl::opt<std::string>
+MCPU("mcpu",
+ cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+ cl::value_desc("cpu-name"),
+ cl::init(std::string("")));
+
+static cl::list<std::string>
+MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes (-mattr=help for details)"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
+static cl::opt<std::string>
+EntryFunc("entry-function",
+ cl::desc("Specify the entry function (default = 'main') "
+ "of the executable"),
+ cl::value_desc("function"),
+ cl::init(std::string("main")));
+
+static cl::list<std::string>
+ExtraModules("extra-module",
+ cl::desc("Extra modules to be loaded"),
+ cl::value_desc("input bitcode"));
+
+static cl::list<std::string>
+ExtraObjects("extra-object",
+ cl::desc("Extra object files to be loaded"),
+ cl::value_desc("input object"));
+
+static cl::list<std::string>
+ExtraArchives("extra-archive",
+ cl::desc("Extra archive files to be loaded"),
+ cl::value_desc("input archive"));
+
+static cl::opt<bool>
+EnableCacheManager("enable-cache-manager",
+ cl::desc("Use cache manager to save/load mdoules"),
+ cl::init(false));
+
+static cl::opt<std::string>
+ObjectCacheDir("object-cache-dir",
+ cl::desc("Directory to store cached object files "
+ "(must be user writable)"),
+ cl::init(std::string("")));
+
+static cl::opt<std::string>
+FakeArgv0("fake-argv0",
+ cl::desc("Override the 'argv[0]' value passed into the executing"
+ " program"), cl::value_desc("executable"));
+
+static cl::opt<bool>
+DisableCoreFiles("disable-core-files", cl::Hidden,
+ cl::desc("Disable emission of core files if possible"));
- cl::list<std::string>
- InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
-
- cl::opt<bool> ForceInterpreter("force-interpreter",
- cl::desc("Force interpretation: disable JIT"),
- cl::init(false));
-
- cl::opt<JITKind> UseJITKind("jit-kind",
- cl::desc("Choose underlying JIT kind."),
- cl::init(JITKind::MCJIT),
- cl::values(
- clEnumValN(JITKind::MCJIT, "mcjit",
- "MCJIT"),
- clEnumValN(JITKind::OrcMCJITReplacement,
- "orc-mcjit",
- "Orc-based MCJIT replacement"),
- clEnumValN(JITKind::OrcLazy,
- "orc-lazy",
- "Orc-based lazy JIT."),
- clEnumValEnd));
-
- // The MCJIT supports building for a target address space separate from
- // the JIT compilation process. Use a forked process and a copying
- // memory manager with IPC to execute using this functionality.
- cl::opt<bool> RemoteMCJIT("remote-mcjit",
- cl::desc("Execute MCJIT'ed code in a separate process."),
- cl::init(false));
-
- // Manually specify the child process for remote execution. This overrides
- // the simulated remote execution that allocates address space for child
- // execution. The child process will be executed and will communicate with
- // lli via stdin/stdout pipes.
- cl::opt<std::string>
- ChildExecPath("mcjit-remote-process",
- cl::desc("Specify the filename of the process to launch "
- "for remote MCJIT execution. If none is specified,"
- "\n\tremote execution will be simulated in-process."),
- cl::value_desc("filename"), cl::init(""));
-
- // Determine optimization level.
- cl::opt<char>
- OptLevel("O",
- cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
- "(default = '-O2')"),
- cl::Prefix,
- cl::ZeroOrMore,
- cl::init(' '));
-
- cl::opt<std::string>
- TargetTriple("mtriple", cl::desc("Override target triple for module"));
-
- cl::opt<std::string>
- MArch("march",
- cl::desc("Architecture to generate assembly for (see --version)"));
-
- cl::opt<std::string>
- MCPU("mcpu",
- cl::desc("Target a specific cpu type (-mcpu=help for details)"),
- cl::value_desc("cpu-name"),
- cl::init(""));
-
- cl::list<std::string>
- MAttrs("mattr",
- cl::CommaSeparated,
- cl::desc("Target specific attributes (-mattr=help for details)"),
- cl::value_desc("a1,+a2,-a3,..."));
-
- cl::opt<std::string>
- EntryFunc("entry-function",
- cl::desc("Specify the entry function (default = 'main') "
- "of the executable"),
- cl::value_desc("function"),
- cl::init("main"));
-
- cl::list<std::string>
- ExtraModules("extra-module",
- cl::desc("Extra modules to be loaded"),
- cl::value_desc("input bitcode"));
-
- cl::list<std::string>
- ExtraObjects("extra-object",
- cl::desc("Extra object files to be loaded"),
- cl::value_desc("input object"));
-
- cl::list<std::string>
- ExtraArchives("extra-archive",
- cl::desc("Extra archive files to be loaded"),
- cl::value_desc("input archive"));
-
- cl::opt<bool>
- EnableCacheManager("enable-cache-manager",
- cl::desc("Use cache manager to save/load mdoules"),
- cl::init(false));
-
- cl::opt<std::string>
- ObjectCacheDir("object-cache-dir",
- cl::desc("Directory to store cached object files "
- "(must be user writable)"),
- cl::init(""));
-
- cl::opt<std::string>
- FakeArgv0("fake-argv0",
- cl::desc("Override the 'argv[0]' value passed into the executing"
- " program"), cl::value_desc("executable"));
-
- cl::opt<bool>
- DisableCoreFiles("disable-core-files", cl::Hidden,
- cl::desc("Disable emission of core files if possible"));
-
- cl::opt<bool>
- NoLazyCompilation("disable-lazy-compilation",
+static cl::opt<bool>
+NoLazyCompilation("disable-lazy-compilation",
cl::desc("Disable JIT lazy compilation"),
cl::init(false));
- cl::opt<Reloc::Model>
- RelocModel("relocation-model",
- cl::desc("Choose relocation model"),
- cl::init(Reloc::Default),
- cl::values(
- clEnumValN(Reloc::Default, "default",
- "Target default relocation model"),
- clEnumValN(Reloc::Static, "static",
- "Non-relocatable code"),
- clEnumValN(Reloc::PIC_, "pic",
- "Fully relocatable, position independent code"),
- clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
- "Relocatable external references, non-relocatable code"),
- clEnumValEnd));
-
- cl::opt<llvm::CodeModel::Model>
- CMModel("code-model",
- cl::desc("Choose code model"),
- cl::init(CodeModel::JITDefault),
- cl::values(clEnumValN(CodeModel::JITDefault, "default",
- "Target default JIT code model"),
- clEnumValN(CodeModel::Small, "small",
- "Small code model"),
- clEnumValN(CodeModel::Kernel, "kernel",
- "Kernel code model"),
- clEnumValN(CodeModel::Medium, "medium",
- "Medium code model"),
- clEnumValN(CodeModel::Large, "large",
- "Large code model"),
- clEnumValEnd));
-
- cl::opt<bool>
- GenerateSoftFloatCalls("soft-float",
- cl::desc("Generate software floating point library calls"),
- cl::init(false));
-
- cl::opt<llvm::FloatABI::ABIType>
- FloatABIForCalls("float-abi",
- cl::desc("Choose float ABI type"),
- cl::init(FloatABI::Default),
- cl::values(
- clEnumValN(FloatABI::Default, "default",
- "Target default float ABI type"),
- clEnumValN(FloatABI::Soft, "soft",
- "Soft float ABI (implied by -soft-float)"),
- clEnumValN(FloatABI::Hard, "hard",
- "Hard float ABI (uses FP registers)"),
- clEnumValEnd));
-}
+static cl::opt<Reloc::Model>
+RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+static cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::JITDefault),
+ cl::values(clEnumValN(CodeModel::JITDefault, "default",
+ "Target default JIT code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
+static cl::opt<bool>
+GenerateSoftFloatCalls("soft-float",
+ cl::desc("Generate software floating point library calls"),
+ cl::init(false));
+
+static cl::opt<llvm::FloatABI::ABIType>
+FloatABIForCalls("float-abi",
+ cl::desc("Choose float ABI type"),
+ cl::init(FloatABI::Default),
+ cl::values(
+ clEnumValN(FloatABI::Default, "default",
+ "Target default float ABI type"),
+ clEnumValN(FloatABI::Soft, "soft",
+ "Soft float ABI (implied by -soft-float)"),
+ clEnumValN(FloatABI::Hard, "hard",
+ "Hard float ABI (uses FP registers)"),
+ clEnumValEnd));
//===----------------------------------------------------------------------===//
// Object cache
@@ -429,17 +434,17 @@
}
std::string ErrorMsg;
- EngineBuilder builder(std::move(Owner));
- builder.setMArch(MArch);
- builder.setMCPU(MCPU);
- builder.setMAttrs(MAttrs);
- builder.setRelocationModel(RelocModel);
- builder.setCodeModel(CMModel);
- builder.setErrorStr(&ErrorMsg);
- builder.setEngineKind(ForceInterpreter
+ EngineBuilder Builder(std::move(Owner));
+ Builder.setMArch(MArch);
+ Builder.setMCPU(MCPU);
+ Builder.setMAttrs(MAttrs);
+ Builder.setRelocationModel(RelocModel);
+ Builder.setCodeModel(CMModel);
+ Builder.setErrorStr(&ErrorMsg);
+ Builder.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
: EngineKind::JIT);
- builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement);
+ Builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement);
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
@@ -455,7 +460,7 @@
// Deliberately construct a temp std::unique_ptr to pass in. Do not null out
// RTDyldMM: We still use it below, even though we don't own it.
- builder.setMCJITMemoryManager(
+ Builder.setMCJITMemoryManager(
std::unique_ptr<RTDyldMemoryManager>(RTDyldMM));
} else if (RemoteMCJIT) {
errs() << "error: Remote process execution does not work with the "
@@ -463,15 +468,15 @@
exit(1);
}
- builder.setOptLevel(getOptLevel());
+ Builder.setOptLevel(getOptLevel());
TargetOptions Options;
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
- builder.setTargetOptions(Options);
+ Builder.setTargetOptions(Options);
- EE = builder.create();
+ EE = Builder.create();
if (!EE) {
if (!ErrorMsg.empty())
errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
@@ -550,12 +555,16 @@
errs() << "warning: remote mcjit does not support lazy compilation\n";
NoLazyCompilation = true;
}
+
EE->DisableLazyCompilation(NoLazyCompilation);
+ std::string Argv0;
+ std::vector<std::string> ArgvVector;
+
// If the user specifically requested an argv[0] to pass into the program,
// do it now.
- if (!FakeArgv0.empty()) {
- InputFile = static_cast<std::string>(FakeArgv0);
+ if (!FakeArgv0.getValue().empty()) {
+ InputFile.setValue(FakeArgv0.getValue());
} else {
// Otherwise, if there is a .bc suffix on the executable strip it off, it
// might confuse the program.
@@ -563,25 +572,59 @@
InputFile.erase(InputFile.length() - 3);
}
+ Argv0 = InputFile.getValue();
+ ArgvVector.push_back(Argv0);
+
// Add the module's name to the start of the vector of arguments to main().
- InputArgv.insert(InputArgv.begin(), InputFile);
+ ArgvVector.insert(ArgvVector.end(), InputArgv.begin(), InputArgv.end());
// Call the main function from M as if its signature were:
// int main (int argc, char **argv, const char **envp)
// using the contents of Args to determine argc & argv, and the contents of
// EnvVars to determine envp.
//
- Function *EntryFn = Mod->getFunction(EntryFunc);
+ std::string EntryFuncName = EntryFunc.getValue();
+ LLVMContext &Ctx = Mod->getContext();
+
+ llvm::Type *PPInt8ArgvTy = llvm::Type::getInt8PtrTy(Ctx)->getPointerTo();
+ llvm::Type *PPInt8EnvpTy = llvm::Type::getInt8PtrTy(Ctx)->getPointerTo();
+ llvm::IntegerType *PInt32RetTy = llvm::Type::getInt32Ty(Ctx);
+ llvm::IntegerType *PInt32ArgcTy = llvm::Type::getInt32Ty(Ctx);
+ llvm::Type *VoidRetTy = llvm::Type::getVoidTy(Ctx);
+ llvm::Type *VoidArgTy = llvm::Type::getVoidTy(Ctx);
+
+ Constant *EC = Mod->getOrInsertFunction("main",
+ PInt32RetTy, PInt32ArgcTy,
+ PPInt8ArgvTy, PPInt8EnvpTy,
+ nullptr);
+
+ Function *EntryFn = dyn_cast<Function>(EC);
+ if (!EntryFn) {
+ EC = Mod->getOrInsertFunction("main", PInt32RetTy, PInt32ArgcTy,
+ PPInt8ArgvTy, nullptr);
+ EntryFn = dyn_cast<Function>(EC);
+ }
+
+ if (!EntryFn) {
+ EC = Mod->getOrInsertFunction("main", PInt32RetTy, nullptr);
+ EntryFn = dyn_cast<Function>(EC);
+ }
+
+ if (!EntryFn) {
+ EC = Mod->getOrInsertFunction("main", VoidRetTy, nullptr);
+ EntryFn = dyn_cast<Function>(EC);
+ }
+
if (!EntryFn) {
errs() << '\'' << EntryFunc << "\' function not found in module.\n";
return -1;
}
+ EntryFn->setCallingConv(CallingConv::C);
+
// Reset errno to zero on entry to main.
errno = 0;
- int Result;
-
// Sanity check use of remote-jit: LLI currently only supports use of the
// remote JIT on Unix platforms.
if (RemoteMCJIT) {
@@ -601,29 +644,48 @@
#endif
}
+ int Result = 0;
+ Constant *Exit = nullptr;
+ Function *ExitFn = nullptr;
+ void *EntryFnPtr = nullptr;
+ void *ExitFnPtr = nullptr;
+
if (!RemoteMCJIT) {
// If the program doesn't explicitly call exit, we will need the Exit
// function later on to make an explicit call, so get the function now.
- Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
- Type::getInt32Ty(Context),
- nullptr);
+ Exit = Mod->getOrInsertFunction("exit",
+ Type::getVoidTy(Context),
+ Type::getInt32Ty(Context),
+ nullptr);
+ assert(Exit && "Could not create an exit(2) Constant!");
+
+ ExitFn = cast_or_null<Function>(Exit);
+ assert(ExitFn && "Could not create an exit(2) Function!");
+
+ ExitFnPtr = EE->getPointerToFunction(ExitFn);
+ assert(ExitFnPtr && "Could not retrieve an exit(2) Function pointer!");
+ (void) ExitFnPtr;
// Run static constructors.
if (!ForceInterpreter) {
// Give MCJIT a chance to apply relocations and set page permissions.
EE->finalizeObject();
}
+
EE->runStaticConstructorsDestructors(false);
// Trigger compilation separately so code regions that need to be
// invalidated will be known.
- (void)EE->getPointerToFunction(EntryFn);
+ EntryFnPtr = EE->getPointerToFunction(EntryFn);
+ assert(EntryFnPtr && "Could not retrieve a main(2) Function pointer!");
+ (void) EntryFnPtr;
+
// Clear instruction cache before code will be executed.
if (RTDyldMM)
static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache();
// Run main.
- Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
+ Result = EE->runFunctionAsMain(EntryFn, ArgvVector, envp);
// Run static destructors.
EE->runStaticConstructorsDestructors(true);