[COFF, ARM64] Add support for Windows ARM64 COFF format

Summary:
This is the llvm part of the initial implementation to support Windows ARM64 COFF format.
I will gradually add more functionality in subsequent patches.

Reviewers: ruiu, rnk, t.p.northover, compnerd

Reviewed By: ruiu, compnerd

Subscribers: aemerson, mgorny, javed.absar, llvm-commits, kristof.beyls

Differential Revision: https://reviews.llvm.org/D34705

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306490 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mandeep Singh Grang 2017-06-27 23:58:19 +00:00
parent a4799adf39
commit 85e0946267
16 changed files with 249 additions and 5 deletions

View File

@ -1216,6 +1216,29 @@ void COFFObjectFile::getRelocationTypeName(
Res = "Unknown";
}
break;
case COFF::IMAGE_FILE_MACHINE_ARM64:
switch (Reloc->Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
default:
Res = "Unknown";
}
break;
case COFF::IMAGE_FILE_MACHINE_I386:
switch (Reloc->Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);

View File

@ -151,13 +151,25 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
return MCOperand::createExpr(Expr);
}
MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
MCSymbol *Sym) const {
MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
if (!MO.isJTI() && MO.getOffset())
Expr = MCBinaryExpr::createAdd(
Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
return MCOperand::createExpr(Expr);
}
MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
MCSymbol *Sym) const {
if (Printer.TM.getTargetTriple().isOSDarwin())
return lowerSymbolOperandDarwin(MO, Sym);
if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
return lowerSymbolOperandCOFF(MO, Sym);
assert(Printer.TM.getTargetTriple().isOSBinFormatELF() &&
"Expect Darwin or ELF target");
"Expect Darwin, ELF or COFF target");
return lowerSymbolOperandELF(MO, Sym);
}

View File

@ -42,6 +42,8 @@ public:
MCSymbol *Sym) const;
MCOperand lowerSymbolOperandELF(const MachineOperand &MO,
MCSymbol *Sym) const;
MCOperand lowerSymbolOperandCOFF(const MachineOperand &MO,
MCSymbol *Sym) const;
MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;

View File

@ -167,6 +167,8 @@ extern "C" void LLVMInitializeAArch64Target() {
static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
if (TT.isOSBinFormatMachO())
return llvm::make_unique<AArch64_MachoTargetObjectFile>();
if (TT.isOSBinFormatCOFF())
return llvm::make_unique<AArch64_COFFTargetObjectFile>();
return llvm::make_unique<AArch64_ELFTargetObjectFile>();
}
@ -179,6 +181,8 @@ static std::string computeDataLayout(const Triple &TT,
return "e-m:e-p:32:32-i8:8-i16:16-i64:64-S128";
if (TT.isOSBinFormatMachO())
return "e-m:o-i64:64-i128:128-n32:64-S128";
if (TT.isOSBinFormatCOFF())
return "e-m:w-i64:64-i128:128-n32:64-S128";
if (LittleEndian)
return "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";
return "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";

View File

@ -45,6 +45,9 @@ public:
const TargetMachine &TM) const override;
};
/// This implementation is used for AArch64 COFF targets.
class AArch64_COFFTargetObjectFile : public TargetLoweringObjectFileCOFF {};
} // end namespace llvm
#endif

View File

@ -567,6 +567,18 @@ void ELFAArch64AsmBackend::processFixupValue(const MCAssembler &Asm,
}
namespace {
class COFFAArch64AsmBackend : public AArch64AsmBackend {
public:
COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple)
: AArch64AsmBackend(T, /*IsLittleEndian*/true) {}
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
return createAArch64WinCOFFObjectWriter(OS);
}
};
}
MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
const MCRegisterInfo &MRI,
const Triple &TheTriple,
@ -575,7 +587,12 @@ MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
if (TheTriple.isOSBinFormatMachO())
return new DarwinAArch64AsmBackend(T, MRI);
assert(TheTriple.isOSBinFormatELF() && "Expect either MachO or ELF target");
if (TheTriple.isOSBinFormatCOFF())
return new COFFAArch64AsmBackend(T, TheTriple);
assert(TheTriple.isOSBinFormatELF() &&
"Expect either MachO, ELF or COFF target");
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
bool IsILP32 = Options.getABIName() == "ilp32";
return new ELFAArch64AsmBackend(T, OSABI, /*IsLittleEndian=*/true, IsILP32);

