Loading llvm/lib/Target/PowerPC/PPCISelLowering.cpp +64 −24 Original line number Diff line number Diff line Loading @@ -5117,6 +5117,15 @@ static unsigned getCallOpcode(bool isIndirectCall, bool isPatchPoint, return PPCISD::CALL; } static bool isValidAIXExternalSymSDNode(StringRef SymName) { return StringSwitch<bool>(SymName) .Cases("__divdi3", "__fixunsdfdi", "__floatundidf", "__floatundisf", "__moddi3", "__udivdi3", "__umoddi3", true) .Cases("ceil", "floor", "memcpy", "memmove", "memset", "round", true) .Default(false); } static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG, const SDLoc &dl, const PPCSubtarget &Subtarget) { if (!Subtarget.usesFunctionDescriptors() && !Subtarget.isELFv2ABI()) Loading @@ -5141,42 +5150,73 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG, Subtarget.is32BitELFABI() && !isLocalCallee() && Subtarget.getTargetMachine().getRelocationModel() == Reloc::PIC_; if (isFunctionGlobalAddress(Callee)) { const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); if (!Subtarget.isAIXABI()) return DAG.getTargetGlobalAddress(G->getGlobal(), dl, Callee.getValueType(), 0, UsePlt ? PPCII::MO_PLT : 0); // On AIX, direct function calls reference the symbol for the function's // entry point, which is named by prepending a "." before the function's // C-linkage name. const auto getAIXFuncEntryPointSymbolSDNode = [&](StringRef FuncName, bool IsDeclaration, const XCOFF::StorageClass &SC) { auto &Context = DAG.getMachineFunction().getMMI().getContext(); const GlobalObject *GO = cast<GlobalObject>(G->getGlobal()); MCSymbolXCOFF *S = cast<MCSymbolXCOFF>( Context.getOrCreateSymbol(Twine(".") + Twine(GO->getName()))); Context.getOrCreateSymbol(Twine(".") + Twine(FuncName))); if (GO && GO->isDeclaration() && !S->hasContainingCsect()) { if (IsDeclaration && !S->hasContainingCsect()) { // On AIX, an undefined symbol needs to be associated with a // MCSectionXCOFF to get the correct storage mapping class. // In this case, XCOFF::XMC_PR. const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); MCSectionXCOFF *Sec = Context.getXCOFFSection(S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC, SectionKind::getMetadata()); MCSectionXCOFF *Sec = Context.getXCOFFSection( S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC, SectionKind::getMetadata()); S->setContainingCsect(Sec); } EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); return DAG.getMCSymbol(S, PtrVT); }; if (isFunctionGlobalAddress(Callee)) { const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); const GlobalValue *GV = G->getGlobal(); if (!Subtarget.isAIXABI()) return DAG.getTargetGlobalAddress(GV, dl, Callee.getValueType(), 0, UsePlt ? PPCII::MO_PLT : 0); assert(!isa<GlobalIFunc>(GV) && "IFunc is not supported on AIX."); const GlobalObject *GO = cast<GlobalObject>(GV); const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); return getAIXFuncEntryPointSymbolSDNode(GO->getName(), GO->isDeclaration(), SC); } if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) return DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType(), if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { const char *SymName = S->getSymbol(); if (!Subtarget.isAIXABI()) return DAG.getTargetExternalSymbol(SymName, Callee.getValueType(), UsePlt ? PPCII::MO_PLT : 0); // If there exists a user-declared function whose name is the same as the // ExternalSymbol's, then we pick up the user-declared version. const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); if (const Function *F = dyn_cast_or_null<Function>(Mod->getNamedValue(SymName))) { const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(F); return getAIXFuncEntryPointSymbolSDNode(F->getName(), F->isDeclaration(), SC); } // TODO: Remove this when the support for ExternalSymbolSDNode is complete. if (isValidAIXExternalSymSDNode(SymName)) { return getAIXFuncEntryPointSymbolSDNode(SymName, true, XCOFF::C_EXT); } report_fatal_error("Unexpected ExternalSymbolSDNode: " + Twine(SymName)); } // No transformation needed. assert(Callee.getNode() && "What no callee?"); return Callee; Loading llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll 0 → 100644 +128 −0 Original line number Diff line number Diff line ; RUN: llc -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff \ ; RUN: -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=32BIT %s ; RUN: llc -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \ ; RUN: -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=64BIT %s define i64 @call_divdi3(i64 %p, i64 %num) { entry: %div = sdiv i64 %p, %num ret i64 %div } ; 32BIT: BL_NOP <mcsymbol .__divdi3> define i64 @call_fixunsdfdi(double %p) { entry: %conv = fptoui double %p to i64 ret i64 %conv } ; 32BIT: BL_NOP <mcsymbol .__fixunsdfdi> define double @call_floatundidf(i64 %p) { entry: %conv = uitofp i64 %p to double ret double %conv } ; 32BIT: BL_NOP <mcsymbol .__floatundidf> define float @call_floatundisf(i64 %p) { entry: %conv = uitofp i64 %p to float ret float %conv } ; 32BIT: BL_NOP <mcsymbol .__floatundisf> define i64 @call_moddi3(i64 %p, i64 %num) { entry: %rem = srem i64 %p, %num ret i64 %rem } ; 32BIT: BL_NOP <mcsymbol .__moddi3> define i64 @call_udivdi3(i64 %p, i64 %q) { %1 = udiv i64 %p, %q ret i64 %1 } ; 32BIT: BL_NOP <mcsymbol .__udivdi3> define i64 @call_umoddi3(i64 %p, i64 %num) { entry: %rem = urem i64 %p, %num ret i64 %rem } ; 32BIT: BL_NOP <mcsymbol .__umoddi3> define double @call_ceil(double %n) { entry: %0 = call double @llvm.ceil.f64(double %n) ret double %0 } declare double @llvm.ceil.f64(double) ; 32BIT: BL_NOP <mcsymbol .ceil> ; 64BIT: BL8_NOP <mcsymbol .ceil> define double @call_floor(double %n) { entry: %0 = call double @llvm.floor.f64(double %n) ret double %0 } declare double @llvm.floor.f64(double) ; 32BIT: BL_NOP <mcsymbol .floor> ; 64BIT: BL8_NOP <mcsymbol .floor> define void @call_memcpy(i8* %p, i8* %q, i32 %n) { entry: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ret void } declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) ; 32BIT: BL_NOP <mcsymbol .memcpy> ; 64BIT: BL8_NOP <mcsymbol .memcpy> define void @call_memmove(i8* %p, i8* %q, i32 %n) { entry: call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ret void } declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) ; 32BIT: BL_NOP <mcsymbol .memmove> ; 64BIT: BL8_NOP <mcsymbol .memmove> define void @call_memset(i8* %p, i8 %q, i32 %n) #0 { entry: call void @llvm.memset.p0i8.i32(i8* %p, i8 %q, i32 %n, i1 false) ret void } declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) ; 32BIT: BL_NOP <mcsymbol .memset> ; 64BIT: BL8_NOP <mcsymbol .memset> define double @call_round(double %n) { entry: %0 = call double @llvm.round.f64(double %n) ret double %0 } declare double @llvm.round.f64(double) ; 32BIT: BL_NOP <mcsymbol .round> ; 64BIT: BL8_NOP <mcsymbol .round> llvm/test/CodeGen/PowerPC/aix-user-defined-memcpy.ll 0 → 100644 +58 −0 Original line number Diff line number Diff line ; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ ; RUN: -mattr=-altivec -filetype=obj -o %t.o < %s ; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=32-SYM %s ; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck \ ; RUN: --check-prefix=32-REL %s ; RUN: not llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \ ; RUN: -mcpu=pwr4 -mattr=-altivec -filetype=obj < %s 2>&1 | FileCheck \ ; RUN: --check-prefix=64-CHECK %s ; Test verifies: ; If there exists a user-defined function whose name is the same as the ; "memcpy" ExternalSymbol's, we pick up the user-defined version, even if this ; may lead to some undefined behavior. define dso_local signext i32 @memcpy(i8* %destination, i32 signext %num) { entry: ret i32 3 } define void @call_memcpy(i8* %p, i8* %q, i32 %n) { entry: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ret void } declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) ; TODO: This test should preferably check the symbol table for .o file and ; the relocation associated with the call. ; 32-SYM: Symbol {{[{][[:space:]] *}}Index: [[#Index:]]{{[[:space:]] *}}Name: .memcpy ; 32-SYM-NEXT: Value (RelocatableAddress): 0x0 ; 32-SYM-NEXT: Section: .text ; 32-SYM-NEXT: Type: 0x0 ; 32-SYM-NEXT: StorageClass: C_EXT (0x2) ; 32-SYM-NEXT: NumberOfAuxEntries: 1 ; 32-SYM-NEXT: CSECT Auxiliary Entry { ; 32-SYM-NEXT: Index: 3 ; 32-SYM-NEXT: ContainingCsectSymbolIndex: 0 ; 32-SYM-NEXT: ParameterHashIndex: 0x0 ; 32-SYM-NEXT: TypeChkSectNum: 0x0 ; 32-SYM-NEXT: SymbolAlignmentLog2: 0 ; 32-SYM-NEXT: SymbolType: XTY_LD (0x2) ; 32-SYM-NEXT: StorageMappingClass: XMC_PR (0x0) ; 32-SYM-NEXT: StabInfoIndex: 0x0 ; 32-SYM-NEXT: StabSectNum: 0x0 ; 32-SYM-NEXT: } ; 32-SYM-NEXT: } ; 32-SYM-NOT: .memcpy ; We are expecting to have the test fail when the support for relocations land. ; 32-REL-NOT: Relocation{{[[:space:]]}} ; 64-CHECK: LLVM ERROR: 64-bit XCOFF object files are not supported yet. Loading
llvm/lib/Target/PowerPC/PPCISelLowering.cpp +64 −24 Original line number Diff line number Diff line Loading @@ -5117,6 +5117,15 @@ static unsigned getCallOpcode(bool isIndirectCall, bool isPatchPoint, return PPCISD::CALL; } static bool isValidAIXExternalSymSDNode(StringRef SymName) { return StringSwitch<bool>(SymName) .Cases("__divdi3", "__fixunsdfdi", "__floatundidf", "__floatundisf", "__moddi3", "__udivdi3", "__umoddi3", true) .Cases("ceil", "floor", "memcpy", "memmove", "memset", "round", true) .Default(false); } static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG, const SDLoc &dl, const PPCSubtarget &Subtarget) { if (!Subtarget.usesFunctionDescriptors() && !Subtarget.isELFv2ABI()) Loading @@ -5141,42 +5150,73 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG, Subtarget.is32BitELFABI() && !isLocalCallee() && Subtarget.getTargetMachine().getRelocationModel() == Reloc::PIC_; if (isFunctionGlobalAddress(Callee)) { const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); if (!Subtarget.isAIXABI()) return DAG.getTargetGlobalAddress(G->getGlobal(), dl, Callee.getValueType(), 0, UsePlt ? PPCII::MO_PLT : 0); // On AIX, direct function calls reference the symbol for the function's // entry point, which is named by prepending a "." before the function's // C-linkage name. const auto getAIXFuncEntryPointSymbolSDNode = [&](StringRef FuncName, bool IsDeclaration, const XCOFF::StorageClass &SC) { auto &Context = DAG.getMachineFunction().getMMI().getContext(); const GlobalObject *GO = cast<GlobalObject>(G->getGlobal()); MCSymbolXCOFF *S = cast<MCSymbolXCOFF>( Context.getOrCreateSymbol(Twine(".") + Twine(GO->getName()))); Context.getOrCreateSymbol(Twine(".") + Twine(FuncName))); if (GO && GO->isDeclaration() && !S->hasContainingCsect()) { if (IsDeclaration && !S->hasContainingCsect()) { // On AIX, an undefined symbol needs to be associated with a // MCSectionXCOFF to get the correct storage mapping class. // In this case, XCOFF::XMC_PR. const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); MCSectionXCOFF *Sec = Context.getXCOFFSection(S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC, SectionKind::getMetadata()); MCSectionXCOFF *Sec = Context.getXCOFFSection( S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC, SectionKind::getMetadata()); S->setContainingCsect(Sec); } EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); return DAG.getMCSymbol(S, PtrVT); }; if (isFunctionGlobalAddress(Callee)) { const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); const GlobalValue *GV = G->getGlobal(); if (!Subtarget.isAIXABI()) return DAG.getTargetGlobalAddress(GV, dl, Callee.getValueType(), 0, UsePlt ? PPCII::MO_PLT : 0); assert(!isa<GlobalIFunc>(GV) && "IFunc is not supported on AIX."); const GlobalObject *GO = cast<GlobalObject>(GV); const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO); return getAIXFuncEntryPointSymbolSDNode(GO->getName(), GO->isDeclaration(), SC); } if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) return DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType(), if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { const char *SymName = S->getSymbol(); if (!Subtarget.isAIXABI()) return DAG.getTargetExternalSymbol(SymName, Callee.getValueType(), UsePlt ? PPCII::MO_PLT : 0); // If there exists a user-declared function whose name is the same as the // ExternalSymbol's, then we pick up the user-declared version. const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); if (const Function *F = dyn_cast_or_null<Function>(Mod->getNamedValue(SymName))) { const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(F); return getAIXFuncEntryPointSymbolSDNode(F->getName(), F->isDeclaration(), SC); } // TODO: Remove this when the support for ExternalSymbolSDNode is complete. if (isValidAIXExternalSymSDNode(SymName)) { return getAIXFuncEntryPointSymbolSDNode(SymName, true, XCOFF::C_EXT); } report_fatal_error("Unexpected ExternalSymbolSDNode: " + Twine(SymName)); } // No transformation needed. assert(Callee.getNode() && "What no callee?"); return Callee; Loading
llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll 0 → 100644 +128 −0 Original line number Diff line number Diff line ; RUN: llc -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff \ ; RUN: -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=32BIT %s ; RUN: llc -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \ ; RUN: -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=64BIT %s define i64 @call_divdi3(i64 %p, i64 %num) { entry: %div = sdiv i64 %p, %num ret i64 %div } ; 32BIT: BL_NOP <mcsymbol .__divdi3> define i64 @call_fixunsdfdi(double %p) { entry: %conv = fptoui double %p to i64 ret i64 %conv } ; 32BIT: BL_NOP <mcsymbol .__fixunsdfdi> define double @call_floatundidf(i64 %p) { entry: %conv = uitofp i64 %p to double ret double %conv } ; 32BIT: BL_NOP <mcsymbol .__floatundidf> define float @call_floatundisf(i64 %p) { entry: %conv = uitofp i64 %p to float ret float %conv } ; 32BIT: BL_NOP <mcsymbol .__floatundisf> define i64 @call_moddi3(i64 %p, i64 %num) { entry: %rem = srem i64 %p, %num ret i64 %rem } ; 32BIT: BL_NOP <mcsymbol .__moddi3> define i64 @call_udivdi3(i64 %p, i64 %q) { %1 = udiv i64 %p, %q ret i64 %1 } ; 32BIT: BL_NOP <mcsymbol .__udivdi3> define i64 @call_umoddi3(i64 %p, i64 %num) { entry: %rem = urem i64 %p, %num ret i64 %rem } ; 32BIT: BL_NOP <mcsymbol .__umoddi3> define double @call_ceil(double %n) { entry: %0 = call double @llvm.ceil.f64(double %n) ret double %0 } declare double @llvm.ceil.f64(double) ; 32BIT: BL_NOP <mcsymbol .ceil> ; 64BIT: BL8_NOP <mcsymbol .ceil> define double @call_floor(double %n) { entry: %0 = call double @llvm.floor.f64(double %n) ret double %0 } declare double @llvm.floor.f64(double) ; 32BIT: BL_NOP <mcsymbol .floor> ; 64BIT: BL8_NOP <mcsymbol .floor> define void @call_memcpy(i8* %p, i8* %q, i32 %n) { entry: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ret void } declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) ; 32BIT: BL_NOP <mcsymbol .memcpy> ; 64BIT: BL8_NOP <mcsymbol .memcpy> define void @call_memmove(i8* %p, i8* %q, i32 %n) { entry: call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ret void } declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) ; 32BIT: BL_NOP <mcsymbol .memmove> ; 64BIT: BL8_NOP <mcsymbol .memmove> define void @call_memset(i8* %p, i8 %q, i32 %n) #0 { entry: call void @llvm.memset.p0i8.i32(i8* %p, i8 %q, i32 %n, i1 false) ret void } declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) ; 32BIT: BL_NOP <mcsymbol .memset> ; 64BIT: BL8_NOP <mcsymbol .memset> define double @call_round(double %n) { entry: %0 = call double @llvm.round.f64(double %n) ret double %0 } declare double @llvm.round.f64(double) ; 32BIT: BL_NOP <mcsymbol .round> ; 64BIT: BL8_NOP <mcsymbol .round>
llvm/test/CodeGen/PowerPC/aix-user-defined-memcpy.ll 0 → 100644 +58 −0 Original line number Diff line number Diff line ; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ ; RUN: -mattr=-altivec -filetype=obj -o %t.o < %s ; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=32-SYM %s ; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck \ ; RUN: --check-prefix=32-REL %s ; RUN: not llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \ ; RUN: -mcpu=pwr4 -mattr=-altivec -filetype=obj < %s 2>&1 | FileCheck \ ; RUN: --check-prefix=64-CHECK %s ; Test verifies: ; If there exists a user-defined function whose name is the same as the ; "memcpy" ExternalSymbol's, we pick up the user-defined version, even if this ; may lead to some undefined behavior. define dso_local signext i32 @memcpy(i8* %destination, i32 signext %num) { entry: ret i32 3 } define void @call_memcpy(i8* %p, i8* %q, i32 %n) { entry: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) ret void } declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) ; TODO: This test should preferably check the symbol table for .o file and ; the relocation associated with the call. ; 32-SYM: Symbol {{[{][[:space:]] *}}Index: [[#Index:]]{{[[:space:]] *}}Name: .memcpy ; 32-SYM-NEXT: Value (RelocatableAddress): 0x0 ; 32-SYM-NEXT: Section: .text ; 32-SYM-NEXT: Type: 0x0 ; 32-SYM-NEXT: StorageClass: C_EXT (0x2) ; 32-SYM-NEXT: NumberOfAuxEntries: 1 ; 32-SYM-NEXT: CSECT Auxiliary Entry { ; 32-SYM-NEXT: Index: 3 ; 32-SYM-NEXT: ContainingCsectSymbolIndex: 0 ; 32-SYM-NEXT: ParameterHashIndex: 0x0 ; 32-SYM-NEXT: TypeChkSectNum: 0x0 ; 32-SYM-NEXT: SymbolAlignmentLog2: 0 ; 32-SYM-NEXT: SymbolType: XTY_LD (0x2) ; 32-SYM-NEXT: StorageMappingClass: XMC_PR (0x0) ; 32-SYM-NEXT: StabInfoIndex: 0x0 ; 32-SYM-NEXT: StabSectNum: 0x0 ; 32-SYM-NEXT: } ; 32-SYM-NEXT: } ; 32-SYM-NOT: .memcpy ; We are expecting to have the test fail when the support for relocations land. ; 32-REL-NOT: Relocation{{[[:space:]]}} ; 64-CHECK: LLVM ERROR: 64-bit XCOFF object files are not supported yet.