mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
[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:
parent
a4799adf39
commit
85e0946267
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -100,3 +100,7 @@ AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) {
|
||||
|
||||
HasIdentDirective = true;
|
||||
}
|
||||
|
||||
AArch64MCAsmInfoCOFF::AArch64MCAsmInfoCOFF() {
|
||||
CommentString = ";";
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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
|
37
lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
Normal file
37
lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
Normal 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
|
43
lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.h
Normal file
43
lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.h
Normal 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
|
@ -8,6 +8,8 @@ add_llvm_library(LLVMAArch64Desc
|
||||
AArch64MCTargetDesc.cpp
|
||||
AArch64MachObjectWriter.cpp
|
||||
AArch64TargetStreamer.cpp
|
||||
AArch64WinCOFFObjectWriter.cpp
|
||||
AArch64WinCOFFStreamer.cpp
|
||||
)
|
||||
add_dependencies(LLVMAArch64Desc AArch64CommonTableGen)
|
||||
|
||||
|
8
test/MC/AArch64/coff-basic.ll
Normal file
8
test/MC/AArch64/coff-basic.ll
Normal file
@ -0,0 +1,8 @@
|
||||
; RUN: llc -mtriple aarch64-windows < %s | FileCheck %s
|
||||
|
||||
define i32 @foo() {
|
||||
entry:
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
; CHECK: .globl foo
|
Loading…
Reference in New Issue
Block a user