View File

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "AArch64TargetStreamer.h"
#include "AArch64WinCOFFStreamer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@ -30,6 +31,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCWinCOFFStreamer.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
@ -210,6 +212,8 @@ createAArch64ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
const Triple &TT = STI.getTargetTriple();
if (TT.isOSBinFormatELF())
return new AArch64TargetELFStreamer(S);
if (TT.isOSBinFormatCOFF())
return new AArch64TargetWinCOFFStreamer(S);
return nullptr;
}

View File

@ -100,3 +100,7 @@ AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) {
HasIdentDirective = true;
}
AArch64MCAsmInfoCOFF::AArch64MCAsmInfoCOFF() {
CommentString = ";";
}

View File

@ -14,6 +14,7 @@
#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H
#include "llvm/MC/MCAsmInfoCOFF.h"
#include "llvm/MC/MCAsmInfoDarwin.h"
#include "llvm/MC/MCAsmInfoELF.h"
@ -33,6 +34,10 @@ struct AArch64MCAsmInfoELF : public MCAsmInfoELF {
explicit AArch64MCAsmInfoELF(const Triple &T);
};
struct AArch64MCAsmInfoCOFF : public MCAsmInfoCOFF {
explicit AArch64MCAsmInfoCOFF();
};
} // namespace llvm
#endif

View File

@ -14,6 +14,7 @@
#include "AArch64MCTargetDesc.h"
#include "AArch64ELFStreamer.h"
#include "AArch64MCAsmInfo.h"
#include "AArch64WinCOFFStreamer.h"
#include "InstPrinter/AArch64InstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
@ -59,8 +60,10 @@ static MCAsmInfo *createAArch64MCAsmInfo(const MCRegisterInfo &MRI,
MCAsmInfo *MAI;
if (TheTriple.isOSBinFormatMachO())
MAI = new AArch64MCAsmInfoDarwin();
else if (TheTriple.isOSBinFormatCOFF())
MAI = new AArch64MCAsmInfoCOFF();
else {
assert(TheTriple.isOSBinFormatELF() && "Only expect Darwin or ELF");
assert(TheTriple.isOSBinFormatELF() && "Only expect Darwin, ELF or COFF");
MAI = new AArch64MCAsmInfoELF(TheTriple);
}
@ -74,8 +77,9 @@ static MCAsmInfo *createAArch64MCAsmInfo(const MCRegisterInfo &MRI,
static void adjustCodeGenOpts(const Triple &TT, Reloc::Model RM,
CodeModel::Model &CM) {
assert((TT.isOSBinFormatELF() || TT.isOSBinFormatMachO()) &&
"Only expect Darwin and ELF targets");
assert((TT.isOSBinFormatELF() || TT.isOSBinFormatMachO() ||
TT.isOSBinFormatCOFF()) &&
"Only expect Darwin, ELF and COFF targets");
if (CM == CodeModel::Default)
CM = CodeModel::Small;
@ -122,6 +126,14 @@ static MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
/*LabelSections*/ true);
}
static MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll,
bool IncrementalLinkerCompatible) {
return createAArch64WinCOFFStreamer(Ctx, TAB, OS, Emitter, RelaxAll,
IncrementalLinkerCompatible);
}
static MCInstrAnalysis *createAArch64InstrAnalysis(const MCInstrInfo *Info) {
return new MCInstrAnalysis(Info);
}
@ -154,6 +166,7 @@ extern "C" void LLVMInitializeAArch64TargetMC() {
// Register the obj streamers.
TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
TargetRegistry::RegisterMachOStreamer(*T, createMachOStreamer);
TargetRegistry::RegisterCOFFStreamer(*T, createWinCOFFStreamer);
// Register the obj target streamer.
TargetRegistry::RegisterObjectTargetStreamer(

View File

@ -60,6 +60,8 @@ MCObjectWriter *createAArch64MachObjectWriter(raw_pwrite_stream &OS,
uint32_t CPUType,
uint32_t CPUSubtype);
MCObjectWriter *createAArch64WinCOFFObjectWriter(raw_pwrite_stream &OS);
MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S,
formatted_raw_ostream &OS,
MCInstPrinter *InstPrint,

View File

@ -0,0 +1,65 @@
//= AArch64WinCOFFObjectWriter.cpp - AArch64 Windows COFF Object Writer C++ =//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
#include "MCTargetDesc/AArch64FixupKinds.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCWinCOFFObjectWriter.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace llvm;
namespace {
class AArch64WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
public:
AArch64WinCOFFObjectWriter()
: MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARM64) {
}
~AArch64WinCOFFObjectWriter() override = default;
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsCrossSection,
const MCAsmBackend &MAB) const override;
bool recordRelocation(const MCFixup &) const override;
};
} // end anonymous namespace
unsigned
AArch64WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
const MCValue &Target,
const MCFixup &Fixup,
bool IsCrossSection,
const MCAsmBackend &MAB) const {
const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind());
report_fatal_error(Twine("unsupported relocation type: ") + Info.Name);
}
bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {
return true;
}
namespace llvm {
MCObjectWriter *createAArch64WinCOFFObjectWriter(raw_pwrite_stream &OS) {
MCWinCOFFObjectTargetWriter *MOTW = new AArch64WinCOFFObjectWriter();
return createWinCOFFObjectWriter(MOTW, OS);
}
} // end namespace llvm

View File

@ -0,0 +1,37 @@
//===-- AArch64WinCOFFStreamer.cpp - ARM Target WinCOFF Streamer ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "AArch64WinCOFFStreamer.h"
using namespace llvm;
namespace {
class AArch64WinCOFFStreamer : public MCWinCOFFStreamer {
public:
friend class AArch64TargetWinCOFFStreamer;
AArch64WinCOFFStreamer(MCContext &C, MCAsmBackend &AB, MCCodeEmitter &CE,
raw_pwrite_stream &OS)
: MCWinCOFFStreamer(C, AB, CE, OS) {}
};
} // end anonymous namespace
namespace llvm {
MCWinCOFFStreamer
*createAArch64WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll,
bool IncrementalLinkerCompatible) {
auto *S = new AArch64WinCOFFStreamer(Context, MAB, *Emitter, OS);
S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
return S;
}
} // end llvm namespace

View File

@ -0,0 +1,43 @@
//===-- AArch64WinCOFFStreamer.h - WinCOFF Streamer for AArch64 -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements WinCOFF streamer information for the AArch64 backend.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64WINCOFFSTREAMER_H
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64WINCOFFSTREAMER_H
#include "AArch64TargetStreamer.h"
#include "llvm/MC/MCWinCOFFStreamer.h"
namespace {
class AArch64WinCOFFStreamer;
class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
private:
AArch64WinCOFFStreamer &getStreamer();
public:
AArch64TargetWinCOFFStreamer(llvm::MCStreamer &S)
: AArch64TargetStreamer(S) {}
};
} // end anonymous namespace
namespace llvm {
MCWinCOFFStreamer
*createAArch64WinCOFFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll,
bool IncrementalLinkerCompatible);
} // end llvm namespace
#endif

View File

@ -8,6 +8,8 @@ add_llvm_library(LLVMAArch64Desc
AArch64MCTargetDesc.cpp
AArch64MachObjectWriter.cpp
AArch64TargetStreamer.cpp
AArch64WinCOFFObjectWriter.cpp
AArch64WinCOFFStreamer.cpp
)
add_dependencies(LLVMAArch64Desc AArch64CommonTableGen)

View File

@ -0,0 +1,8 @@
; RUN: llc -mtriple aarch64-windows < %s | FileCheck %s
define i32 @foo() {
entry:
ret i32 1
}
; CHECK: .globl foo